In a previous article, I demonstrated how we could utilize PowerShell to get the MACTripleDES, MD5, RIPEMD160, SHA1, SHA256, SHA384 or SHA512 HASH of a string
I figured I’d also demonstrate how it can be done using plain vanilla VBA, no need for PowerShell at all.
The Code
The Main Function
'---------------------------------------------------------------------------------------
' Procedure : Crypto_GetStringHash
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Returns the specified Hash for the supplied string.
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding -> none required
' Dependencies: Requires ReadStringAsBinary()
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sInput : String to get the Hash of
' sHashAlgorithm : Algorithm to use for the Hashing: MACTripleDES, MD5, RIPEMD160
' SHA1, SHA256, SHA384 or SHA512
'
' Usage:
' ~~~~~~
' ? Crypto_GetStringHash("String to get the Hash of", "MD5")
' Returns -> 69563FFABD2E9D63BF83567F1B664C6
' ? Crypto_GetStringHash("String to get the Hash of", "SHA256")
' Returns -> 823C17899E52A815FD90EEDDAB5C67B88C1E868E81B88F5ECEFA1D3B17D753
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2023-01-03 Initial Public Release
' 2 2025-08-22 Fix issue reported by Michael
'---------------------------------------------------------------------------------------
Function Crypto_GetStringHash(sInput As String, sHashAlgorithm As String) As String
On Error GoTo Error_Handler
Dim oSSCrypto As Object
Dim aFileBytes() As Byte
Dim hashBytes() As Byte
Dim sOutput As String
Dim lCounter As Long
Select Case sHashAlgorithm
Case "MACTripleDES"
Set oSSCrypto = CreateObject("System.Security.Cryptography.MACTripleDES") '
Case "MD5"
Set oSSCrypto = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider") '128 bits
Case "RIPEMD160"
Set oSSCrypto = CreateObject("System.Security.Cryptography.RIPEMD160Managed") '160 bits
Case "SHA1"
Set oSSCrypto = CreateObject("System.Security.Cryptography.SHA1Managed") '160 bits
Case "SHA256"
Set oSSCrypto = CreateObject("System.Security.Cryptography.SHA256Managed") '256 bits
Case "SHA384"
Set oSSCrypto = CreateObject("System.Security.Cryptography.SHA384Managed") '384 bits
Case "SHA512"
Set oSSCrypto = CreateObject("System.Security.Cryptography.SHA512Managed") '512 bits
Case Else
'MsgBox ""
GoTo Error_Handler_Exit
End Select
' Convert input string to bytes
aFileBytes = StrConv(sInput, vbFromUnicode)
' Compute the hash
hashBytes = oSSCrypto.ComputeHash_2(aFileBytes)
' Convert hash bytes to hex string
For lCounter = LBound(hashBytes) To UBound(hashBytes)
sOutput = sOutput & LCase(Right("0" & Hex(hashBytes(lCounter)), 2))
Next
Crypto_GetStringHash = sOutput
Error_Handler_Exit:
On Error Resume Next
Set oSSCrypto = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: Crypto_GetStringHash" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
The Helper Function
The above relies on one helper function:
'---------------------------------------------------------------------------------------
' Procedure : ReadStringAsBinary
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Converts the supplied string to a binary array
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding -> None required
' Early Binding -> Microsoft ActiveX Data Objects X.X Library
' Based off of ReadFileAsBinary()
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sInput : String to be converted
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2023-01-03 Initial Public Release
'---------------------------------------------------------------------------------------
Public Function ReadStringAsBinary(ByVal sInput As String) As Variant
On Error GoTo Error_Handler
'#Const EarlyBind = 1 'Use Early Binding
#Const EarlyBind = 0 'Use Late Binding
#If EarlyBind Then
Dim oADOStream As ADODB.Stream
#Else
Dim oADOStream As Object
Const adTypeBinary = 1
#End If
Dim aStringBytes() As Byte
#If EarlyBind Then
Set oADOStream = New ADODB.Stream
#Else
Set oADOStream = CreateObject("ADODB.Stream")
#End If
With oADOStream
.Charset = "utf-8"
.Open
.WriteText sInput
.Flush
.Position = 0
.Type = adTypeBinary
.Position = 3 'no bom
aStringBytes() = .Read
End With
ReadStringAsBinary = aStringBytes()
Error_Handler_Exit:
On Error Resume Next
If Not oADOStream Is Nothing Then
oADOStream.Close
Set oADOStream = Nothing
End If
Exit Function
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Source: ReadStringAsBinary" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Function
Usage Example
The main function is very straightforward to use!
? Crypto_GetStringHash("Microsoft Access", "SHA512")
which will return/output a value of
C4208CAAFB46AFA43F246676C8331CAD5B955CF7C2CFE4B4D3E404C75F242E16FE59A41C58984587C6FEAA93C9ED0824C4FD4D6FA2B972BB769A27CD094
Or
? Crypto_GetStringHash("Any String You'd Like to Hash", "MD5")
which will return/output a value of
23954A0132E39C143EA654982F3CE0
Self-Healing Object Variables (SHOVs)
Just a quick note to mention that if this is the type of code you will need to run frequently within a solution, then this would be a great place to implement SHOVs to optimize the process and squeeze out every millisecond you can out of your code!
If this is of interest to you, then I’d urge you to review:


This method does require .Net 3.5 which does come pre-intalled with since most of the operating systems.