Introduction
This article describes how to use a MD5 class library I have written for .NET. MD5 is recommended to be implemented in the following manner:
Encrypting
- Generate a random "Salt" value
- Merge the string to encrypt with the "Salt"
- MD5 the merged string
- Save the MD5 hash in one location and the Salt in another, usually a separate "Table" in your DBMS (Database Management System).
Testing
- Locate the saved "Salt"
- Merge the string and the saved "Salt"
- MD5 the merged string
- Test the new MD5 hash against the saved; if a match is found, allow usage to whatever you were protecting
Background
I chose to write this class library because all the articles and recommendation I found and were told at MSDN events recommended storing this Salt in a DBMS. I was writing an ASP.NET application where I wanted to use XML files for storage of usernames and passwords. Storing Salts in the same XML file isn't recommended, but I also didn't think it was secure storing them in any XML file "plainly". I decided to write a class that would generate the Salt, merge it with the string, encrypt the string, take the Salt, and place it in a random location in the hash, and save the hash. This allows me to store the hash in an XML file, and makes the Salt far more secure since it has to be found in the hash string first, very difficult to do. Also, since the hash string looks so similar to regular MD5 hash strings, it's hard to determine when this method is actually being used.
Using the Code
Since the code is being distributed as a class library, it is very easy to use.
Steps to using this class library:
- Download the package.
- Extract it to your hard disk.
- Right click References in the VS.NET IDE (Solution Explorer) and hit "Add Reference".
- Add code similar to that below:
Imports IST.DataHash
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim MD5 As New MD5
lblEncString.Text = MD5.Encrypt(txtEncrypt.Text)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim MD5 As New MD5
lblDecString.Text = MD5.Verify(txtEncrypt.Text, lblEncString.Text)
End Sub
The assembly is also Strong Name signed to allow addition to the GAC.
Source Code
Imports System.Security.Cryptography
Imports System.Text
Namespace DataHash
Public Class MD5
Private EncStringBytes() As Byte
Private Encoder As New UTF8Encoding
Private MD5Hasher As New MD5CryptoServiceProvider
Public Function Encrypt(ByVal EncString As String) As String
Dim RanGen As New Random
Dim RanString As String = ""
Dim MD5String As String
Dim RanSaltLoc As String
While RanString.Length <= 3
RanString = RanString & RanGen.Next(0, 9)
End While
EncStringBytes = Encoder.GetBytes(EncString & RanString)
EncStringBytes = MD5Hasher.ComputeHash(EncStringBytes)
MD5String = BitConverter.ToString(EncStringBytes)
MD5String = MD5String.Replace("-", Nothing)
RanSaltLoc = RanGen.Next(4, MD5String.Length)
MD5String = MD5String.Insert(RanSaltLoc, RanString)
If RanSaltLoc < 10 Then
RanSaltLoc = "0" & RanSaltLoc
End If
MD5String = MD5String.Insert(3, RanSaltLoc)
Return MD5String
End Function
Public Function Verify(ByVal S As String, ByVal Hash As String) As Boolean
Dim SaltAddress As Double
Dim SaltID As String
Dim NewHash As String
SaltAddress = Hash.Substring(3, 2)
Hash = Hash.Remove(3, 2)
SaltID = Hash.Substring(SaltAddress, 4)
Hash = Hash.Remove(SaltAddress, 4)
EncStringBytes = Encoder.GetBytes(S & SaltID)
EncStringBytes = MD5Hasher.ComputeHash(EncStringBytes)
NewHash = BitConverter.ToString(EncStringBytes)
NewHash = NewHash.Replace("-", Nothing)
If NewHash = Hash Then
Return True
ElseIf NewHash <> Hash Then
Return False
End If
End Function
End Class
End Namespace
Points of Interest
Various MD5 references:
History