How does RFC2898DeriveBytes generate an AES key?

余生长醉 提交于 2021-01-27 04:42:29

问题


I saw some code like

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

I can see the key is generated by Rfc2898DeriveBytes with passphrase and salt. Then AES retrieves the key by GetBytes.

But the question is, what does RFC2898DeriveBytes do and what key.GetBytes(cb) do? Could anyone elaborate this? I couldn't get it from the documentation.


回答1:


RFC2898 refers to a password-based cryptography specification published in September 2000. Effectively, Rfc2898DeriveBytes takes a password and salt to generate keys. The method it uses is known as PBKDF2 (Password Based Key Derivation Function #2) and is defined in section 5.2 of RFC2898. From section 5.2:

PBKDF2 applies a pseudorandom function (see Appendix B.1 for an example) to derive keys. The length of the derived key is essentially unbounded. (However, the maximum effective search space for the derived key may be limited by the structure of the underlying pseudorandom function. See Appendix B.1 for further discussion.) PBKDF2 is recommended for new applications.

For further details, see RFC2898.

As for what Rfc2898DeriveBytes.GetBytes does, it returns a different key on each invocation; it effectively just applies PBKDF2 repeatedly with the same password and salt but also an iteration count.

This is outlined in RFC doc where PBKDF2 is defined as

PBKDF2 (P, S, c, dkLen)

where P is the password, S is the salt, c is the iteration count and dkLen is the length of the desired key.

The RFCs are in general very interesting and historically quite important. RFC 1149 is quite important, as is RFC 2324.




回答2:


From looking at the implementation in 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;
}


来源:https://stackoverflow.com/questions/1937243/how-does-rfc2898derivebytes-generate-an-aes-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!