Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Générer un hachage de mot de passe d'adhésion ASP.Net en pur T-SQL

J'ai écrit une procédure de hachage stockée en rétro-concevant le code C# à partir d'ici Hasher de mot de passe par défaut de l'identité ASP.NET, comment ça marche et est-ce sécurisé ? et quelques fantastiques fonctions SQL PBKDF2 d'ici Y a-t-il un Implémentation SQL de PBKDF2 ?

Créez d'abord ces deux fonctions extraites de Y a-t-il un SQL implémentation de 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

et

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

puis créez la procédure stockée pour générer le mot de passe de hachage

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

Enfin, exécutez la procédure stockée en utilisant

DECLARE @NewPassword varchar(100)
DECLARE @EncryptPassword VARCHAR(max)

select @NewPassword = 'password12344'                                           

EXECUTE EncryptPassword2 @NewPassword, @PasswordOut = @EncryptPassword OUTPUT;

PRINT @EncryptPassword

Veuillez noter que la procédure stockée devra peut-être être modifiée pour les versions ultérieures de SQL Server car cela a été écrit spécifiquement pour 2005 et je pense que la conversion en base64 est différente dans les versions ultérieures.