Hash Digests


As we mentioned earlier in this chapter, a hash is a type of one-way cryptography. Some people refer to hashing as encryption; others feel it’s not strictly encryption because the hash cannot be unencrypted. A hash is a very large number, generated by scrambling and condensing the letters of a string. In this chapter, you’ll use the SHA-1 algorithm. SHA-1 is an acronym for Secure Hashing Algorithm. The “-1” refers to revision 1, which was developed in 1994. SHA- 1 takes a string as input and returns a 160-bit (20-byte) number. Because a string is being condensed into a fixed-size number, the result is called a hash digest, where digest indicates a shortened size, similar to Reader’s Digest condensed books. Hash digests are considered to be one-way cryptography because it’s impossible to derive the original string from the hash. A hash digest is like a person’s fingerprint. A fingerprint uniquely identifies an individual without revealing anything about that person—you can’t determine someone’s eye color, height, or gender from a fingerprint. Figure 1-2 shows the SHA-1 hash digests for various strings. Notice that even very similar strings have quite different hash digests.

click to expand
Figure 1-2: SHA-1 hash digests

It’s common, as shown in Figure 1-2, to display a hash as a base-64 encoded 28-character string. This is easier to read than a 48-digit (160-bit) number.

Hash digests are useful for verifying that someone knows a password, without actually storing the password. Storing passwords unencrypted in the database opens two security holes:

  • If an intruder gains access to the database, he can use the information to later log on to the system using someone else’s username and password.

  • People often use the same password for different systems, so the stolen passwords might allow the intruder to break into other systems.

Because the password is used solely for authenticating the user, there’s no reason to store the password in the database. Instead, a hash digest of the password can be stored. When the user logs on to the system, a hash digest from the password she types in is created and compared with the hash digest stored in the database. If an intruder somehow gained access to the password table, he wouldn’t be able to use the hash digest to log on to the system because he would need to know the unencrypted password, which isn’t stored anywhere. In the following exercise, you’ll change the employee management system to validate logons using hash digests instead of passwords.[1]

Create a hash digest function

In this exercise, you’ll write a function that returns SHA-1 hash digests. You’ll then use this function to create hash digests for all the passwords in EmployeeDatabase.mdb and store the hash digests in a field named PasswordHash. This field is already in the database, but it’s currently unpopulated. The passwords are currently stored unencrypted in the Password field.

  1. Start Visual Studio .NET, and open the empty project CH01_Encryption\EncryptDatabaseField\Start\EncryptDatabaseField.sln. This project is empty of code, but it has been set up with the database path, import statements, and a shared library module.

  2. Open the module SecurityLibrary.vb in the Visual Basic .NET editor. This module is empty: it’s where you’ll put all your reusable security routines for use in this and other projects. Add the following function to the library:

    Namespace Hash
    Module Hash
    Function CreateHash(ByVal strSource As String) As String
    Dim bytHash As Byte()
    Dim uEncode As New UnicodeEncoding()
    ’Store the source string in a byte array
    Dim bytSource() As Byte = uEncode.GetBytes(strSource)
    Dim sha1 As New SHA1CryptoServiceProvider()
    ’Create the hash
    bytHash = sha1.ComputeHash(bytSource)
    ’return as a base64 encoded string
    Return Convert.ToBase64String(bytHash)
    End Function
    End Module
    End Namespace

    This function is all that is needed to create a hash. It converts a string to an array of bytes and then creates a SHA-1 hash. The result is returned as a 28-character string.

  3. Open MainModule.vb. You’ll now write a routine to store hash digests for all the passwords in the database. Add the following code to the module:

    Sub Main()
    EncryptField("Password", "PasswordHash")
    End Sub
    Sub EncryptField(ByVal strSourceField As String, _
    ByVal strDestinationField As String)
    Dim strSQL, strUsername, strPlainText, strCipherText As String
    strSQL = "Select Username, " & strSourceField & " from Employee"
    Dim cnRead As New OleDbConnection(G_CONNECTIONSTRING)
    Dim cnWrite As New OleDbConnection(G_CONNECTIONSTRING)
    Dim cmdRead As New OleDbCommand(strSQL, cnRead)
    Dim cmdWrite As New OleDbCommand()
    cmdWrite.Connection = cnWrite
    Dim dr As OleDbDataReader
    ’Open two connections,
    ’one for reading and the other for writing
    cnRead.Open()
    cnWrite.Open()
    dr = cmdRead.ExecuteReader()
    ’Loop through the table, reading strings
    ’encrypting and writing them back
    While dr.Read
    strUsername = dr.GetString(0)
    strPlainText = dr.GetString(1)
    strCipherText = Hash.CreateHash(strPlainText)
    strSQL = "UPDATE Employee SET " & strDestinationField & " =‘" & _
    strCipherText & "‘ WHERE Username =‘" & strUsername & "‘"
    cmdWrite.CommandText = strSQL
    cmdWrite.ExecuteNonQuery()
    Console.WriteLine(LSet(strPlainText, 16) & strCipherText)
    End While
    Console.WriteLine(vbCrLf & "Press <Enter> to continue>")
    Console.ReadLine()
    End Sub

  4. Now press F5 to run the project. It will populate the PasswordHash field and display the results in the console window. The output should look like this:

    click to expand

Verify passwords using a hash digest

Now you will modify the employee management system to verify passwords with the hash digests you just created.

  1. In Visual Studio .NET, open the project CH01_Encryption\EMS\ Start\EMS.sln.

  2. Open the class clsEmployee.vb; find the declaration

    Private m_Password As String

    and change it to

    Private m_PasswordHash As String
  3. In the Create function, find the line that reads

    Me.m_Password = CStr(dr("Password"))

    and change it to

    Me.m_PasswordHash = CStr(dr("PasswordHash"))
  4. In the IsValidPassword function, find the line that reads

    If strPassword = Me.m_Password AndAlso Me.m_IsValidUser Then

    and change it to read

    If Hash.CreateHash(strPassword) = Me.m_PasswordHash _
    AndAlso Me.m_IsValidUser Then

  5. Open the form frmAddNew.vb, and double-click the Add button to open the btnAdd_Click event handler. Change the first line of code from

    Dim strPassword As String = Me.txtPassword.Text

    to

    Dim strPassword As String = Hash.CreateHash(Me.txtPassword.Text)

  6. Still in the btnAdd_Click event, find the line of code that reads

    strSQL = _
    "INSERT INTO Employee ( UserName, [Password], Fullname ) " & _
    "SELECT ’" & strUsername & "‘ As Field1," & _
    "‘" & strPassword & "‘ As Field2," & _
    "‘" & strUsername & "‘ As Field3"

    and change it to

    strSQL = _  "INSERT INTO Employee ( UserName, [PasswordHash], Fullname ) " & _
    "SELECT ’" & strUsername & "‘ As Field1," & _
    "‘" & strPassword & "‘ As Field2," & _
    "‘" & strUsername & "‘ As Field3"

  7. Press F5 to run the project. You can log on using the username RKing with the password RKing, as shown in the following illustration. Congratulations—you are now checking passwords without storing passwords! Even if an intruder gains access to the database, the password hash digests can’t then be used to log on.

    click to expand

start sidebar
How Does a Hash Digest Work?

How does a hash digest work? If each unique string results in a unique hash digest, is it possible to decrypt the hash digest and derive the original string?

To answer these two questions, let’s create a simple hash algorithm. We’ll start by assigning every letter in the alphabet a unique number, so A is equal to 1, B equal to 2, C equal to 3, and so on up to Z, which is equal to 26. Next we’ll use these values to create a hash by adding them together for each character in a string. The string VB generates a hash of 24 because V is the 22nd letter in the alphabet and B is the second letter (22 + 2 = 24).

Can the hash of 24 be reverse-engineered to derive the original string? No. The hash doesn’t tell us the length, starting character, or anything else about the original string. In this simple example, the strings VB, BV, BMDACA, FEJAAA, and thousands of other combinations all give a hash of 24. When different strings produce the same hash value, this is known as a collision. A good hashing algorithm should produce unique results and be collision-free. SHA-1 produces collision-free results, and it scrambles and condenses the original string in such a way that it’s considered computationally infeasible to derive the original string.

end sidebar

[1]Validating against hashes is a good mechanism to use for an application that opens a database directly. For a client-server application or a Web application, this mechanism does not protect against “spoof ing” the server component—where an intruder who knows the hashes constructs a fake client appli cation that submits the hash to the server. However, if an intruder gains access to the list of passwords, they can do less damage if the passwords are hashed.




Security for Microsoft Visual Basic  .NET
Security for Microsoft Visual Basic .NET
ISBN: 735619190
EAN: N/A
Year: 2003
Pages: 168

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net