void ExpandKey(byte[] key, byte[] salt, EksBlowfishKeyExpansionFlags flags) { uint[] p = P; uint[][] s = S; int i, j, k; uint data, datal, datar; j = 0; for (i = 0; i < p.Length; i++) { data = 0x00000000; for (k = 0; k < 4; k++) { if ((flags & EksBlowfishKeyExpansionFlags.EmulateCryptBlowfishSignExtensionBug) != 0) { data = (data << 8) | (uint)(int)(sbyte)key[j]; } else { data = (data << 8) | key[j]; } j = (j + 1) % key.Length; } p[i] = p[i] ^ data; } uint saltL0 = BitPacking.UInt32FromBEBytes(salt, 0); uint saltR0 = BitPacking.UInt32FromBEBytes(salt, 4); uint saltL1 = BitPacking.UInt32FromBEBytes(salt, 8); uint saltR1 = BitPacking.UInt32FromBEBytes(salt, 12); datal = 0x00000000; datar = 0x00000000; for (i = 0; i < p.Length; i += 4) { datal ^= saltL0; datar ^= saltR0; Encipher(ref datal, ref datar); p[i + 0] = datal; p[i + 1] = datar; if (i + 2 == p.Length) { break; } // 18 here datal ^= saltL1; datar ^= saltR1; Encipher(ref datal, ref datar); p[i + 2] = datal; p[i + 3] = datar; } for (i = 0; i < s.Length; i++) { uint[] sb = s[i]; for (j = 0; j < sb.Length; j += 4) { datal ^= saltL1; datar ^= saltR1; Encipher(ref datal, ref datar); sb[j + 0] = datal; sb[j + 1] = datar; datal ^= saltL0; datar ^= saltR0; Encipher(ref datal, ref datar); sb[j + 2] = datal; sb[j + 3] = datar; } } }
/// <summary> /// Uses the given key, salt, and cost to generate a BCrypt hash. /// Flags may modify the key expansion. /// </summary> /// <param name="key"> /// The key. This must be between 1 and 72 bytes. /// Unlike <see cref="BlowfishCrypter"/>, this method does NOT automatically add a null byte to the key. /// </param> /// <param name="salt">The salt. This must be 16 bytes.</param> /// <param name="cost"> /// The expansion cost. This is a value between 4 and 31, /// specifying the logarithm of the number of iterations. /// </param> /// <param name="flags">Flags modifying the key expansion.</param> /// <returns>A BCrypt hash.</returns> public static byte[] BCrypt(byte[] key, byte[] salt, int cost, EksBlowfishKeyExpansionFlags flags) { using (BlowfishCipher fish = CreateEks(key, salt, cost, flags)) { return(fish.BCrypt()); } }
/// <summary> /// Performs an Expensive Key Schedule (EKS) Blowfish key expansion and /// creates a Blowfish cipher using the result. Flags may modify the key expansion. /// </summary> /// <param name="key"> /// The key. This must be between 1 and 72 bytes. /// Unlike <see cref="BlowfishCrypter"/>, this method does NOT automatically add a null byte to the key. /// </param> /// <param name="salt">The salt. This must be 16 bytes.</param> /// <param name="cost"> /// The expansion cost. This is a value between 4 and 31, /// specifying the logarithm of the number of iterations. /// </param> /// <param name="flags">Flags modifying the key expansion.</param> /// <returns>A Blowfish cipher.</returns> public static BlowfishCipher CreateEks(byte[] key, byte[] salt, int cost, EksBlowfishKeyExpansionFlags flags) { Check.Length("key", key, 1, 72); Check.Length("salt", salt, 16, 16); Check.Range("cost", cost, 4, 31); BlowfishCipher fish = new BlowfishCipher(null, null); fish.ExpandKey(key, salt, flags); for (uint i = 1u << cost; i > 0; i--) { fish.ExpandKey(key, _zeroSalt, flags); fish.ExpandKey(salt, _zeroSalt, EksBlowfishKeyExpansionFlags.None); } return(fish); }
void ExpandKey(byte[] key, byte[] salt, EksBlowfishKeyExpansionFlags flags) { uint[] p = P; uint[][] s = S; int i, j, k; uint data, datal, datar; j = 0; for (i = 0; i < p.Length; i ++) { data = 0x00000000; for (k = 0; k < 4; k ++) { if ((flags & EksBlowfishKeyExpansionFlags.EmulateCryptBlowfishSignExtensionBug) != 0) { data = (data << 8) | (uint)(int)(sbyte)key[j]; } else { data = (data << 8) | key[j]; } if (++j >= key.Length) { j = 0; } } p[i] = p[i] ^ data; } uint saltL0 = BitPacking.UInt32FromBEBytes(salt, 0); uint saltR0 = BitPacking.UInt32FromBEBytes(salt, 4); uint saltL1 = BitPacking.UInt32FromBEBytes(salt, 8); uint saltR1 = BitPacking.UInt32FromBEBytes(salt, 12); datal = 0x00000000; datar = 0x00000000; for (i = 0; i < p.Length; i += 4) { datal ^= saltL0; datar ^= saltR0; Encipher(ref datal, ref datar); p[i + 0] = datal; p[i + 1] = datar; if (i + 2 == p.Length) { break; } // 18 here datal ^= saltL1; datar ^= saltR1; Encipher(ref datal, ref datar); p[i + 2] = datal; p[i + 3] = datar; } for (i = 0; i < s.Length; i ++) { uint[] sb = s[i]; for (j = 0; j < sb.Length; j += 4) { datal ^= saltL1; datar ^= saltR1; Encipher(ref datal, ref datar); sb[j + 0] = datal; sb[j + 1] = datar; datal ^= saltL0; datar ^= saltR0; Encipher(ref datal, ref datar); sb[j + 2] = datal; sb[j + 3] = datar; } } }
/// <summary> /// Performs an Expensive Key Schedule (EKS) Blowfish key expansion and /// creates a Blowfish cipher using the result. Flags may modify the key expansion. /// </summary> /// <param name="key"> /// The key. This must be between 1 and 72 bytes. /// Unlike <see cref="BlowfishCrypter"/>, this method does NOT automatically add a null byte to the key. /// </param> /// <param name="salt">The salt. This must be 16 bytes.</param> /// <param name="cost"> /// The expansion cost. This is a value between 4 and 31, /// specifying the logarithm of the number of iterations. /// </param> /// <param name="flags">Flags modifying the key expansion.</param> /// <returns>A Blowfish cipher.</returns> public static BlowfishCipher CreateEks(byte[] key, byte[] salt, int cost, EksBlowfishKeyExpansionFlags flags) { Check.Length("key", key, 1, 72); Check.Length("salt", salt, 16, 16); Check.Range("cost", cost, 4, 31); BlowfishCipher fish = new BlowfishCipher(null, null); fish.ExpandKey(key, salt, flags); for (uint i = 1u << cost; i > 0; i --) { fish.ExpandKey(key, _zeroSalt, flags); fish.ExpandKey(salt, _zeroSalt, EksBlowfishKeyExpansionFlags.None); } return fish; }
/// <summary> /// Uses the given key, salt, and cost to generate a BCrypt hash. /// Flags may modify the key expansion. /// </summary> /// <param name="key"> /// The key. This must be between 1 and 72 bytes. /// Unlike <see cref="BlowfishCrypter"/>, this method does NOT automatically add a null byte to the key. /// </param> /// <param name="salt">The salt. This must be 16 bytes.</param> /// <param name="cost"> /// The expansion cost. This is a value between 4 and 31, /// specifying the logarithm of the number of iterations. /// </param> /// <param name="flags">Flags modifying the key expansion.</param> /// <returns>A BCrypt hash.</returns> public static byte[] BCrypt(byte[] key, byte[] salt, int cost, EksBlowfishKeyExpansionFlags flags) { using (BlowfishCipher fish = CreateEks(key, salt, cost, flags)) { return fish.BCrypt(); } }