public static byte[] BCrypt(byte[] key, byte[] salt, int cost) { using (BlowfishCipher fish = CreateEks(key, salt, cost)) { return(fish.BCrypt()); } }
public static BlowfishCipher Create(byte[] key) { Helper.CheckRange("key", key, 4, 56); BlowfishCipher fish = new BlowfishCipher(); fish.ExpandKey(key, _zeroSalt); return(fish); }
public static BlowfishCipher CreateEks(byte[] key, byte[] salt, int cost) { Helper.CheckRange("key", key, 1, 72); Helper.CheckRange("salt", salt, 16, 16); Helper.CheckRange("cost", cost, 4, 31); BlowfishCipher fish = new BlowfishCipher(); fish.ExpandKey(key, salt); for (uint i = 1u << cost; i > 0; i--) { fish.ExpandKey(key, _zeroSalt); fish.ExpandKey(salt, _zeroSalt); } return(fish); }
public override string Crypt(byte[] key, string salt) { CheckKey(key); Helper.CheckNull("salt", salt); Match saltMatch = _regex.Match(salt); if (!saltMatch.Success) { throw new ArgumentException("Invalid salt.", "salt"); } int rounds = int.Parse(saltMatch.Groups[1].Value); if (rounds < 4 || rounds > 31) { throw new ArgumentException("Invalid number of rounds.", "salt"); } byte[] saltBytes = UnixBase64.Decode(saltMatch.Groups[2].Value, 128); bool resized = key.Length < MaxKeyLength; if (resized) { Array.Resize(ref key, key.Length + 1); } // The ending null terminator is vital for compatibility byte[] crypt = BlowfishCipher.BCrypt(key, saltBytes, rounds); string result = string.Format("$2a${0}${1}{2}", rounds.ToString("00"), new string(UnixBase64.Encode(saltBytes)), new string(UnixBase64.Encode(crypt))); Array.Clear(crypt, 0, crypt.Length); Array.Clear(saltBytes, 0, saltBytes.Length); if (resized) { Array.Clear(key, 0, key.Length); } // This is new since we resized it. return(result); }