ASP.NET成员HashAlgorithmType默认为HMACSHA256,密码哈希键也是如此

本文关键字:哈希键 密码 HMACSHA256 成员 NET HashAlgorithmType 默认 ASP | 更新日期: 2023-09-27 18:26:42

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

根据我在所有相关问答上读到的内容;A、 密码只是使用直接的SHA256进行散列,并且不是机器特定的或键控的。但是,当我在运行时检查Membership.HashAlgorithmType时,它的值是"HMACSHA256",并且.NET HMACSHA256类需要一个密钥(因为它是HMAC),如果没有向构造函数提供密钥,则会随机生成一个密钥。看来这里面一定有一把钥匙。那么,会员密码散列是否有密钥?如果是,我如何在机器之间使用相同的密钥?支持您回答的文件或证据将不胜感激。

编辑

根据MSDN上的"安全成员身份"页面,machineKey元素确实控制散列密钥:

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

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

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

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

ASP.NET成员HashAlgorithmType默认为HMACSHA256,密码哈希键也是如此

在对源代码和在线进行更多挖掘后,我在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中的intellisense中显示。一旦我在web.config的SqlMembershipProvider上显式设置了passwordCompatMode="Framework40",我的哈希就开始使用一个带密钥的HMACSHA256哈希,其中密钥是machineKey的validationKey。使用相同的验证密钥,我就可以从控制台应用程序中复制相同的哈希。

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

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

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

[密码CompatMode]的默认值是Framework20。

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

编辑

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