Imports System.Collections.Generic
Imports System.Security.Cryptography
Dim existingPassword = Authentication.EncryptPlainText("Password123456789")
Console.Write("Password: ")
Dim incomingPassword = Console.ReadLine()
Dim authenticated = Authentication.Authenticate(incomingPassword, existingPassword)
Console.WriteLine("Authenticated!")
Console.WriteLine("Invalid login.")
Public Class Authentication
Private Shared ReadOnly _byteLength As Integer = 32
Private Shared ReadOnly _rcfIterations As Integer = 100000
Public Shared Function Authenticate(plaintext As String, encryptedText As Byte()) As Boolean
Dim salt(_byteLength - 1) As Byte
If (encryptedText.Length > _byteLength) Then
For index = 0 To _byteLength - 1
salt(index) = encryptedText(index)
For index = 0 To _byteLength - 1
salt(index) = [Byte].MinValue
Dim hash = Authentication.GenerateHash(plaintext, salt)
If (encryptedText.Length - _byteLength = hash.Length) Then
For index = 0 To hash.Length - 1
authenticated = hash(index) = encryptedText(_byteLength + index)
authenticated = [Byte].MinValue = [Byte].MaxValue
For index = 0 To hash.Length - 1
authenticated = [Byte].MinValue = [Byte].MaxValue
Public Shared Function CombineSaltAndHash(salt As Byte(), hash As Byte()) As IEnumerable(Of Byte)
If (_byteLength < 1) Then
Throw New Exception($"{NameOf(_byteLength)} cannot be less than 1")
If (salt.Length <> _byteLength) Then
Throw New ArgumentOutOfRangeException(NameOf(salt), "The incoming salt is invalid")
If (hash.Length <> _byteLength) Then
Throw New ArgumentOutOfRangeException(NameOf(hash), "The incoming hash is invalid")
Return salt.Concat(hash).ToArray()
Public Shared Function EncryptPlainText(plaintext As String) As IEnumerable(Of Byte)
Dim salt = Authentication.GenerateSalt()
Dim hash = Authentication.GenerateHash(plaintext, salt)
Dim combinedHash = Authentication.CombineSaltAndHash(salt, hash)
Public Shared Function GenerateHash(plaintext As String, salt As Byte()) As Byte()
If (_byteLength < 1) Then
Throw New Exception($"{NameOf(_byteLength)} cannot be less than 1")
If (_rcfIterations < 1) Then
Throw New Exception($"{NameOf(_rcfIterations)} cannot be less than 1")
If (String.IsNullOrWhiteSpace(plaintext)) Then
Throw New ArgumentNullException(NameOf(plaintext))
If (salt.Length <> _byteLength) Then
Throw New ArgumentOutOfRangeException(NameOf(salt), "The incoming salt is invalid")
Using rcf = New Rfc2898DeriveBytes(plaintext, salt, _rcfIterations)
hash = rcf.GetBytes(_byteLength)
Public Shared Function GenerateSalt() As Byte()
If (_byteLength < 1) Then
Throw New Exception($"{NameOf(_byteLength)} cannot be less than 1")
Dim salt(_byteLength - 1) As Byte
Using provider = RandomNumberGenerator.Create()