RFC2898DeriveBytes 如何生成 AES 密钥?

发布于 2024-08-15 23:37:55 字数 403 浏览 4 评论 0原文

我看到了一些代码,就像

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) 是做什么的?有人能详细说明一下吗?我无法从文档中获取它。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烂人 2024-08-22 23:37:55

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

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

有关更多详细信息,请参阅 RFC2898

至于 Rfc2898DeriveBytes.GetBytes 的作用,它在每次调用时返回一个不同的密钥;它实际上只是使用相同的密码和盐以及迭代计数重复应用 PBKDF2。

RFC 文档中对此进行了概述,其中 PBKDF2 定义为

PBKDF2 (P, S, c, dkLen)

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

RFC 总的来说非常有趣,并且在历史上非常重要。 RFC 1149 非常重要,RFC 2324

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.

一个人的旅程 2024-08-22 23:37:55

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

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文