ASP.NET会员资格的HashAlgorithmType默认为HMACSHA256,因此密码哈希是否有键值?

9
我有一个ASP.NET 4.5网络应用程序,使用SqlMembershipProvider。在开发过程中,有人在配置文件中放置了passwordFormat="Clear",导致密码以明文形式保存。我想删除此设置并启用密码散列,但我想确保哈希不是使用特定于机器或自动生成的密钥生成的。
根据我阅读所有相关的Q&A,密码仅使用直接的SHA256进行哈希,并且不是特定于机器或键入的。但是,当我在运行时检查Membership.HashAlgorithmType时,它的值为“HMACSHA256”,而.NET HMACSHA256 class需要一个密钥(因为它是HMAC),如果没有提供,则随机生成一个密钥。因此似乎必须涉及密钥。那么Membership密码哈希是否带有密钥?如果是,如何跨多台机器使用相同的密钥?将赞赏支持您答案的文档或证据。 编辑 根据"此 MSDN 页面关于“安全成员资格”的说明,machineKey 元素确实控制哈希密钥:

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

然而,我尝试在 web.config 中设置 machine key 验证密钥,但它仍生成与设置之前相同的密码哈希,因此似乎没有影响。
我也一直在研究 SqlMembershipProvider源代码,据我所知,它确实使用了键控哈希。当然,这是.Net 4.6.1的源代码,而我正在运行4.5。我复制了EncodePassword的源代码,并对其进行了修改,以便在控制台应用程序中运行,在我的控制台应用程序中,对于相同的密码和盐值,与MembershipProvider结果(在同一台机器上)仍然得到不同的哈希值。

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

1个回答

18

在仔细查看源代码和在线文档后,我发现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中显式设置了 SqlMembershipProviderpasswordCompatMode="Framework40",我的哈希值就开始使用一个基于机器密钥的validationKey作为密钥的 keyed HMACSHA256哈希算法。使用相同的validationKey,我随后能够在我的控制台应用程序中复制相同的哈希值。

作为问题确认,当我移除 passwordCompatMode="Framework40" 属性时,通过调试器检查 SqlMembershipProvider 的实例,可以看到:

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

所以这件事很疯狂。关于SqlMembershipProvider的MSDN文档声明:

(passwordCompatMode的)默认值为Framework20。

因此,除非您显式声明此晦涩属性为Framework40,否则SqlMembershipProvider将使用SHA1,尽管4.0 Framework被宣传为升级到HMACSHA256。已经很难找到暗示密钥来自machineKey部分的文档...甚至很难找到其他地方说明需要该属性的地方。我想知道有多少开发人员认为他们使用了更安全的HMACSHA[X],而实际上仍然只使用了SHA1?希望这能帮助大家。

编辑

以上内容是在<membership>元素未显式声明hashAlgorithType的情况下成立的。您可以在.NET源代码中看到它查找!Membership.IsHashAlgorithmFromMembershipConfig,这表明它是否在membership元素上找到了hashAlgorithmType属性。因此,如果您在配置中指定了<membership ... hashAlgorithmType=[x]>,我认为它不需要SqlMembershipProvider上的passwordCompatMode属性。


这太疯狂了...我们遇到了这个问题。我希望以前有一些明显的方法可以注意到这个问题。 - samy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接