Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Sub Main
- Dim passwords = Enumerable.Range(0, 5).Select(Function(d, i) New UserRecord With {.Name = i.ToString, .PasswordInfo = New PasswordData With {.ClearTextPassword = "cat"}}).ToArray
- passwords.Select(Function(p) New With {.UserName = p.Name, .Password = PasswordData.ConvertBytesToHex(p.PasswordInfo.Password), .Salt = PasswordData.ConvertBytesToHex(p.PasswordInfo.Salt)}).Dump("All passwords are cat")
- Console.WriteLine("Now these are records in a database or file or any storage.
- Instead of names of 0-4 it could be user names.
- I could match user name 3 to get that record and then get the salt and load up a PasswordData instance like below.
- You don't need to store the values as hex. I just did that to show the values in a little easier to read format.")
- Dim rand As New Random
- Dim index As Integer = rand.Next(0, passwords.Length)
- Dim pw = passwords(index)
- Dim pwData As New PasswordData(pw.PasswordInfo.Salt, pw.PasswordInfo.Password)
- pwData.ToString.Dump("Password loaded from datasource")
- pwData.VerifyPassword("cat").Dump("Password is cat?")
- End Sub
- 'This just demonstrates basic password functionality. Storing passwords even as strings because of managed memory is no a good idea.
- 'This time I am not covering SecureStrings
- Class PasswordData
- Private Readonly enc As Encoding = Encoding.Unicode
- Sub New
- GenerateSalt
- End Sub
- Sub New(Salt As Byte(), Password As Byte())
- Me.Salt = Salt
- _PasswordBytes = Password
- End Sub
- Sub GenerateSalt()
- Dim tmp(63) As Byte
- Using rng As New Security.Cryptography.RNGCryptoServiceProvider()
- rng.GetNonZeroBytes(tmp)
- End Using
- Salt = tmp
- End Sub
- Private _PasswordBytes As Byte()
- Writeonly Property ClearTextPassword As String
- Set(value As String)
- _PasswordBytes = HashPassword(value)
- End Set
- End Property
- ReadOnly Property Password As Byte()
- Get
- Return _PasswordBytes
- End Get
- End Property
- Property Salt As Byte()
- Shared Function ConvertBytesToHex(bytes As Byte()) As String
- Return String.Join("", bytes.Select(Function(b) b.ToString("X2")))
- End Function
- Shared Function ConvertHexToBytes(Hex As String) As Byte()
- If Hex.Length Mod 2 <> 0 Then
- Throw New ArgumentException($"{Nameof(Hex)} must be a valid hex string of 2 characters per byte.", Nameof(Hex))
- End If
- Dim bytes As Byte() = New Byte(hex.Length \ 2 - 1) {}
- For i As Integer = 0 To hex.Length - 1 Step 2
- bytes(i \ 2) = Byte.Parse(Hex.Substring(i, 2), System.Globalization.NumberStyles.HexNumber)
- Next
- Return bytes
- End Function
- Function HashPassword(ClearText As String) As Byte()
- Dim pBytes = enc.GetBytes(ClearText).Concat(Salt).ToArray
- Using sha As System.Security.Cryptography.SHA512 = System.Security.Cryptography.SHA512CryptoServiceProvider.Create
- Return sha.ComputeHash(pbytes)
- End Using
- End Function
- Function VerifyPassword(ClearTextPassword As String) As Boolean
- Dim hashed = HashPassword(ClearTextPassword)
- Return Enumerable.SequenceEqual(_PasswordBytes, hashed)
- End Function
- Overrides Function ToString() As String
- Return $"{ConvertBytesToHex(_PasswordBytes)}{vbTab}{ConvertBytesToHex(Salt)}"
- End Function
- End Class
- Class UserRecord
- Property PasswordInfo As New PasswordData
- Property Name As String
- Public Overrides Function ToString() As String
- Return $"{Name}{vbTab}{PasswordData.ConvertBytesToHex(PasswordInfo.Password)}{vbTab}{PasswordData.ConvertBytesToHex(PasswordInfo.Salt)}"
- End Function
- End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement