Asp.net Identity 密码哈希

Posted

技术标签:

【中文标题】Asp.net Identity 密码哈希【英文标题】:Asp.net Identity password hashing 【发布时间】:2013-11-26 06:06:45 【问题描述】:

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

IPasswordHasher ASP.net Identity 中的接口

namespace Microsoft.AspNet.Identity

    public interface IPasswordHasher
    
         string HashPassword(string password);
         PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword);
    

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

【问题讨论】:

在你输入密码之前只需加盐即可。 string providedPassword 是否也需要散列? 虽然他们确实提供了使用您自己的哈希器的方法,但强烈推荐。此外,默认哈希器已经对密码进行了加盐处理,否则对相同的密码进行两次哈希处理会得到类似的结果。 【参考方案1】:

HEALTH WARNING 对于以下答案:知道您使用的是哪个版本的 ASP.Net Identity。如果它是来自 github 存储库的较新版本之一,您应该直接参考源代码。

在我写这篇文章时,密码处理程序的当前版本 (3.0.0-rc1/.../PasswordHasher.cs) 与以下答案有很大不同。这个较新的版本支持多个哈希算法版本,并记录为(并且在您阅读本文时可能会进一步更改):

版本 2:

带有 HMAC-SHA1、128 位盐、256 位子密钥、1000 次迭代的 PBKDF2。 (另请参见:SDL 加密指南 v5.1,第 III 部分) 格式: 0x00, salt, subkey

版本 3:

带有 HMAC-SHA256、128 位盐、256 位子密钥、10000 次迭代的 PBKDF2。 格式: 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey (所有 UInt32 都是大端存储的。)

原来的答案仍然有效对于原来的ASP.Net Identity版本,如下:


@jd4u 是正确的,但要阐明一些不适合他回答的评论:

Microsoft.AspNet.Identity.PasswordHasher : IPasswordHasher 已经给你加盐了, 更重要的是它使用Rfc2898DeriveBytes 来生成盐和哈希, 使用行业标准 PBKDF2 (SE discussion here, OWASP recommendation for PBKDF2 here)。 默认的Microsoft.AspNet.Identity.UserManager<TUser>实现使用Microsoft.AspNet.Identity.PasswordHasher作为具体的IPasswordHasher PasswordHasher 反过来是(最终)System.Security.Cryptography.Rfc2898DeriveBytes 的一个非常简单的包装器

所以,如果您要使用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);

【讨论】:

谢谢!!!我需要一种独立于用户管理器的新方法来创建我的散列密码,这非常有效 这是迄今为止我发现的最有用的解释,框架中嵌入了默认哈希,因此当我保存用户时,我只需执行此操作 var hash = new PasswordHasher().HashPassword(userViewModel.Password ); var userAggregate = UserAggregate.Create(userViewModel.Username, userViewModel.Email, hash, DateTime.Now.ToString()); vimeo.com/97530814 第 58 分钟,Troy Hunt 还说 1,000 次哈希迭代。 1) 将 32 字节输出与 PBKDF2-HMAC-SHA1 一起使用是个坏主意。输出超过本机大小(20 字节)会使防御者的速度减慢 2 倍,而完全不会减慢攻击者的速度。 2) 1000 次迭代,如果有点偏低。 这是它现在的样子github.com/aspnet/Identity/blob/…它与上面描述的github.com/aspnet/Identity/commit/…有所不同【参考方案2】:

“是否可以使用密码加盐来实现更安全的加密 ASP.net Identity 和通过这个接口?”

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

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

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

See one example of such IPasswordHasher

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

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

【讨论】:

【参考方案3】:

我在从 Membership 更新到 AspNet.Identity 时遇到了问题。 Rfc2898 哈希与以前使用的不同。这是有充分理由的,但更改哈希值需要所有用户重置密码。作为一种解决方案,此自定义实现使其向后兼容:

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;
   

创建 UserManager 实例后,只需设置哈希:

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

代码抱怨 HashPasswordForStoringInConfigFile 方法已被弃用,但这很好,因为我们知道整个练习是为了摆脱旧技术。

【讨论】:

这很棒。我有同样的问题,我想将成千上万的用户从成员资格提供程序迁移到新的 ASP.Identity。我会试一试的。 这基本上也是我最终做的。我想指出您的构造函数名称不正确(应该是MyPasswordHasher(...)。对于我的实现,我还使用此处的一些示例在登录时更新了用户密码以使用新的哈希功能:asp.net/identity/overview/migrations/… 我已经修复了复制粘贴错误。 我正在尝试做同样的事情但没有成功。。VerifyHashedPassword 方法的第一个参数是指db 表AspNetUsers 列PasswordHash,对吗?我想从旧的会员栏目中加入什么?只有密码还是密码加盐?

以上是关于Asp.net Identity 密码哈希的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Identity 的默认密码哈希器 - 它是如何工作的,它是不是安全?

如何在 Asp.Net identity 2 中手动检查密码?

ASP.NET Identity 重置密码

ASP.NET Identity 重置密码

ASP.NET Identity 更改密码

ASP.NET Core Identity 系列之三