You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:17:25