Solved

Authenticate against password hash & salt

Posted on 2009-06-30
19
555 Views
Last Modified: 2012-05-07
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

0
Comment
Question by:asp_net2
  • 8
  • 8
  • 3
19 Comments
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
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
 
LVL 3

Expert Comment

by:jbeasle3
Comment Utility
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
 
LVL 3

Expert Comment

by:jbeasle3
Comment Utility
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
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
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
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
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
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
>> 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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
Yep thats what I am talking about....
Now follow step 2 and 3 as in my previous post.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
Ok that is Step 1..creating user...
I do not see anything about Login ..
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 41

Accepted Solution

by:
guru_sami earned 500 total points
Comment Utility
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
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
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
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
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
 
LVL 41

Expert Comment

by:guru_sami
Comment Utility
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
 
LVL 3

Expert Comment

by:jbeasle3
Comment Utility
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
 
LVL 4

Author Closing Comment

by:asp_net2
Comment Utility
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

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now