在仔细查看源代码和在线文档后,我发现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"
,我的哈希值就开始使用一个基于机器密钥的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
属性。