SQL Server密码哈希算法:
hashBytes = 0x0100 | fourByteSalt | SHA1(utf16EncodedPassword+fourByteSalt)
例如,对密码进行哈希处理“正确的马电池主食”。首先我们生成一些随机盐:
fourByteSalt = 0x9A664D79;
然后将密码(以 UTF-16 编码)与盐一起进行哈希处理:
SHA1("correct horse battery staple" + 0x9A66D79);
=SHA1(0x63006F007200720065006300740020006200610074007400650072007900200068006F00720073006500200073007400610070006C006500 0x9A66D79)
=0x6EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
存储在的值syslogins
表是以下内容的串联:
[标头] + [盐] + [哈希值]
0x0100
9A664D79
6EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
您可以在 SQL Server 中看到:
SELECT
name, CAST(password AS varbinary(max)) AS PasswordHash
FROM sys.syslogins
WHERE name = 'sa'
name PasswordHash
==== ======================================================
sa 0x01009A664D796EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
- 版本标题:
0100
- 盐(四个字节):
9A664D79
- Hash:
6EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
(SHA-1 为 20 字节;160 位)
验证
您可以通过执行相同的哈希来验证密码:
- 从保存的盐中取出盐
PasswordHash
:0x9A664D79
并再次执行哈希:
SHA1("correct horse battery staple" + 0x9A66D79);
这将得出相同的哈希值,并且您知道密码是正确的。
曾经很好但现在很弱的东西
1999 年随 SQL Server 7 引入的哈希算法在 1999 年表现良好。
- 密码哈希加盐是件好事。
- 这是很好的append密码的盐,而不是prepend it.
但今天它已经过时了。它只运行哈希一次,它应该运行几千次,以阻止暴力攻击。
事实上,作为检查的一部分,Microsoft Baseline Security Analyzer 将尝试暴力破解密码。如果它猜到任何密码,它就会报告密码为弱密码。它确实得到了一些。
暴力破解
为了帮助您测试一些密码:
DECLARE @hash varbinary(max)
SET @hash = 0x01009A664D796EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
--Header: 0x0100
--Salt: 0x9A664D79
--Hash: 0x6EDB2FA35E3B8FAB4DBA2FFB62F5426B67FE54A3
DECLARE @password nvarchar(max)
SET @password = 'password'
SELECT
@password AS CandidatePassword,
@hash AS PasswordHash,
--Header
0x0100
+
--Salt
CONVERT(VARBINARY(4), SUBSTRING(CONVERT(NVARCHAR(MAX), @hash), 2, 2))
+
--SHA1 of Password + Salt
HASHBYTES('SHA1', @password + SUBSTRING(CONVERT(NVARCHAR(MAX), @hash), 2, 2))
SQL Server 2012 和 SHA-512
从 SQL Server 2012 开始,Microsoft 转而使用 SHA-2 512 位:
hashBytes = 0x0200 | fourByteSalt | SHA512(utf16EncodedPassword+fourByteSalt)
将版本前缀更改为0x0200
:
SELECT
name, CAST(password AS varbinary(max)) AS PasswordHash
FROM sys.syslogins
name PasswordHash
---- --------------------------------
xkcd 0x02006A80BA229556EB280AA7818FAF63A0DA8D6B7B120C6760F0EB0CB5BB320A961B04BD0836 0C0E8CC4C326220501147D6A9ABD2A006B33DEC99FCF1A822393FC66226B7D38
- 版本:
0200
(SHA-2 512 位)
- Salt:
6A80BA22
- 哈希值(64 字节):
9556EB280AA7818FAF63A0DA8D6B7B120C6760F0EB0CB5BB320A961B04BD0836 0C0E8CC4C326220501147D6A9ABD2A006B33DEC99FCF1A822393FC66226B7D38
这意味着我们对 UTF-16 编码的密码进行哈希处理,并带有盐后缀:
- SHA512(“正确的马电池主食”+
6A80BA22
)
- SHA512(
63006f0072007200650063007400200068006f0072007300650020006200610074007400650072007900200073007400610070006c006500
+ 6A80BA22
)
9556EB280AA7818FAF63A0DA8D6B7B120C6760F0EB0CB5BB320A961B04BD0836 0C0E8CC4C326220501147D6A9ABD2A006B33DEC99FCF1A822393FC66226B7D38