/// <summary> /// Hashes the specified data bytes. /// </summary> /// <param name="hashData">The hash data.</param> /// <returns> /// Hashed bytes /// </returns> protected override byte[] Hash(byte[] hashData) { using (var sha512 = CryptoAbstraction.CreateSHA512()) { return(sha512.ComputeHash(hashData)); } }
/// <summary> /// Applies the Bcrypt kdf to derive a key and iv from the passphrase, /// the key/iv are returned in the output variable. /// Ported from the SSHJ library. https://github.com/hierynomus/sshj /// </summary> /// <param name="password"></param> /// <param name="salt"></param> /// <param name="rounds"></param> /// <param name="output"></param> public void Pbkdf(byte[] password, byte[] salt, int rounds, byte[] output) { using (var sha512 = CryptoAbstraction.CreateSHA512()) { int nblocks = (output.Length + 31) / 32; byte[] hpass = sha512.ComputeHash(password); byte[] hsalt = new byte[64]; byte[] block_b = new byte[4]; byte[] outBytes = new byte[32]; byte[] tmp = new byte[32]; for (int block = 1; block <= nblocks; block++) { // Block count is in big endian block_b[0] = (byte)((block >> 24) & 0xFF); block_b[1] = (byte)((block >> 16) & 0xFF); block_b[2] = (byte)((block >> 8) & 0xFF); block_b[3] = (byte)(block & 0xFF); hsalt = sha512.ComputeHash(AppendArrays(salt, block_b)); Hash(hpass, hsalt, outBytes); Array.Copy(outBytes, 0, tmp, 0, outBytes.Length); for (int round = 1; round < rounds; round++) { hsalt = sha512.ComputeHash(tmp); Hash(hpass, hsalt, tmp); for (int i = 0; i < tmp.Length; i++) { outBytes[i] ^= tmp[i]; } } for (int i = 0; i < outBytes.Length; i++) { int idx = i * nblocks + (block - 1); if (idx < output.Length) { output[idx] = outBytes[i]; } } } } }