¿Versión C # del método OpenSSL EVP_BytesToKey?

Estoy buscando la implementación directa de .NET de la función OpenSSL EVP_BytesToKey . Lo más parecido que he encontrado es la clase System.Security.Cryptography.PasswordDeriveBytes (y Rfc2898DeriveBytes ), pero parece ser ligeramente diferente y no genera la misma clave y iv como EVP_BytesToKey.

También encontré esta implementación que parece un buen comienzo pero no tiene en cuenta el recuento de iteraciones.

Me doy cuenta de que hay OpenSSL.NET, pero es solo una envoltura alrededor de las DLL nativas de openssl, no una implementación de .NET “real”.

Encontré esta explicación de pseudocódigo del método EVP_BytesToKey (en /doc/ssleay.txt de la fuente de openssl):

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

Así que, basado en eso, pude llegar a este método C # (que parece funcionar para mis propósitos y asume una clave de 32 bytes y iv de 16 bytes):

 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); } 

ACTUALIZACIÓN : Aquí hay más / menos la misma implementación, pero usa la interfaz .NET DeriveBytes: https://gist.github.com/1339719


OpenSSL 1.1.0c cambió el algoritmo de resumen utilizado en algunos componentes internos. Anteriormente, se usaba MD5 y 1.1.0 cambiaba a SHA256. Tenga cuidado de que el cambio no le afecte tanto en EVP_BytesToKey como en comandos como openssl enc .