Published on

January 23, 2025

Securely Storing Passwords in SQL Server

When it comes to password security, it’s not just about choosing strong passwords. Storing passwords securely in a database is equally important. In this article, we will discuss how to encrypt and store passwords in a SQL Server database to ensure maximum security.

One-Way Hashing Algorithms

To encrypt passwords, we will use one-way hashing algorithms. These algorithms generate an encrypted output for a given input value, but there is no decryption algorithm. This means that it is impossible to revert to the original value using the encrypted output.

In SQL Server, the HASHBYTES function can be used to generate a hash for an input value using various algorithms such as MD2, MD4, MD5, SHA, SHA1, SHA2_256, and SHA2_512. For our example, we will choose the strongest algorithm – SHA2_512.

Creating the User Table

Let’s assume we need to create a table to store user data, including their login name, encrypted password hash, first name, and last name. We can create the table using the following SQL statement:

CREATE TABLE dbo.[User]
(
    UserID INT IDENTITY(1,1) NOT NULL,
    LoginName NVARCHAR(40) NOT NULL,
    PasswordHash BINARY(64) NOT NULL,
    FirstName NVARCHAR(40) NULL,
    LastName NVARCHAR(40) NULL,
    CONSTRAINT [PK_User_UserID] PRIMARY KEY CLUSTERED (UserID ASC)
)

Creating the Stored Procedure

We will also create a stored procedure to insert user data into the table. The stored procedure takes the login name, password, first name, and last name as input parameters. Inside the stored procedure, we will use the HASHBYTES function to encrypt the password before inserting it into the table.

CREATE PROCEDURE dbo.uspAddUser
    @pLogin NVARCHAR(50), 
    @pPassword NVARCHAR(50), 
    @pFirstName NVARCHAR(40) = NULL, 
    @pLastName NVARCHAR(40) = NULL,
    @responseMessage NVARCHAR(250) OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    BEGIN TRY

        INSERT INTO dbo.[User] (LoginName, PasswordHash, FirstName, LastName)
        VALUES(@pLogin, HASHBYTES('SHA2_512', @pPassword), @pFirstName, @pLastName)

        SET @responseMessage='Success'

    END TRY
    BEGIN CATCH
        SET @responseMessage=ERROR_MESSAGE() 
    END CATCH

END

Encrypting and Storing Passwords

To encrypt and store passwords, we can execute the stored procedure as follows:

DECLARE @responseMessage NVARCHAR(250)

EXEC dbo.uspAddUser
          @pLogin = N'Admin',
          @pPassword = N'123',
          @pFirstName = N'Admin',
          @pLastName = N'Administrator',
          @responseMessage=@responseMessage OUTPUT

SELECT *
FROM [dbo].[User]

As you can see, the password’s text is unreadable in the database, ensuring that even if an attacker gains access to the database, they cannot easily steal users’ passwords.

Enhancing Security with Salts

Although encrypting passwords provides a significant level of security, there are still vulnerabilities, such as dictionary and rainbow table attacks. To further enhance security, we can use salts.

A salt is a randomly generated text that is combined with the password before hashing. This makes it much more difficult for attackers to crack passwords, even if they have access to the hashed passwords.

In our example, we will alter the user table and the stored procedure to include a salt column and generate a unique salt for each user:

ALTER TABLE dbo.[User] ADD Salt UNIQUEIDENTIFIER 

ALTER PROCEDURE dbo.uspAddUser
    @pLogin NVARCHAR(50), 
    @pPassword NVARCHAR(50),
    @pFirstName NVARCHAR(40) = NULL, 
    @pLastName NVARCHAR(40) = NULL,
    @responseMessage NVARCHAR(250) OUTPUT
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @salt UNIQUEIDENTIFIER=NEWID()
    BEGIN TRY

        INSERT INTO dbo.[User] (LoginName, PasswordHash, Salt, FirstName, LastName)
        VALUES(@pLogin, HASHBYTES('SHA2_512', @pPassword+CAST(@salt AS NVARCHAR(36))), @salt, @pFirstName, @pLastName)

       SET @responseMessage='Success'

    END TRY
    BEGIN CATCH
        SET @responseMessage=ERROR_MESSAGE() 
    END CATCH

END

By using different salts for each user, we can avoid situations where two users with the same password have the same hashed password string. This significantly reduces the risk of an attacker cracking multiple passwords.

Authentication with Encrypted Passwords and Salts

To authenticate a user, we can create a stored procedure that checks if the login name and password match the stored encrypted password and salt:

CREATE PROCEDURE dbo.uspLogin
    @pLoginName NVARCHAR(254),
    @pPassword NVARCHAR(50),
    @responseMessage NVARCHAR(250)='' OUTPUT
AS
BEGIN

    SET NOCOUNT ON

    DECLARE @userID INT

    IF EXISTS (SELECT TOP 1 UserID FROM [dbo].[User] WHERE LoginName=@pLoginName)
    BEGIN
        SET @userID=(SELECT UserID FROM [dbo].[User] WHERE LoginName=@pLoginName AND PasswordHash=HASHBYTES('SHA2_512', @pPassword+CAST(Salt AS NVARCHAR(36))))

       IF(@userID IS NULL)
           SET @responseMessage='Incorrect password'
       ELSE 
           SET @responseMessage='User successfully logged in'
    END
    ELSE
       SET @responseMessage='Invalid login'

END

We can test the authentication procedure as follows:

DECLARE @responseMessage NVARCHAR(250)

--Correct login and password
EXEC dbo.uspLogin
		@pLoginName = N'Admin',
		@pPassword = N'123',
		@responseMessage = @responseMessage OUTPUT

SELECT	@responseMessage as N'@responseMessage'

--Incorrect login
EXEC dbo.uspLogin
		@pLoginName = N'Admin1', 
		@pPassword = N'123',
		@responseMessage = @responseMessage OUTPUT

SELECT	@responseMessage as N'@responseMessage'

--Incorrect password
EXEC dbo.uspLogin
		@pLoginName = N'Admin', 
		@pPassword = N'1234',
		@responseMessage = @responseMessage OUTPUT

SELECT	@responseMessage as N'@responseMessage'

By securely storing passwords in an encrypted form and using unique salts for each user, we can significantly reduce the risk of password cracking. The use of the SQL Server UNIQUEIDENTIFIER data type for salts ensures uniqueness and randomness, further enhancing security.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.