我有一个使用SqlMembershipProvider
的ASP.NET 4.5 Web应用程序。在开发过程中,有人将passwordFormat="Clear"
放入配置中,导致密码以明文形式保存。我想删除它并启用密码哈希,但我想确保不使用机器特定的或自动生成的密钥生成哈希。
根据我在所有相关Q& A上阅读的内容,密码只使用直接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从哪里获取它的哈希键
答案 0 :(得分:14)
在对源代码和在线进行更多挖掘后,我在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
,即使它没有出现在intellisense中web.config。在我的web.config中passwordCompatMode="Framework40"
上明确设置SqlMembershipProvider
之后,我的哈希开始使用密钥HMACSHA256哈希,其中密钥是machineKey的validationKey。使用相同的验证密钥,我可以从我的控制台应用程序重现相同的哈希值。
作为问题的确认,当我删除passwordCompatMode="Framework40"
属性时,然后在调试器中检查SqlMembershipProvider
的实例,我可以看到:
_LegacyPasswordCompatibilityMode = "Framework20"
s_HashAlgorithm = "SHA1" (!!!)
所以这是疯狂的事情。 SqlMembershipProvider上的MSDN文档指出:
[passwordCompatMode]的默认值是Framework20。
因此,除非您将此隐藏属性显式声明为Framework40
,否则SqlMembershipProvider
使用SHA1,尽管4.0 Framework被宣传为升级到HMACSHA256。很难找到文件推断密钥来自machineKey部分......难道甚至很难发现4.0使用HMACSHA256,而不仅仅是SHA256 ...但我没有看到其他地方说明这个属性是需要。我想知道有多少开发人员在他们实际上仍然只使用SHA1时会使用更安全的HMACSHA [X]的印象?希望这有助于人们。
修改
如果<membership>
元素未明确声明hashAlgorithType
,则上述情况属实。您可以在上面的.NET源代码中看到它查找!Membership.IsHashAlgorithmFromMembershipConfig
,它指示它是否在成员资格元素上找到hashAlgorithmType
属性。因此,如果您在配置中指定<membership ... hashAlgorithmType=[x]>
,我相信它不需要SqlMembershipProvider上的passwordCompatMode
属性。