C# 版本的 OpenSSL EVP_BytesToKey 方法? [英] C# version of OpenSSL EVP_BytesToKey method?

查看:19
本文介绍了C# 版本的 OpenSSL EVP_BytesToKey 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm looking for straight-up .NET implementation of the OpenSSL EVP_BytesToKey function. The closest thing I've found is the System.Security.Cryptography.PasswordDeriveBytes class (and Rfc2898DeriveBytes) but it seems to be slightly different and doesn't generate the same key and iv as EVP_BytesToKey.

我还发现了这个实施,这似乎是一个好的开始但不考虑迭代次数.

I also found this implementation which seems like a good start but doesn't take into account iteration count.

我意识到有 OpenSSL.NET,但它只是原生 openssl DLL 的包装,而不是真正的".NET 实现.

I realize there's OpenSSL.NET but it's just a wrapper around the native openssl DLLs not a "real" .NET implementation.

推荐答案

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

I found this pseudo-code explanation of the EVP_BytesToKey method (in /doc/ssleay.txt of the openssl source):

/* 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] .......

因此,基于此,我能够想出这个 C# 方法(这似乎对我有用,并假设 32 字节的密钥和 16 字节的 iv):

So based on that I was able to come up with this C# method (which seems to work for my purposes and assumes 32-byte key and 16-byte iv):

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

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

UPDATE: Here's more/less the same implementation but uses the .NET DeriveBytes interface: https://gist.github.com/1339719

OpenSSL 1.1.0c 更改了一些内部组件中使用的摘要算法.以前用的是MD5,1.1.0改用SHA256.请注意,更改不会影响 EVP_BytesToKey 和诸如 openssl enc 之类的命令.

OpenSSL 1.1.0c changed the digest algorithm used in some internal components. Formerly, MD5 was used, and 1.1.0 switched to SHA256. Be careful the change is not affecting you in both EVP_BytesToKey and commands like openssl enc.

这篇关于C# 版本的 OpenSSL EVP_BytesToKey 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆