C#版本的OpenSSL EVP_BytesToKey方法?

我正在寻找OpenSSL EVP_BytesToKey函数的直接.NET实现。 我发现的最接近的是System.Security.Cryptography.PasswordDeriveBytes类(和Rfc2898DeriveBytes ),但它似乎略有不同 ,并且不生成与EVP_BytesToKey相同的密钥iv

我也发现这个实现似乎是一个好的开始,但没有考虑迭代计数。

我意识到有OpenSSL.NET,但它只是本机openssl DLL的包装,而不是“真正的”.NET实现。

我发现了EVP_BytesToKey方法的伪代码解释(在openssl源代码的/doc/ssleay.txt中):

/* M[] is an array of message digests * MD() is the message digest function */ M[0]=MD(data . salt); for (i=1; i 

所以基于此我能够提出这个C#方法(这似乎适用于我的目的并假设32字节密钥和16字节iv):

 private static void DeriveKeyAndIV(byte[] data, byte[] salt, int count, out byte[] key, out byte[] iv) { List hashList = new List(); byte[] currentHash = new byte[0]; int preHashLength = data.Length + ((salt != null) ? salt.Length : 0); byte[] preHash = new byte[preHashLength]; System.Buffer.BlockCopy(data, 0, preHash, 0, data.Length); if (salt != null) System.Buffer.BlockCopy(salt, 0, preHash, data.Length, salt.Length); MD5 hash = MD5.Create(); currentHash = hash.ComputeHash(preHash); for (int i = 1; i < count; i++) { currentHash = hash.ComputeHash(currentHash); } hashList.AddRange(currentHash); while (hashList.Count < 48) // for 32-byte key and 16-byte iv { preHashLength = currentHash.Length + data.Length + ((salt != null) ? salt.Length : 0); preHash = new byte[preHashLength]; System.Buffer.BlockCopy(currentHash, 0, preHash, 0, currentHash.Length); System.Buffer.BlockCopy(data, 0, preHash, currentHash.Length, data.Length); if (salt != null) System.Buffer.BlockCopy(salt, 0, preHash, currentHash.Length + data.Length, salt.Length); currentHash = hash.ComputeHash(preHash); for (int i = 1; i < count; i++) { currentHash = hash.ComputeHash(currentHash); } hashList.AddRange(currentHash); } hash.Clear(); key = new byte[32]; iv = new byte[16]; hashList.CopyTo(0, key, 0, 32); hashList.CopyTo(32, iv, 0, 16); } 

更新 :这里有更多/更少相同的实现,但使用.NET DeriveBytes接口: https ://gist.github.com/1339719


OpenSSL 1.1.0c改变了一些内部组件中使用的摘要算法 。 以前使用MD5,1.1.0切换到SHA256。 请注意,在EVP_BytesToKeyopenssl enc等命令中,更改不会影响您。