Solved

Authenticate against password hash & salt

Posted on 2009-06-30
19
570 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 8
  • 3
19 Comments
 
LVL 41

Expert Comment

by:guru_sami
ID: 24746360
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
ID: 24746848
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
ID: 24746858
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Author Comment

by:asp_net2
ID: 24747366
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
ID: 24747510
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
ID: 24747632
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
ID: 24747749
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
ID: 24747850
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
ID: 24747873
>> 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
 
LVL 41

Expert Comment

by:guru_sami
ID: 24747966
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
ID: 24748076
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
ID: 24748113
Ok that is Step 1..creating user...
I do not see anything about Login ..
0
 
LVL 4

Author Comment

by:asp_net2
ID: 24748208
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
ID: 24748390
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
ID: 24748546
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
ID: 24749099
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
ID: 24749184
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
ID: 24749542
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
ID: 31598300
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article discusses the ASP.NET AJAX ModalPopupExtender control. In this article we will show how to use the ModalPopupExtender control, how to display/show/call the ASP.NET AJAX ModalPopupExtender control from javascript, how to show/display/cal…
I recently went through the process of creating a Calendar Control of events with the basis of using a database to keep track of the dates that are selectable, one requirement was to have the selected date pop-up in a simple lightbox.  At first this…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

696 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