Authenticate against password hash & salt

Hello,

I have the following code below that works when authenticating against a username and password in my database. I need the ability to check against the passwordhash and the passwordsalt to authenticate a user.

I'm going to attach the code that i have for the hash and salt below.
Protected Sub pssalogin_click(ByVal sender As Object, ByVal e As ImageClickEventArgs)
 
        Session("username") = txtUsername.Text
 
        ' Create Connection to Database
        Dim connectionString As String = ConfigurationManager.ConnectionStrings("PSSA").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)
 
        'declare the command
        Dim comm As SqlCommand
 
        comm = New SqlCommand("LoginData", conn)
        comm.CommandType = System.Data.CommandType.StoredProcedure
 
        'declare the parameters
        comm.Parameters.Add("@username", SqlDbType.VarChar, 50)
        comm.Parameters("@username").Value = txtUsername.Text
        comm.Parameters.Add("@passwordhash", SqlDbType.VarChar, 128)
        comm.Parameters("@passwordhash").Value = txtPassword.Text
 
        Try
            conn.Open()
            Dim myreader As SqlDataReader
            myreader = comm.ExecuteReader(CommandBehavior.CloseConnection)
            If myreader.Read() Then
                FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)
            Else
                pssaerrors.Text = "your login credentials are invalid!!!"
            End If
            myreader.Close()
        Catch
            pssaerrors.Text = "the pssa database is currently offline."
        Finally
            conn.Close()
        End Try
    End Sub
 
 
HASH AND SALT CODE:
 
Public Function gfCreatePasswordHash(ByVal vstrPwd As String, ByVal vstrSalt As String) As String
        Dim strSaltAndPwd As String = String.Concat(vstrPwd, vstrSalt)
        Dim strHashedPwd As String = FormsAuthentication.HashPasswordForStoringInConfigFile(strSaltAndPwd, "SHA1")
        Return strHashedPwd
    End Function
 
    Public Function gfCreateSalt(ByVal intSize As Integer) As String
        ' Generate a cryptographic random number using the cryptographic
        ' service provider
        Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider
        Dim buff() As Byte = New Byte(intSize) {}
        rng.GetBytes(buff)
        ' Return a Base64 string representation of the random number
        Return Convert.ToBase64String(buff)
    End Function
 
    Protected Sub btnAddUser_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddUser.Click
        If Page.IsValid Then
 
            Dim strSalt As String
 
            Dim conn As SqlConnection
            Dim Insertcomm As SqlCommand
 
            Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString
 
            conn = New SqlConnection(connectionString)
 
            Insertcomm = New SqlCommand("SaltInsert", conn)
            Insertcomm.CommandType = CommandType.StoredProcedure
 
            Insertcomm.Parameters.Add("@name", System.Data.SqlDbType.VarChar, 50)
            Insertcomm.Parameters("@name").Value = txtName.Text
 
            Insertcomm.Parameters.Add("@email", System.Data.SqlDbType.VarChar, 100)
            Insertcomm.Parameters("@email").Value = txtEmail.Text
 
            Insertcomm.Parameters.Add("@username", System.Data.SqlDbType.VarChar, 50)
            Insertcomm.Parameters("@username").Value = txtUsername.Text
 
            strSalt = gfCreateSalt(5)   'This creates a 5-digit salt
            Insertcomm.Parameters.Add("@passwordsalt", System.Data.SqlDbType.VarChar, 128)
            Insertcomm.Parameters("@passwordsalt").Value = strSalt
 
            Insertcomm.Parameters.Add("@passwordhash", System.Data.SqlDbType.VarChar, 128)
            Insertcomm.Parameters("@passwordhash").Value = gfCreatePasswordHash(txtPassword.Text, strSalt)
            'strSalt was created above and strUserPswd is what the user keyed in
 
            Try
                conn.Open()
 
                Insertcomm.ExecuteNonQuery()
 
            Catch ex As Exception
                ex.Message.ToString()
 
            Finally
                conn.Close()
            End Try
        End If
 
    End Sub

Open in new window

LVL 4
asp_net2Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

guru_samiCommented:
From what I understood here is what you should do upon pssalogin_click:
1: Get Salt from DB for txtUsername.Text username
2: Hash txtPassword.Text using Salt you get from step 1.
3: Now call SP LoginData passing the username and hashedPassword from step 2.

I am not sure if thats what your were looking for.
0
jbeasle3Commented:
To verify the login do the following:

(See Function Below)

1.  Read the user info from the database.
2.  Take the password just keked in anad concatenate it to the Salt
3.  Hash the concatenated result
4.  Compare it to the encrypted password stored in the database.

The function in the code snippet was derived from one I use.  It may not work as it hasn't been tested as written, but it should give you a good idea of what needs to be done.
0
jbeasle3Commented:
Forgot to attach code snippet...Here it is.
Function VerifyPassword(ByVal vstrUserName As String, ByVal vstrPassword as String) As Integer
 
        Dim bolPasswordMatch As Boolean = False
        Dim strDbPasswordHash As String
        Dim strDbSalt As String
        Dim ObjUserMaster as New UserMaster(vstrUserName)
 
'Get the user's login info from the database using your preferred method (I use a UserMaster Class)
 
    Try
        With objUserMaster
                strDbPasswordHash = .WebPin
                strDbSalt = .WebPinSalt
                If .NbrOfAttempts > 3 Then
                    .AccountLocked = True
                    .UpdateRecord()
                    'They've used up all their login chances, so inform them (by returning -4) and lock their account
                    Return -4
                End If
        End With
        
        ' Now take the salt and the password entered by the user
        ' and concatenate them together.
        Dim strPasswordAndSalt As String = String.Concat(vstrPassword, strDbSalt)
 
        ' Now hash them
        Dim strHashedPasswordAndSalt As String = FormsAuthentication.HashPasswordForStoringInConfigFile(strPasswordAndSalt, "SHA1")
 
        ' Now verify them.
        bolPasswordMatch = strHashedPasswordAndSalt.Equals(strDbPasswordHash)
        If bolPasswordMatch = True Then
            With objUserMaster
                .NbrOfAttempts = 0
                .UpdateRecord()
            End With
            Return 0
        Else
            With objUserMaster
                .NbrOfAttempts += 1
                .UpdateRecord()
            End With
            Return -1
        End If
    Catch ex As Exception
        mstrDisplayMsg = ex.ToString
    Finally
        objUserMaster.Dispose
        System.GC.Collect()
    End Try
End Function

Open in new window

0
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

asp_net2Author Commented:
is there any way i could have a little more help :(

this is the first time dealing with hash and salt and to be honest i don't know where to begin with the following code above.
0
asp_net2Author Commented:
can i have help filling in the pieces from what i'm use to compared to the function that you supplied?

Protected Sub btnAuthenticate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAuthenticate.Click

        Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)

        Dim comm As SqlCommand

        comm = New SqlCommand("PSSA_LoginData", conn)
        comm.CommandType = System.Data.CommandType.StoredProcedure

        comm.Parameters.Add("@username", SqlDbType.VarChar, 50)
        comm.Parameters("@username").Value = txtUsername.Text
        comm.Parameters.Add("@passwordhash", SqlDbType.VarChar, 128)
        comm.Parameters("@passwordhash").Value = txtPassword.Text

        Try
            conn.Open()
            Dim myreader As SqlDataReader
            myreader = comm.ExecuteReader(CommandBehavior.CloseConnection)
            If myreader.Read() Then
                FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)
            Else
                lblError.Text = "your login credentials are invalid!!!"
            End If
            myreader.Close()
        Catch
            lblError.Text = "the pssa database is currently offline."
        Finally
            conn.Close()
        End Try

    End Sub


STORED PROCEDURE THAT I'M USING WITH CODE ABOVE:

ALTER PROCEDURE PSSA_LoginData

@username varchar(50),
@password varchar(128)

AS

SELECT [password ] FROM [PSSA_USERS] WHERE (([username ] = @username ) AND ([password ] = @password ))
0
guru_samiCommented:
I think you are missing one major point the point. i.e. you should store hashedPassword and Salt in the DB as well.
When you Create the user account ... you do the following:
1: Call gfCreateSalt function and get the Salt
2: Call gfCreatePasswordHash and get hashedPwd
3: Store username,hashedPwd(step 2) and Salt(step 1) in the DB.

Upon login....in your btnAuthenticate_Click:
1: Get Salt and HashedPwd from DB calling call SP PSSA_LoginData
2: Hash txtPassword.Text using Salt you get from step 1 by calling gfCreatePasswordHash .
3: Now compare HashedPwd that was returned by PSSA_LoginData and the hashedPwd you get from step 2.

Note: You will have to modify your PSSA_LoginData stored Proc to take only "username" and return Salt and HashedPwd(that you stored during User account creation).

Hope that is a better explanation ...Sorry I don't have code right now.
0
asp_net2Author Commented:
Hi guru_sami,

yes hashedPassword and Salt is and has been stored in the DB.

Steps 1,2, and 3 above when creating the user account have been completed and everything works on the user creation end.

>> upon login, this is where i'm having the problems at :(

is the following SP correct that i have below

CREATE PROCEDURE PSSA_LoginData

@username varchar(50),
@passwordhash varchar(128),
@passwordsalt varchar(128)

AS

SELECT [username] FROM [EmpSalt] WHERE (([username] = @username) AND ([passwordhash] = @passwordhash))
0
guru_samiCommented:
Is the username,passwordhash and passwordsalt stored in same table?

Looks your storedProc needs some changes...
Your SP should take username as input parameter and return salt and passwordhash for that user.

The idea is you get Salt from the DB ...then Hash the password that User entered using this Salt.
So now you have hashedpwd(for what user entered) and passwordhash that was initally stored for the user when the account was created.

Now you compare that hashedpwd with the "passwordhash" that your storedProc returned.

Hope that helps.
0
asp_net2Author Commented:
>> Is the username,passwordhash and passwordsalt stored in same table?
Yes, all three fields are in the same table

I think i understand how i need the SP to look, is the following SP correct now?

@username varchar(50)

AS

SELECT username, passwordhash, passwordsalt FROM EmpSalt WHERE username = @username
0
guru_samiCommented:
Yep thats what I am talking about....
Now follow step 2 and 3 as in my previous post.
0
asp_net2Author Commented:
ok, step 1 down and 2 to go :)

I modified the btnAuthenticate Code below, can you check to see if i accomplished either Step 2 or 3? This is where things are getting crazy and above me :)

I added the Function Code below:

Public Function gfCreateSalt(ByVal intSize As Integer) As String
        ' Generate a cryptographic random number using the cryptographic
        ' service provider
        Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider
        Dim buff() As Byte = New Byte(intSize) {}
        rng.GetBytes(buff)
        ' Return a Base64 string representation of the random number
        Return Convert.ToBase64String(buff)
    End Function




Protected Sub btnAddUser_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddUser.Click
        If Page.IsValid Then

            Dim strSalt As String

            Dim conn As SqlConnection
            Dim Insertcomm As SqlCommand

            Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString

            conn = New SqlConnection(connectionString)

            Insertcomm = New SqlCommand("SaltInsert", conn)
            Insertcomm.CommandType = CommandType.StoredProcedure

            Insertcomm.Parameters.Add("@name", System.Data.SqlDbType.VarChar, 50)
            Insertcomm.Parameters("@name").Value = txtName.Text

            Insertcomm.Parameters.Add("@email", System.Data.SqlDbType.VarChar, 100)
            Insertcomm.Parameters("@email").Value = txtEmail.Text

            Insertcomm.Parameters.Add("@username", System.Data.SqlDbType.VarChar, 50)
            Insertcomm.Parameters("@username").Value = txtUsername.Text

            strSalt = gfCreateSalt(5)   'This creates a 5-digit salt
            Insertcomm.Parameters.Add("@passwordsalt", System.Data.SqlDbType.VarChar, 128)
            Insertcomm.Parameters("@passwordsalt").Value = strSalt

            Insertcomm.Parameters.Add("@passwordhash", System.Data.SqlDbType.VarChar, 128)
            Insertcomm.Parameters("@passwordhash").Value = gfCreatePasswordHash(txtPassword.Text, strSalt)
            'strSalt was created above and strUserPswd is what the user keyed in

            Try
                conn.Open()

                Insertcomm.ExecuteNonQuery()

            Catch ex As Exception
                ex.Message.ToString()

            Finally
                conn.Close()
            End Try
        End If

    End Sub
0
guru_samiCommented:
Ok that is Step 1..creating user...
I do not see anything about Login ..
0
asp_net2Author Commented:
LOL, sorry please see my btnAuthenticate Code below. Now, the strSalt is not declared because i was not sure how to declare and use it below.

Protected Sub btnAuthenticate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAuthenticate.Click

        Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)

        Dim comm As SqlCommand

        comm = New SqlCommand("PSSA_LoginData", conn)
        comm.CommandType = System.Data.CommandType.StoredProcedure

        comm.Parameters.Add("@username", SqlDbType.VarChar, 50)
        comm.Parameters("@username").Value = txtUsername.Text
        comm.Parameters.Add("@passwordhash", SqlDbType.VarChar, 128)
        comm.Parameters("@passwordhash").Value = gfCreatePasswordHash(txtPassword.Text, passwordsalt)

        Try
            conn.Open()
            Dim myreader As SqlDataReader
            myreader = comm.ExecuteReader(CommandBehavior.CloseConnection)
            If myreader.Read() Then
                FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)
            Else
                lblError.Text = "your login credentials are invalid!!!"
            End If
            myreader.Close()
        Catch
            lblError.Text = "the pssa database is currently offline."
        Finally
            conn.Close()
        End Try

    End Sub
0
guru_samiCommented:
Sorry but there might be syntax errors....but you will get the idea what needs to be done.

Considering this as your SP PSSA_LoginData:
@username varchar(50)
AS
SELECT username, passwordhash, passwordsalt FROM EmpSalt WHERE username = @username


Dim strSaltFromDB As String
Dim hashPwdInDB As String
Dim hashPwdEnterd As String

   Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)
        Dim comm As SqlCommand
        comm = New SqlCommand("PSSA_LoginData", conn)
        comm.CommandType = System.Data.CommandType.StoredProcedure
 comm.Parameters.Add("@username", SqlDbType.VarChar, 50)
        comm.Parameters("@username").Value = txtUsername.Text
     
        Try
            conn.Open()
            Dim myreader As SqlDataReader
            myreader = comm.ExecuteReader(CommandBehavior.CloseConnection)
            If myreader.Read() Then
                  hashPwdInDD = myreader.GetString(1)
                  strSaltFromDB = myreader.GetString(2)
                  hashPwdEnterd = gfCreatePasswordHash(txtPassword.Text,strSaltFromDB)
               If hashPwdEnterd = hashPwdInDB Then
                FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)            
            Else
                lblError.Text = "your login credentials are invalid!!!"
             EndIf
            Else
             lblError.Text = "your login credentials are invalid!!!"
            End If
            myreader.Close()
        Catch
            lblError.Text = "the pssa database is currently offline."
        Finally
            conn.Close()
        End Try
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
asp_net2Author Commented:
ok, let me know if this looks okay now. I now recieve a different error before running which is listed below.

ERROR MESSAGE:

Variable 'strSaltFromDB' is used before it has been assigned  a value. A null reference exception could result at runtime.

Protected Sub btnAuthenticate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAuthenticate.Click

        Dim strSaltFromDB As String
        Dim hashPwdInDB As String
        Dim hashPwdEnterd As String

        Dim connectionString As String = ConfigurationManager.ConnectionStrings("DemoSql").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)

        Dim comm As SqlCommand

        comm = New SqlCommand("PSSA_LoginData", conn)
        comm.CommandType = System.Data.CommandType.StoredProcedure

        comm.Parameters.Add("@username", SqlDbType.VarChar, 50)
        comm.Parameters("@username").Value = txtUsername.Text
        comm.Parameters.Add("@passwordhash", SqlDbType.VarChar, 128)
        comm.Parameters("@passwordhash").Value = gfCreatePasswordHash(txtPassword.Text, strSaltFromDB)

        Try
            conn.Open()
            Dim myreader As SqlDataReader
            myreader = comm.ExecuteReader(CommandBehavior.CloseConnection)
            If myreader.Read() Then

                hashPwdInDB = myreader.GetString("passwordhash")
                strSaltFromDB = myreader.GetString("passwordsalt")

                hashPwdEnterd = gfCreatePasswordHash(txtPassword.Text, strSaltFromDB)
                If hashPwdEnterd = hashPwdInDB Then
                    FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, True)

                Else
                    lblError.Text = "your login credentials are invalid!!!"
                End If
            End If
            myreader.Close()
        Catch
            lblError.Text = "the pssa database is currently offline."
        Finally
            conn.Close()
        End Try

    End Sub
0
guru_samiCommented:
Did you see my code does not have this:

    comm.Parameters.Add("@passwordhash", SqlDbType.VarChar, 128)
        comm.Parameters("@passwordhash").Value = gfCreatePasswordHash(txtPassword.Text, strSaltFromDB)

there is no need to pass passwordhash to your StoreProc as it just take username as input parameter.

So remove those two lines shown above.
0
guru_samiCommented:
Also you change this which might throw exception:
                hashPwdInDB = myreader.GetString("passwordhash")
                strSaltFromDB = myreader.GetString("passwordsalt")
GetString() takes int as input and not String...
So look at my code and use that first and see if it works.

I think this is the other way:
hashPwdInDB = myreader("passwordhash").ToString
strSaltFromDB = myreader("passwordsalt").ToString
0
jbeasle3Commented:
Sorry my explanation was so confusing.  I tend to have all my sql and vb code in classes and common code pages.  That way my aspx.vb pages aren't so cluttered and can take care of just what's on the web page.
0
asp_net2Author Commented:
THANK YOU VERY MUCH FOR ALL YOUR HELP!!! That worked out GREAT!!

you where right i forgot to remove the following line below and once i did that and applied your changes everything worked.

Thanks again!!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.