net example encrypt decrypt c# .net encryption openssl md5

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



nuget openssl net (1)

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<count; i++) M[0]=MD(M[0]); i=1 while (data still needed for key and iv) { M[i]=MD(M[i-1] . data . salt); for (i=1; i<count; i++) M[i]=MD(M[i]); i++; } If the salt is NULL, it is not used. The digests are concatenated together. M = M[0] . M[1] . M[2] .......

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<byte> hashList = new List<byte>(); 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 .