7

我看到了一些类似的代码

string password = "11111111";
byte[] salt = Encoding.ASCII.GetBytes("22222222");
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt);
RijndaelAlg.Key = key.GetBytes(RijndaelAlg.KeySize / 8);

我可以看到密钥是由带有密码和盐的 Rfc2898DeriveBytes 生成的。然后 AES 通过 GetBytes 检索密钥。

但问题是,RFC2898DeriveBytes 是做什么的,key.GetBytes(cb) 是做什么的?谁能详细说明一下?我无法从文档中得到它。

4

2 回答 2

12

RFC2898 指的是 2000 年 9 月发布的基于密码的加密规范。有效地,Rfc2898DeriveBytes使用密码和盐来生成密钥。它使用的方法称为 PBKDF2(基于密码的密钥派生函数 #2),并在 RFC2898 的第 5.2 节中定义。从第 5.2 节开始:

PBKDF2 应用伪随机函数(参见附录 B.1 中的示例)来派生密钥。派生密钥的长度基本上是无界的。(但是,派生密钥的最大有效搜索空间可能受到底层伪随机函数结构的限制。有关进一步讨论,请参见附录 B.1。)建议将 PBKDF2 用于新应用程序。

有关详细信息,请参阅RFC2898

至于做什么Rfc2898DeriveBytes.GetBytes,它在每次调用时返回一个不同的键;它有效地只是使用相同的密码和盐重复应用 PBKDF2,但还有一个迭代计数。

这在 RFC doc 中有概述,其中 PBKDF2 定义为

PBKDF2 (P, S, c, dkLen)

其中P是密码,S是盐,c是迭代次数,dkLen是所需密钥的长度。

RFC通常非常有趣并且在历史上非常重要。RFC 1149和RFC 2324一样非常重要。

于 2009-12-20T22:25:12.203 回答
5

通过查看 Reflector 中的实现:

public Rfc2898DeriveBytes(string password, byte[] salt) : this(password, salt, 0x3e8)
{
}

public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
{
    if (saltSize < 0)
    {
        throw new ArgumentOutOfRangeException("saltSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    }
    byte[] data = new byte[saltSize];
    Utils.StaticRandomNumberGenerator.GetBytes(data);
    this.Salt = data;
    this.IterationCount = iterations;
    this.m_hmacsha1 = new HMACSHA1(new UTF8Encoding(false).GetBytes(password));
    this.Initialize();
}


public override byte[] GetBytes(int cb)
{
    if (cb <= 0)
    {
        throw new ArgumentOutOfRangeException("cb", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
    }
    byte[] dst = new byte[cb];
    int dstOffset = 0;
    int count = this.m_endIndex - this.m_startIndex;
    if (count > 0)
    {
        if (cb < count)
        {
            Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, cb);
            this.m_startIndex += cb;
            return dst;
        }
        Buffer.InternalBlockCopy(this.m_buffer, this.m_startIndex, dst, 0, count);
        this.m_startIndex = this.m_endIndex = 0;
        dstOffset += count;
    }
    while (dstOffset < cb)
    {
        byte[] src = this.Func();
        int num3 = cb - dstOffset;
        if (num3 > 20)
        {
            Buffer.InternalBlockCopy(src, 0, dst, dstOffset, 20);
            dstOffset += 20;
        }
        else
        {
            Buffer.InternalBlockCopy(src, 0, dst, dstOffset, num3);
            dstOffset += num3;
            Buffer.InternalBlockCopy(src, num3, this.m_buffer, this.m_startIndex, 20 - num3);
            this.m_endIndex += 20 - num3;
            return dst;
        }
    }
    return dst;
}
于 2009-12-20T22:27:28.630 回答