35

新的 ASP.net Identity 项目为网站安全带来了一些有用的代码和接口。要使用接口实现自定义系统(而不是使用 MVC 5 模板中包含的标准实体框架实现),IPasswordHasher需要一个。

IPasswordHasherASP.net Identity 中的接口

namespace Microsoft.AspNet.Identity
{
    public interface IPasswordHasher
    {
         string HashPassword(string password);
         PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword);
    }
}

是否可以使用密码加盐在 ASP.net Identity 中和通过此接口进行更安全的加密?

4

3 回答 3

59

以下答案的健康警告:知道您使用的是哪个版本的 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);
于 2014-02-01T09:19:59.473 回答
34

“是否可以使用密码加盐在 ASP.net Identity 中和通过此界面进行更安全的加密?”

是的,该接口是为 Core 框架中已经存在的 PasswordHasher 的新实现提供的。

另请注意,默认实现已经在使用 Salt+Bytes。

创建自定义PasswordHasher(例如MyPasswordHasher)后,您可以将其分配给 UserManager 实例,例如userManager.PasswordHasher=new MyPasswordHasher()

查看此类 IPasswordHasher 的一个示例

要使用接口实现自定义系统(而不是使用 MVC 5 模板中包含的标准实体框架实现),需要 IPasswordHasher。

为了从 EF 实现替代系统,您应实现所有核心接口。- 不需要 IPasswordHasher 实现。核心框架中已经提供了 PasswordHasher 作为它的实现。

于 2013-11-13T19:13:08.560 回答
9

I ran into an issue while updating from Membership to AspNet.Identity. The Rfc2898 hashes are different from those used before. That's for good reason, but changing the hashes would require all users to reset their passwords. As a solution this custom implementation makes it backwards compatible:

public class MyPasswordHasher : PasswordHasher {

   public FormsAuthPasswordFormat FormsAuthPasswordFormat { get; set; }

   public MyPasswordHasher(FormsAuthPasswordFormat format) {
      FormsAuthPasswordFormat = format;
   }

   public override string HashPassword(string password) {
      return FormsAuthentication.HashPasswordForStoringInConfigFile(password, FormsAuthPasswordFormat.ToString());
   }

   public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) {
     var testHash = FormsAuthentication.HashPasswordForStoringInConfigFile(providedPassword, FormsAuthPasswordFormat.ToString());
     return hashedPassword.Equals(testHash) ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
   }
}

Once you create your UserManager instance just set the hasher:

Usermanager.PasswordHasher = new MyPasswordHasher(FormsAuthPasswordFormat.SHA1);

The code complains that the HashPasswordForStoringInConfigFile method is deprecated, but that's fine as we know that the whole exercise is to get rid of the old technology.

于 2014-07-09T09:30:32.007 回答