求基于SHA1的PBKDF2算法SQL实现方案(适配SQL 2008 R2及以下)
我刚好折腾过SQL Server 2008 R2下的PBKDF2-SHA1实现,之前也参考过anti-weakpasswords的SHA512版本,踩过同样的坑,给你整理了完整的可运行脚本,还有关键修改点的说明:
PBKDF2-SHA1 SQL Server 2008 R2 实现方案
关键适配修改点
针对SQL 2008 R2及以下版本,需要对SHA512版本的PBKDF2做以下核心调整:
- 摘要大小从64字节改为20字节(SHA1哈希输出固定长度)
- HMAC块大小从128字节改为64字节(SHA1对应的HMAC块大小标准)
- 密码长度检查阈值设为64字节:当原始密码长度超过64字节时,需要先对密码做SHA1哈希,再将哈希值作为HMAC的密钥(符合HMAC规范)
- 将所有
HASHBYTES('SHA512', ...)调用替换为HASHBYTES('SHA1', ...) - 异或展开循环次数调整为20次(对应20字节的摘要长度,每次处理1字节)
完整SQL函数实现
CREATE FUNCTION dbo.PBKDF2_SHA1 ( @Password NVARCHAR(4000), @Salt VARBINARY(MAX), @IterationCount INT, @OutputLength INT ) RETURNS VARBINARY(MAX) AS BEGIN DECLARE @HMACKey VARBINARY(MAX) DECLARE @BlockSize INT = 64 -- SHA1 HMAC block size DECLARE @HashSize INT = 20 -- SHA1 hash output size -- Handle password longer than HMAC block size: hash first per HMAC spec IF LEN(@Password) > @BlockSize SET @HMACKey = HASHBYTES('SHA1', @Password) ELSE SET @HMACKey = CAST(@Password AS VARBINARY(MAX)) -- Pad key to block size if shorter IF LEN(@HMACKey) < @BlockSize SET @HMACKey = @HMACKey + REPLICATE(0x00, @BlockSize - LEN(@HMACKey)) DECLARE @Output VARBINARY(MAX) = 0x DECLARE @BlockIndex INT = 1 WHILE LEN(@Output) < @OutputLength BEGIN -- Initial HMAC: Salt + BlockIndex (big-endian 4-byte integer) DECLARE @U VARBINARY(MAX) = HASHBYTES('SHA1', @HMACKey + @Salt + CAST(@BlockIndex AS VARBINARY(4))) DECLARE @T VARBINARY(MAX) = @U -- Iterate HMAC XOR rounds DECLARE @i INT = 1 WHILE @i < @IterationCount BEGIN SET @U = HASHBYTES('SHA1', @HMACKey + @U) -- XOR each byte of @U with @T DECLARE @xorIndex INT = 1 DECLARE @xorResult VARBINARY(MAX) = 0x WHILE @xorIndex <= @HashSize BEGIN SET @xorResult = @xorResult + CAST((SUBSTRING(@T, @xorIndex, 1) ^ SUBSTRING(@U, @xorIndex, 1)) AS VARBINARY(1)) SET @xorIndex = @xorIndex + 1 END SET @T = @xorResult SET @i = @i + 1 END -- Append block to output SET @Output = @Output + @T SET @BlockIndex = @BlockIndex + 1 END -- Trim to desired output length RETURN SUBSTRING(@Output, 1, @OutputLength) END GO
使用示例
-- 生成PBKDF2-SHA1哈希:密码"TestPassword",盐0x12345678,10000次迭代,输出32字节 SELECT dbo.PBKDF2_SHA1(N'TestPassword', 0x12345678, 10000, 32) AS PBKDF2_SHA1_Hash
注意事项
- 确保
@IterationCount不要设置过低,建议至少10000次(根据安全需求调整) @Salt建议使用至少16字节的随机值,避免彩虹表攻击- SQL Server 2008 R2中
HASHBYTES函数对NVARCHAR的处理是按UTF-16编码,和大多数编程语言的PBKDF2实现一致,不需要额外编码转换
内容的提问来源于stack exchange,提问作者Johannes Huber
相关产品推荐
相关产品推荐

