title: How do I implement this password class in my vb.net login form
body: <p>I came across this password class and I would like to use it in one of my projects. I have a Windows form that connects to a MySQL database. I have created the connection and was previously using this code to login to the system:</p>
  
  <pre class="lang-vb prettyprint-override"><code>Imports System.Data.OleDb
  Imports System.Net.Sockets
  
  Public Class Login
  
  'The maximum number of times the user can try to login.
  Private Const MAX_ATTEMPT_COUNT As Integer = 3
  
  'The number of times the user has tried to login.
  Private attemptCount As Integer = 0
  Dim adminLogin As Boolean
  
  
  Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
  
  
      Dim x As New System.Security.Cryptography.MD5CryptoServiceProvider()
      Dim bs As Byte() = System.Text.Encoding.UTF8.GetBytes(TextBoxPassword.Text)
      bs = x.ComputeHash(bs)
      Dim s As New System.Text.StringBuilder()
      For Each b As Byte In bs
          s.Append(b.ToString("x2").ToLower())
      Next
      TextBoxPassword.Text = s.ToString()
      Dim pass = TextBoxPassword.Text
  
      If Me.ValidateCredentials Then
          Dim Obj As New Main
          adminLogin = False
          My.Forms.Main.RadTextBox1.Text = adminLogin
          Me.DialogResult = Windows.Forms.DialogResult.OK
  
  
  
      ElseIf Me.ValidateCredentials1 Then
          Dim Obj As New Main
          adminLogin = True
          My.Forms.Main.RadTextBox1.Text = adminLogin
          Me.DialogResult = Windows.Forms.DialogResult.OK
  
  
      Else
          Me.attemptCount += 1
  
          Dim message As String
  
          If Me.attemptCount = MAX_ATTEMPT_COUNT Then
              message = "The maximum number of failed logins has been reached." &amp; _
                        Environment.NewLine &amp; _
                        "The application will now exit."
              Me.DialogResult = Windows.Forms.DialogResult.Abort
          Else
              message = "The provided credentials are incorrect." &amp; _
                        Environment.NewLine &amp; _
                        "Please try again."
              Me.TextBoxPassword.Clear()
              Me.TextBoxUserName.SelectAll()
              Me.TextBoxUserName.Select()
          End If
  
          MessageBox.Show(message, _
                          "Login Failed", _
                          MessageBoxButtons.OK, _
                          MessageBoxIcon.Error)
      End If
  
  End Sub``
  </code></pre>
  
  <p>This is the password class I would prefer to use:</p>
  
  <pre class="lang-vb prettyprint-override"><code>Imports System
  Imports System.IO
  Imports System.Security.Cryptography
  Imports System.Data.OleDb
  Imports System.Net.Sockets
  Imports System.Text.RegularExpressions
  
  
  
  Public Class PasswordHash
  
      Public Const SALT_BYTE_SIZE As Integer = 24
      Public Const HASH_BYTE_SIZE As Integer = 24
      Public Const PBKDF2_ITERATIONS As Integer = 1000
  
      Public Const ITERATION_INDEX As Integer = 0
      Public Const SALT_INDEX As Integer = 1
      Public Const PBKDF2_INDEX As Integer = 2
  
  
      Public Shared Function CreateHash(password As String) As String
          ' Generate a random salt
          Dim csprng As New RNGCryptoServiceProvider()
          Dim salt As Byte() = New Byte(SALT_BYTE_SIZE - 1) {}
          csprng.GetBytes(salt)
  
          ' Hash the password and encode the parameters
          Dim hash As Byte() = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE)
          Return PBKDF2_ITERATIONS + ":" + Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash)
      End Function
  
      ''' &lt;summary&gt;
      ''' Validates a password given a hash of the correct one.
      ''' &lt;/summary&gt;
      ''' &lt;param name="password"&gt;The password to check.&lt;/param&gt;
      ''' &lt;param name="correctHash"&gt;A hash of the correct password.&lt;/param&gt;
      ''' &lt;returns&gt;True if the password is correct. False otherwise.&lt;/returns&gt;
      Public Shared Function ValidatePassword(password As String, correctHash As String) As Boolean
          ' Extract the parameters from the hash
          Dim delimiter As Char() = {":"c}
          Dim split As String() = correctHash.Split(delimiter)
          Dim iterations As Integer = Int32.Parse(split(ITERATION_INDEX))
          Dim salt As Byte() = Convert.FromBase64String(split(SALT_INDEX))
          Dim hash As Byte() = Convert.FromBase64String(split(PBKDF2_INDEX))
  
          Dim testHash As Byte() = PBKDF2(password, salt, iterations, hash.Length)
          Return SlowEquals(hash, testHash)
      End Function
  
      ''' &lt;summary&gt;
      ''' Compares two byte arrays in length-constant time. This comparison
      ''' method is used so that password hashes cannot be extracted from
      ''' on-line systems using a timing attack and then attacked off-line.
      ''' &lt;/summary&gt;
      ''' &lt;param name="a"&gt;The first byte array.&lt;/param&gt;
      ''' &lt;param name="b"&gt;The second byte array.&lt;/param&gt;
      ''' &lt;returns&gt;True if both byte arrays are equal. False otherwise.&lt;/returns&gt;
      Private Shared Function SlowEquals(a As Byte(), b As Byte()) As Boolean
          Dim diff As UInteger = CUInt(a.Length) Xor CUInt(b.Length)
          Dim i As Integer = 0
          While i &lt; a.Length AndAlso i &lt; b.Length
              diff = diff Or CUInt(a(i) Xor b(i))
              i += 1
          End While
          Return diff = 0
      End Function
  
      ''' &lt;summary&gt;
      ''' Computes the PBKDF2-SHA1 hash of a password.
      ''' &lt;/summary&gt;
      ''' &lt;param name="password"&gt;The password to hash.&lt;/param&gt;
      ''' &lt;param name="salt"&gt;The salt.&lt;/param&gt;
      ''' &lt;param name="iterations"&gt;The PBKDF2 iteration count.&lt;/param&gt;
      ''' &lt;param name="outputBytes"&gt;The length of the hash to generate, in bytes.&lt;/param&gt;
      ''' &lt;returns&gt;A hash of the password.&lt;/returns&gt;
      Private Shared Function PBKDF2(password As String, salt As Byte(), iterations As Integer, outputBytes As Integer) As Byte()
          Dim pbkdf2__1 As New Rfc2898DeriveBytes(password, salt)
          pbkdf2__1.IterationCount = iterations
          Return pbkdf2__1.GetBytes(outputBytes)
      End Function
  End Class
  </code></pre>
  
  <p>Any help is much appreciated.</p>