以下答案的健康警告:知道您使用的是哪个版本的 ASP.Net Identity。如果它是来自 github 存储库的较新版本之一,您应该直接参考源代码。
在我写这篇文章时,密码处理程序的当前版本(3.0.0-rc1/.../PasswordHasher.cs)与以下答案有很大不同。这个较新的版本支持多个哈希算法版本,并记录为(并且在您阅读本文时可能会进一步更改):
版本 2:
- 带有 HMAC-SHA1 的 PBKDF2,128 位盐,256 位子密钥,1000 次迭代。
- (另请参阅:SDL 加密指南 v5.1,第三部分)
- 格式:
{ 0x00, salt, subkey }
版本 3:
- 带有 HMAC-SHA256 的 PBKDF2,128 位盐,256 位子密钥,10000 次迭代。
- 格式:
{ 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
- (所有 UInt32 都是大端存储的。)
原始答案对原始版本的 ASP.Net Identity仍然有效,如下所示:
@jd4u 是正确的,但要阐明一点,这不适合对他的回答发表评论:
因此,如果您要使用Rfc2898DeriveBytes
,只需使用PasswordHasher
- 所有繁重的工作已经为您完成(希望是正确的)。
细节
PasswordHasher(当前)最终使用的完整代码非常接近:
int saltSize = 16;
int bytesRequired = 32;
byte[] array = new byte[1 + saltSize + bytesRequired];
int iterations = SOME; // 1000, afaik, which is the min recommended for Rfc2898DeriveBytes
using (var pbkdf2 = new Rfc2898DeriveBytes(password, saltSize, iterations))
{
byte[] salt = pbkdf2.Salt;
Buffer.BlockCopy(salt, 0, array, 1, saltSize);
byte[] bytes = pbkdf2.GetBytes(bytesRequired);
Buffer.BlockCopy(bytes, 0, array, saltSize+1, bytesRequired);
}
return Convert.ToBase64String(array);