Reputation: 75
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?
Upvotes: 0
Views: 6868
Reputation: 216
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
Upvotes: 0
Reputation: 24131
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);
Upvotes: 1