为何SHA-1哈希长度非28或40字符?SqlMembershipProvider疑问
我在ASP.NET项目中使用SqlMembershipProvider进行用户与密码管理,因特定需求尝试复现该系统的加盐哈希方法。经查找得到一段算法:将盐值附加到密码后,执行以下代码:
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1"); byte[] inArray = algorithm.ComputeHash(passPlusSalt); return Convert.ToBase64String(inArray);
该代码生成的加密字符串与系统输出一致,长度为28字符——因采用Base64编码:160位 / 6位 = 26.66,Base64会向上取整至4的下一个倍数28。
但系统中存在正常使用的账号,其加密密码长度为44字符或64字符。我原本以为是十六进制编码,但实际并非如此——它们使用相同的字符集(即A-Z、a-z、0-9、+,末尾带=,样本量较小暂未发现/)。我推测是不同编码方式,但不敢贸然发布无法确保有效的修改。
请问如何将160位SHA-1哈希扩展为44字节或64字节?在同时存储28字节字符串的系统中这是如何实现的?
若加密系统同时存储28、44、64字节的哈希,是否意味着它(随机?)使用不同的哈希算法?若并非随机,SqlMembershipProvider依据什么选择哈希算法?
问题解答
哈希长度对应的算法逻辑
- 28字符Base64:对应160位(20字节)的SHA-1哈希,和你复现的逻辑完全一致。
- 44字符Base64:对应256位(32字节)的哈希,这是SHA-256的输出结果,Base64编码后因补位规则长度为44。
- 64字符Base64:对应384位(48字节)的哈希,即SHA-384的输出,Base64编码后刚好为64字符无补位。
不存在安全的“将SHA-1哈希扩展为更长长度”的方式——不同长度的哈希本质是使用了不同的哈希算法,而非对原有哈希的扩展。
SqlMembershipProvider的算法选择规则
它不会随机选择算法,而是完全依赖配置文件中的两个参数:passwordFormat:当设置为Hashed时,才会启用哈希加密;若为Encrypted或Clear则对应其他存储方式。hashAlgorithmType:指定具体哈希算法名称,默认是SHA1,可配置为SHA256、SHA384等标准哈希算法。
系统中存在多种长度哈希,大概率是因为不同阶段修改过配置:老用户在配置变更前创建,使用SHA1;新用户则使用更新后的SHA256/SHA384算法,最终导致数据库中并存多种哈希值。
多哈希共存的验证逻辑
SqlMembershipProvider验证密码时,会读取用户记录的盐值和哈希值,通过哈希值的长度反推对应的算法(默认表结构无单独算法标识字段,靠长度判断),再用对应算法重新计算哈希并与存储值比对,从而兼容不同时期的哈希结果。
内容的提问来源于stack exchange,提问作者AndrewS

