简体   繁体   中英

How to do password validation in sql server?

I have encrypted my password field using aes_256 algorithm in sql server. The password field is now encrypted. Now I want to login user and the validation process should be done on the server. The code which i wrote for the validation process is:

CREATE PROCEDURE Procedure_UserLogin
    @username varchar(50),
    @pwd varchar(50),
    @responseMessage INT OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @userID INT

    IF EXISTS(SELECT TOP 1 username FROM userInfo WHERE username=@username)
    BEGIN
        open symmetric key key1
        decryption by certificate namecert
        SET @userID=(SELECT username FROM userInfo WHERE username=@username AND encryptedpwd=(ENCRYPTBYKEY(KEY_GUID('key1'),@pwd)))
        IF (@userID IS NULL)
            SET @responseMessage=0 /*INAVLID PASSWORD*/
        ELSE
            SET @responseMessage=1  /*VALID USERNAME AND PASSWORD*/
    END
    ELSE
        SET @responseMessage=2 /*INVALID USERNAME*/
END

But the response is always 0. Please tell me what mistake am i doing?

One can/should not delegate password verification to the database. Passwords should be hashed with a slow algorithm like BCrypt, PBKDF2 or SCrypt and those algorithms are usually not supported by database systems. Salting is mandatory and will prevent that you can search for a specific password-hash.

So do not encrypt the passwords, instead implement it like this:

// Get password-hash by user id
SELECT hashedpwd FROM userInfo WHERE username=@username

// Verify the password within your application, which supports a safe algorithm
// like BCrypt, PBKDF2 or SCrypt.
// Take the salt from $existingHashFromDb or from a separate db-field.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

The short answer is because ENCRYPTBYKEY outputs different result every time, and an encrypted value stored in a table is constant.

Try running the script below to see it in action.

DECLARE @passphrase VARCHAR(50);
SET @passphrase = 'UseYourHashLuke';

OPEN SYMMETRIC KEY KEY1
DECRYPTION BY CERTIFICATE namecert

SELECT ENCRYPTBYKEY(KEY_GUID('KEY1'), @passphrase);

CLOSE SYMMETRIC KEY1
GO 10

You should see 10 different outputs. But if you run SELECT statement against the table for encryptedpwd , the output is the same every time. That's why your script can never correctly authenticate the user input even when the input is correct.

Now, based on that you might be thinking of changing this line

encryptedpwd=(ENCRYPTBYKEY(KEY_GUID('key1'),@pwd))) 

to something like this, right?

DECRYPTBYKEY(KEY_GUID('key1'),encryptedpwd)) = @pwd

Not so fast. The reason is that both DECRYPTBYKEY and ENCRYPTBYKEY returns VARBINARY(8000) but the user input @pwd is VARCHAR(50) . So without converting the output to match the datatype of input, they will always be different.

CONVERT(VARCHAR,DECRYPTBYKEY(KEY_GUID('key1'),encryptedpwd))) = @pwd

Lastly, BOL on CLOSE SYMMETRIC KEY says

Open symmetric keys are bound to the session not to the security context. An open key will continue to be available until it is either explicitly closed or the session is terminated.

So it'd be a good practice to explicitly close keys at the end with.

CLOSE SYMMETRIC KEY KEY1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM