我正在尝试理解一些C#代码,我已经处理了密码学,并专门使用PasswordDeriveBytes
中的System.Security.Cryptography
。
在.NET docs中,它表示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兼容,但是我想确切地知道这不是一些随机事物的副作用,并且事情只是神奇地起作用(最终可能会神奇地和惊人地突破)而没有人真正理解为什么。
答案 0 :(得分:2)
我认为可以在这里找到一个很好的答案:
C# PasswordDeriveBytes Confusion
但要总结:
Microsoft对原始PKCS#5(又名PBKDF1)的实现包括不安全的扩展,以提供比哈希函数提供的更多字节(请参阅此处和此处的错误报告)。
即使它没有错误,你也应该避免对标准进行无证的专有扩展(或者你将来可能永远无法解密数据 - 至少不能在Windows之外解密。)
我强烈建议您使用较新的Rfc2898DeriveBytes,它实现了自.NET 2.0以来可用的PBKDF2(PKCS#5 v2)。
答案 1 :(得分:2)
如果您实例化PasswordDeriveBytes
并对GetBytes
方法进行单次调用,并传递一个小于基础摘要算法输出大小的值,那么您将从{{3算法。
如果对同一个对象进行两次GetBytes调用,则可能会在实现中遇到计数错误。
PBKDF1仅被描述为输出最大哈希算法的大小(例如,SHA-1的20个字节),但PasswordDeriveBytes类已构成一个公式,以支持哈希输出大小的1000倍。因此,在另一个平台上,这个类产生的巨大价值可能并不容易实现。
如果您实例化Rfc2898DeriveBytes
,则会获得PBKDF1算法的流式实施。 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年在PBKDF2中发布。 PBKDF2于1999年在PKCS#5 v2.0(重新发布为PKCS #5 v1.5)中发布。幻灯片应位于RFC2898(但似乎有问题ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-5v2/pkcs5v2-0.pdf可能会这样做)进一步总结差异。 (幻灯片由RSA Security编写,是PBKDF1和PBKDF2的创建者,他们是推荐PBKDF2超过PBKDF1的人。)
答案 2 :(得分:1)
这是一篇详细介绍差异的博客文章:
http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx
PBKDF2可用于生成任意长度的密钥,这对于基于密码的加密非常有用(它可以生成对称密码所需的任何密钥长度)但对于安全密码意味着更少存储。它也使用HMAC而不是像PBKDF1那样连接盐,在弱盐的情况下具有更好的安全性。
答案 3 :(得分:0)
PKCS#5 v2.0定义了PBKDF1和PBKDF2,前者出于向后兼容的原因而 建议您将PBKDF2用于新的应用程序。我不知道为什么后者比前者更好,但是这两个.NET类似乎确实使用了不同但可互操作的算法。 (可能是因为只交换了生成的密钥,而不是输入+ KDF。)