Ich habe eine gespeicherte Hashing-Prozedur geschrieben, indem ich den C#-Code von hier aus zurückentwickelt habe ASP.NET Identity default Password Hasher, wie funktioniert es und ist es sicher? und einige fantastische PBKDF2-SQL-Funktionen von hier Gibt es eine SQL-Implementierung von PBKDF2?
Erstellen Sie zuerst diese beiden Funktionen aus Is there a SQL Implementierung von PBKDF2?
create FUNCTION [dbo].[fn_HMAC]
(
@hash_algorithm varchar(25),
@key VARCHAR(MAX),
@message VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
--HASH key if longer than 16 characters
IF(LEN(@key) >64)
SET @key = HASHBYTES(@hash_algorithm,@key)
DECLARE @i_key_pad VARCHAR(MAX), @o_key_pad VARCHAR(MAX), @position INT
SET @position = 1
SET @i_key_pad = ''
SET @o_key_pad = ''
--splice ipad & opod with key
WHILE @position <= LEN(@key)
BEGIN
SET @i_key_pad = @i_key_pad + CHAR(ASCII(SUBSTRING(@key, @position, 1)) ^ 54)
SET @o_key_pad = @o_key_pad + CHAR(ASCII(SUBSTRING(@key, @position, 1)) ^ 92)
SET @position = @position + 1
END
--pad i_key_pad & o_key_pad
SET @i_key_pad = LEFT(@i_key_pad + REPLICATE('6',64),64)
SET @o_key_pad = LEFT(@o_key_pad + REPLICATE('\',64),64)
RETURN HASHBYTES(@hash_algorithm,CONVERT(VARBINARY(MAX),@o_key_pad) + HASHBYTES(@hash_algorithm,@i_key_pad + @message))
END
GO
und
CREATE function [dbo].[fn_PBKDF2]
(
@hash_algorithm varchar(25),
@password varchar(max),
@salt varchar(max),
@rounds int,
@outputbytes int
)
returns varchar(max)
as
begin
declare @hlen int
select @hlen = len(HASHBYTES(@hash_algorithm, 'test'))
declare @l int
SET @l = (@outputbytes [email protected] -1)/@hLen
declare @r int
SET @r = @outputbytes - (@l - 1) * @hLen
declare @t varchar(max), @u varchar(max), @block1 varchar(max)
declare @output varchar(max)
SET @output = ''
declare @i int
SET @i = 1
while @i <= @l
begin
set @block1 = @salt +cast(cast(@i as varbinary(4)) as varchar(4))
set @u = dbo.fn_HMAC(@hash_algorithm,@password,@block1)
set @t = @u
declare @j int
SET @j = 1
while @j < @rounds
begin
set @u = dbo.fn_HMAC(@hash_algorithm,@password,@u)
declare @k int
SET @k = 0
DECLARE @workstring varchar(max)
SET @workstring = ''
while @k < @hLen
begin
set @workstring = @workstring + char(ascii(substring(@u,@k+1,1))^ascii(substring(@t,@k+1,1)))
set @k = @k + 1
end
set @t = @workstring
set @j = @j + 1
end
select @output = @output + case when @i = @l then left(@t,@r) else @t end
set @i = @i + 1
end
return master.dbo.fn_varbintohexstr(convert(varbinary(max), @output ))
end
GO
Erstellen Sie dann die gespeicherte Prozedur, um das Hash-Passwort zu generieren
CREATE PROCEDURE [dbo].[EncryptPassword2]
@passwordIn AS VARCHAR(MAX),
@passwordOut VARCHAR(max) OUTPUT
AS
-- Generate 16 byte salt
DECLARE @saltVarBin VARBINARY(max)
SET @saltVarBin = (SELECT CAST(newid() AS binary(16)))
-- Base64 encode the salt
DECLARE @saltOut VARCHAR(max)
SET @saltOut = cast('' as xml).value('xs:base64Binary(sql:variable("@saltVarBin"))', 'varchar(max)')
-- Decode salt to pass to function fn_PBKDF2
DECLARE @decodedsalt varchar(max)
SET @decodedsalt = convert(varchar(max),(SELECT CAST('' as xml).value('xs:base64Binary(sql:variable("@saltOut"))', 'varbinary(max)')))
-- Build the password binary string from 00 + salt binary string + password binary string created by 32 byte 1000 iteration ORC_PBKDF2 hashing
DECLARE @passwordVarBinStr VARCHAR(max)
-- Identity V1.0 and V2.0 Format: { 0x00, salt, subkey }
SET @passwordVarBinStr = '0x00' + REPLACE(master.dbo.fn_varbintohexstr(@saltVarBin) + (SELECT dbo.fn_PBKDF2('sha1', @passwordIn, @decodedsalt, 1000, 32)),'0x','')
-- Identity V3.0 Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey } (comment out above line and uncomment below line)
--SET @passwordVarBinStr = '0x01000000010000271000000010' + REPLACE(master.dbo.fn_varbintohexstr(@saltVarBin) + (SELECT dbo.fn_PBKDF2('SHA2_256', @passwordIn, @decodedsalt,10000, 32)),'0x','')
-- Convert the password binary string to base 64
DECLARE @passwordVarBin VARBINARY(max)
SET @passwordVarBin = (select cast('' as xml).value('xs:hexBinary( substring(sql:variable("@passwordVarBinStr"), sql:column("t.pos")) )', 'varbinary(max)') from (select case substring(@passwordVarBinStr, 1, 2) when '0x' then 3 else 0 end) as t(pos))
SET @passwordOut = cast(''as xml).value('xs:base64Binary(sql:variable("@passwordVarBin"))', 'varchar(max)')
RETURN
Führen Sie schließlich die gespeicherte Prozedur mit
ausDECLARE @NewPassword varchar(100)
DECLARE @EncryptPassword VARCHAR(max)
select @NewPassword = 'password12344'
EXECUTE EncryptPassword2 @NewPassword, @PasswordOut = @EncryptPassword OUTPUT;
PRINT @EncryptPassword
Bitte beachten Sie, dass die gespeicherte Prozedur möglicherweise für spätere Versionen von SQL Server geändert werden muss, da dies speziell für 2005 geschrieben wurde und ich glaube, dass die Konvertierung in base64 in späteren Versionen anders ist.