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

查看:91
本文介绍了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.

推荐答案

我发现这个伪代码ex计划 EVP_BytesToKey 方法(在 / doc / ssleay.txt

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天全站免登陆