Visual Basic for Applications/String Hashing in VBA
< Visual Basic for ApplicationsSummary
- A hash is an output string that resembles a pseudo random sequence, and is essentially unique for any string that is used as its starting value. Hashes cannot be easily cracked to find the string that was used in their making and they are very sensitive to input change. That is to say, just a change in one character at the start will produce a completely different output. Hashes can be used as the basis of pseudo random character tables, and although not purely random, such methods can produce output quality that is at least as good as the in-built Rnd() function of VBA..
- The use of a hash allows programmers to avoid embedding password strings in their code, where inspection of the memory space might reveal the necessary access details. Instead, a user's password is hashed and compared with a stored hash on-the-fly, only when needed. The assumption is that the intruder does not have access to apply any found hash internally. Because the hash is long and cannot be reverse-engineered to find the password, the intruder cannot mimic the user via the customer access route.
- Hashes can also be made from entire files, and the code for doing so differs only slightly from the string hashing versions given below. The main difference in file hashing is that the file is first turned into a string before using conventional techniques. Code is given elsewhere in this series for file hashing. String hashes will produce an output even when the empty string is used as a starting point, unlike for file hashing where an empty text file can raise errors.
- This VBA code is not specific for any one application, so it will work in any of say, MS Word, MS Excel, or MS Access. These code versions include options for base-64 output or hex.
Code Listings
The VBA code below generates the digests for the MD5, SHA1, SHA2-256, SHA2-384, and SHA2-512 hashes, for strings, in either of the hex or base-64 output formats. These codings each make use of MS Office's built-in functions, and provide consistent results. It has been noted that original implementations elsewhere for the same digests can differ widely in their outputs.
Option Explicit
Sub Test()
'run this to test sha1, sha2/256, or sha2/512
Dim sIn As String, sOut As String, bB64 As Boolean, sH As String
'insert the text to hash within the sIn quotes
'note that this would usually be some private string
sIn = ""
'select as required
'bB64 = False 'output hex
bB64 = True 'output base-64
'enable any one
'sH = MD5(sIn, bB64)
'sH = SHA1(sIn, bB64)
'sH = SHA256(sIn, bB64)
'sH = SHA384(sIn, bB64)
sH = SHA512(sIn, bB64)
Debug.Print sH & vbNewLine & Len(sH) & " characters in length"
MsgBox sH & vbNewLine & Len(sH) & " characters in length"
End Sub
Public Function MD5(ByVal sIn As String, Optional bB64 As Boolean = 0) As String
'Set a reference to mscorlib 4.0 64-bit
'Test with empty string input:
'Hex: d41d8cd98f00...etc
'Base-64: 1B2M2Y8Asg...etc
Dim oT As Object, oMD5 As Object
Dim TextToHash() As Byte
Dim bytes() As Byte
Set oT = CreateObject("System.Text.UTF8Encoding")
Set oMD5 = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
TextToHash = oT.GetBytes_4(sIn)
bytes = oMD5.ComputeHash_2((TextToHash))
If bB64 = True Then
MD5 = ConvToBase64String(bytes)
Else
MD5 = ConvToHexString(bytes)
End If
Set oT = Nothing
Set oMD5 = Nothing
End Function
Function SHA1(sIn As String, Optional bB64 As Boolean = 0) As String
'Set a reference to mscorlib 4.0 64-bit
'Test with empty string input:
'40 Hex: da39a3ee5e6...etc
'28 Base-64: 2jmj7l5rSw0yVb...etc
Dim oT As Object, oSHA1 As Object
Dim TextToHash() As Byte
Dim bytes() As Byte
Set oT = CreateObject("System.Text.UTF8Encoding")
Set oSHA1 = CreateObject("System.Security.Cryptography.SHA1Managed")
TextToHash = oT.GetBytes_4(sIn)
bytes = oSHA1.ComputeHash_2((TextToHash))
If bB64 = True Then
SHA1 = ConvToBase64String(bytes)
Else
SHA1 = ConvToHexString(bytes)
End If
Set oT = Nothing
Set oSHA1 = Nothing
End Function
Function SHA256(sIn As String, Optional bB64 As Boolean = 0) As String
'Set a reference to mscorlib 4.0 64-bit
'Test with empty string input:
'64 Hex: e3b0c44298f...etc
'44 Base-64: 47DEQpj8HBSa+/...etc
Dim oT As Object, oSHA256 As Object
Dim TextToHash() As Byte, bytes() As Byte
Set oT = CreateObject("System.Text.UTF8Encoding")
Set oSHA256 = CreateObject("System.Security.Cryptography.SHA256Managed")
TextToHash = oT.GetBytes_4(sIn)
bytes = oSHA256.ComputeHash_2((TextToHash))
If bB64 = True Then
SHA256 = ConvToBase64String(bytes)
Else
SHA256 = ConvToHexString(bytes)
End If
Set oT = Nothing
Set oSHA256 = Nothing
End Function
Function SHA384(sIn As String, Optional bB64 As Boolean = 0) As String
'Set a reference to mscorlib 4.0 64-bit
'Test with empty string input:
'96 Hex: 38b060a751ac...etc
'64 Base-64: OLBgp1GsljhM2T...etc
Dim oT As Object, oSHA384 As Object
Dim TextToHash() As Byte, bytes() As Byte
Set oT = CreateObject("System.Text.UTF8Encoding")
Set oSHA384 = CreateObject("System.Security.Cryptography.SHA384Managed")
TextToHash = oT.GetBytes_4(sIn)
bytes = oSHA384.ComputeHash_2((TextToHash))
If bB64 = True Then
SHA384 = ConvToBase64String(bytes)
Else
SHA384 = ConvToHexString(bytes)
End If
Set oT = Nothing
Set oSHA384 = Nothing
End Function
Function SHA512(sIn As String, Optional bB64 As Boolean = 0) As String
'Set a reference to mscorlib 4.0 64-bit
'Test with empty string input:
'128 Hex: cf83e1357eefb8bd...etc
'88 Base-64: z4PhNX7vuL3xVChQ...etc
Dim oT As Object, oSHA512 As Object
Dim TextToHash() As Byte, bytes() As Byte
Set oT = CreateObject("System.Text.UTF8Encoding")
Set oSHA512 = CreateObject("System.Security.Cryptography.SHA512Managed")
TextToHash = oT.GetBytes_4(sIn)
bytes = oSHA512.ComputeHash_2((TextToHash))
If bB64 = True Then
SHA512 = ConvToBase64String(bytes)
Else
SHA512 = ConvToHexString(bytes)
End If
Set oT = Nothing
Set oSHA512 = Nothing
End Function
Function ConvToBase64String(vIn As Variant) As Variant
Dim oD As Object
Set oD = CreateObject("MSXML2.DOMDocument")
With oD
.LoadXML "<root />"
.DocumentElement.DataType = "bin.base64"
.DocumentElement.nodeTypedValue = vIn
End With
ConvToBase64String = Replace(oD.DocumentElement.Text, vbLf, "")
Set oD = Nothing
End Function
Function ConvToHexString(vIn As Variant) As Variant
Dim oD As Object
Set oD = CreateObject("MSXML2.DOMDocument")
With oD
.LoadXML "<root />"
.DocumentElement.DataType = "bin.Hex"
.DocumentElement.nodeTypedValue = vIn
End With
ConvToHexString = Replace(oD.DocumentElement.Text, vbLf, "")
Set oD = Nothing
End Function
This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.