.NET:PasswordDeriveBytes和Rfc2898DeriveBytes之间的区别

我正在尝试理解一些C#代码,我已经处理了密码学,并且特别使用了System.Security.Cryptography PasswordDeriveBytes

在.NET文档中 ,它说PasswordDeriveBytes使用“PBKDF1算法的扩展”,后面在指定为“PKCS#5 v2.0标准”的文档中,这是PBKDF2(据我所知)。 我发现网上的任何地方(包括这里的Stack Exchange),但每个人都说“使用Rfc2898DeriveBytes,导致密码*被弃用并使用PBKDF1”。 但msdn.microsoft.com上文档的唯一区别似乎是Rfc * -version特别提到了PBKDF2,其中Password *表示“PBKDF1的扩展”和“PKCS#5 v 2.0”。

那么,任何人都可以告诉我两个类之间的区别(如果有的话)以及为什么我应该使用一个而不是另一个用于PBKDF2密码密钥推导?

现在,处理相同数据的其他代码明确使用PBKDF2,并且可以工作,因此这表明PasswordDeriveBytes确实也使用PBKDF2,或者在某些情况下PBKDF2只与PBKDF1兼容,但我想确切地知道这不是一些随机事物的副作用,并且事情只是神奇地起作用(并且最终可能会神奇地和惊人地突破)而没有人真正理解为什么。

我想在这里可以找到一个很好的答案:

C#PasswordDeriveBytes混淆

但总结一下:

微软对原始PKCS#5(又名PBKDF1)的实现包括不安全的扩展,以提供比散列函数所能提供的更多字节(参见此处和此处的错误报告)。

即使它没有错误,你应该避免未经证实的专有标准扩展(或者你将来可能永远无法解密你的数据 – 至少不在Windows之外。)

我强烈建议您使用较新的Rfc2898DeriveBytes,它实现了自.NET 2.0以来可用的PBKDF2(PKCS#5 v2)。

如果您实例化PasswordDeriveBytes并对GetBytes方法进行一次调用,并传递一个小于底层摘要算法输出大小的值,那么您将从PBKDF1算法中获取一个值。

如果对同一对象进行两次GetBytes调用,则可能会在实现中遇到计数错误。

PBKDF1仅被描述为输出最大哈希算法的大小(例如,SHA-1为20个字节),但PasswordDeriveBytes类已构成一个公式,以支持哈希输出大小的1000倍。 因此,在这个类中产生的大值可能不容易在另一个平台中实现。


如果您实例化Rfc2898DeriveBytes您将获得PBKDF2算法的流实现。 PBKDF2与PBKDF1最明显的区别在于PBKDF2允许生成任意数量的数据(限制为(2^32-1)*hashOutputSize ;或者对于SHA-1 85,899,345,900字节)。 PBKDF2还使用更复杂的结构(特别是HMAC而不是直接摘要)来使输出密码从输出值恢复更加困难。

实现中的“流”是GetBytes(5)GetBytes(3)的串联与GetBytes(8)相同。 与PasswordDeriveBytes不同,这在Rfc2898DeriveBytes中正常工作。


PBKDF1最初是为了生成DES密钥而创建的,在1993年PKCS#5 v1.5中发布.PBKDF2于1999年在PKCS#5 v2.0(重新发布为RFC2898 )中发布。幻灯片应位于ftp: //ftp.rsasecurity.com/pub/pkcs/pkcs-5v2/pkcs5v2-0.pdf (但似乎有问题所以ftp://ftp.dfn-cert.de/pub/pca/docs/PKCS/ftp .rsa.com / 99workshop / pkcs5_v2.0.ppt可能会这样做)进一步总结差异。 (幻灯片由RSA Security编写,是PBKDF1和PBKDF2的创建者,他们是推荐PBKDF2超过PBKDF1的人)。

这是一篇博文,详细介绍了这些差异:

http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx

PBKDF2可用于生成任意长度的密钥,这对于基于密码的加密非常有用(它可以生成对称密码所需的任何密钥长度),但对于安全密码存储意味着更少。 它还使用HMAC而不是像PBKDF1那样的连接来应用盐,这在弱盐的情况下具有更好的安全性。

PKCS#5 v2.0定义了PBKDF1和PBKDF2,前者出于向后兼容的原因,并建议您将PBKDF2用于新应用程序。 我不知道为什么后者比前者更好,但是这两个.NET类似乎确实使用了不同但可互操作的算法。 (可能是因为只交换了生成的密钥,而不是输入+ KDF。)