【问题标题】:ASP.NET membership HashAlgorithmType defaults to HMACSHA256, so is password hash keyed?ASP.NET 成员 HashAlgorithmType 默认为 HMACSHA256,那么密码哈希键控吗?
【发布时间】:2015-12-14 17:37:05
【问题描述】:

我有一个使用 SqlMembershipProvider 的 ASP.NET 4.5 Web 应用程序。在开发过程中,有人将passwordFormat="Clear" 放入配置中,导致密码以明文形式保存。我想删除它并启用密码散列,但我想确保散列不是使用机器特定或自动生成的密钥生成的。

根据我在所有相关问答中阅读的内容,密码只是使用直接的 SHA256 进行哈希处理,而不是特定于机器或密钥的。但是,当我在运行时检查 Membership.HashAlgorithmType 时,它​​的值为“HMACSHA256”并且.NET HMACSHA256 class 需要一个密钥(因为它是 HMAC),如果没有提供给构造函数,则随机生成一个。因此,似乎必须涉及一个关键。那么会员密码哈希是否键控?如果是,我如何跨机器使用相同的密钥?支持您的回答的文件或证据将不胜感激。

编辑

根据this MSDN page on "Securing Membership",machineKey 元素确实控制哈希键:

强烈建议您使用设置为 Hashed 或 Encrypted 的 passwordFormat 属性对成员数据源中的用户密码进行加密,其中 Hashed 是最安全的格式。指定加密算法的加密密钥值存储在 machineKey 配置元素中。

但是,我尝试在 web.config 中设置机器密钥验证密钥,它仍然生成与设置之前相同的密码哈希,因此似乎没有任何效果。

我也一直在查看SqlMembershipProvider source code,据我所知,它确实使用了键控哈希。当然,这是 .Net 4.6.1 的来源,我正在运行 4.5。我已经复制了EncodePassword 源代码并对其进行了修改,以便它可以在控制台应用程序中运行,并且在我的控制台应用程序中,对于相同的密码和盐值,我仍然得到与 MembershipProvider 结果(在同一台机器上)不同的哈希值。

如果它使用随机密钥,您将无法验证密码。那么 SqlMembershipProvider 从哪里得到它的哈希键呢??

【问题讨论】:

    标签: c# asp.net hash asp.net-membership


    【解决方案1】:

    在对源代码和在线进行更多挖掘之后,我在 SO 上发现了一个问题,用户注意到他/她的 SQLMembershipProvider 哈希在数据库中只有 20 个字节。他们应该是 64 岁。我检查了我的,他们也是。我试图确定一个 SHA256 哈希如何最终只有 20 个字节,并得出结论它不能。所以在我的控制台应用程序中,我尝试只使用 SHA1 来完成它。我将其结果与SQLMembershipProvider 创建的哈希值进行了比较,果然,它匹配!我的 SQLMembershipProvider 使用 SHA1,即使 Membership.HashAlgorithmType 表示它设置为 .NET 4.0 默认值“HMACSHA256”。

    这是我阅读源代码的用武之地。我记得我从控制台应用程序中删除了一个条件部分,用于在创建哈希算法类时检查某些旧模式。

            private HashAlgorithm GetHashAlgorithm() {
            if (s_HashAlgorithm != null)
                return HashAlgorithm.Create(s_HashAlgorithm);
    
            string temp = Membership.HashAlgorithmType;
            if (_LegacyPasswordCompatibilityMode == MembershipPasswordCompatibilityMode.Framework20 &&
                !Membership.IsHashAlgorithmFromMembershipConfig &&
                temp != "MD5")
            {
                temp = "SHA1";
            }
            HashAlgorithm hashAlgo = HashAlgorithm.Create(temp);
            if (hashAlgo == null)
                RuntimeConfig.GetAppConfig().Membership.ThrowHashAlgorithmException();
            s_HashAlgorithm = temp;
            return hashAlgo;
        }
    

    经过更多的挖掘,我确定_LegacyPasswordCompatibilityMode 是从名为passwordCompatMode 的配置属性中设置的,这属于SqlMembershipProvider,即使它没有出现在web.config 中的智能感知中。一旦我在 web.config 中的 SqlMembershipProvider 上明确设置了 passwordCompatMode="Framework40",我的哈希就开始使用带密钥的 HMACSHA256 哈希,其中密钥是 machineKey 的验证密钥。使用相同的验证密钥,我就能够从我的控制台应用程序中重现相同的哈希值。

    作为对问题的确认,当我删除passwordCompatMode="Framework40" 属性时,然后在调试器中检查SqlMembershipProvider 的实例,我可以看到:

    _LegacyPasswordCompatibilityMode = "Framework20"
    s_HashAlgorithm = "SHA1" (!!!)
    

    所以这就是疯狂的事情。 SqlMembershipProvider 上的 MSDN 文档指出:

    [passwordCompatMode] 的默认值为 Framework20。

    因此,除非您将这个晦涩的属性明确声明为 Framework40,否则 SqlMembershipProvider 会使用 SHA1,尽管 4.0 框架被宣传为升级到 HMACSHA256。很难找到推断密钥来自 machineKey 部分的文档......地狱甚至很难找到 4.0 使用 HMACSHA256,而不仅仅是 SHA256......但我没有看到其他任何地方说明这个属性是必需的。我想知道有多少开发人员认为他们使用的是更安全的 HMACSHA[X],而实际上他们仍然只使用 SHA1?希望这对人们有所帮助。

    编辑

    如果<membership> 元素没有显式声明hashAlgorithType,则上述情况为真。您可以在上面的 .NET 源代码中看到它会查找 !Membership.IsHashAlgorithmFromMembershipConfig,这表明它是否在 member 元素上找到了 hashAlgorithmType 属性。因此,如果您在配置中指定<membership ... hashAlgorithmType=[x]>,我相信它不需要SqlMembershipProvider 上的passwordCompatMode 属性。

    【讨论】:

    • 这太疯狂了......我们遇到了问题。我希望之前有一些明显的方法来注意到这一点
    猜你喜欢
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 2017-08-16
    相关资源
    最近更新 更多