Get a String Hash using VBA

Since I was already working on Get a File Hash using VBA it made sense to look into how one could hash a string directly.

The basic principle remains identical, in the larger sense, that is I use VBA to run a PowerShell script and return the generated Hash, but this time we need to use the -InputStream parameter to be able to use a string directly. I won’t bore you with the detail, you can review the code for yourself.

'---------------------------------------------------------------------------------------
' Procedure : PS_GetStringHash
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Returns the specified Hash for the supplied string.
'             Utilizes PowerShell to perform the Hashing.
' 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 PS_GetOutput()
'
' 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:
' ~~~~~~
' PS_GetStringHash("Testing The Code A Little Bit", "MD5")
'   Returns -> D2A8E6028DEDC41F87E133E036DCCDE2
' PS_GetStringHash("Testing The Code A Little Bit", "RIPEMD160")
'   Returns -> 2037F4F018759E0EC813213CA36ACC20236891D8
' PS_GetStringHash("Testing The Code A Little Bit", "SHA256")
'   Returns -> FB58DAE56E917CD5F5B4A5DEFDEB46B0222E09C660226A69D19381442ABBA51D
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2021-10-06              Initial Public Release
' 2         2022-11-22              Remove trailing vbCrLf per comment by Leslie Desser
'---------------------------------------------------------------------------------------
Function PS_GetStringHash(sInput As String, sHashAlgorithm As String) As String
    Dim sPSCmd                As String

    On Error GoTo Error_Handler

    Select Case sHashAlgorithm
        Case "MACTripleDES", "MD5", "RIPEMD160", "SHA1", "SHA256", "SHA384", "SHA512"
        Case Else
            MsgBox "Unknown Algorithm", vbCritical Or vbOKOnly, "Operation Aborted"
            GoTo Error_Handler_Exit
    End Select
    sPSCmd = "(Get-FileHash -InputStream ([System.IO.MemoryStream]::" & _
             "New([System.Text.Encoding]::ASCII.GetBytes('" & sInput & "'))) " & _
             "-Algorithm " & sHashAlgorithm & ").Hash"
    PS_GetStringHash = PS_GetOutput(sPSCmd)
    PS_GetStringHash = Replace(PS_GetStringHash, vbCrLf, "")

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: PS_GetStringHash" & 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

So, as you can see, using VBA, we can now employ some very powerful PowerShell cmdlets. Thus, we can execute a, one line, PowerShell cmd and get what we are after!

As explained in the PowerShell Get-FileHash documentation, we can use any of 7 different hashing algorithms:

  • MACTripleDES
  • MD5
  • RIPEMD160
  • SHA1
  • SHA256
  • SHA384
  • SHA512

thus making this function quite versatile.

A Few Resources on the Subject

4 responses on “Get a String Hash using VBA

  1. Leslie Desser

    The returned hash seems to have a CrLf at the end.
    Left(PS_GetStringHash, Len(PS_GetStringHash)-2) returns visually the same hash string.
    Is this intentional? Is the CrLf part of the hash?

  2. Leslie desser

    Correction:
    You reference your Fn PS_GetOutput above but do not provide a link to it. I went hunting and looks like picked up an old version.
    I just tripped over an issue and then came across your ‘clipboard’ version and that does not have the issue with the CrLf (and gets rid of the flash)

    My issue is some PS code that returns the PC IP address very neatly and works fine when pasted into the PS window:
    (Get-NetIPConfiguration | Where-Object {$_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.Status -ne “Disconnected”}).IPv4Address.IPAddress

    Using your your old code it returned an empty string. Using your clipboard version it returns the existing value from the clipboard (the value that was there before running the function). That sounds like that in both versions the script being run returns nothing (or fails) so the old value remains in the clipboard.

    I wonder why the script is OK in the PS window but not when executed via your code.
    Your code works fine with your Hash function – for which many thanks.

  3. Leslie Desser

    The version using the clipboard does not have this problem. I suspect the issue is to do with writing a temporary text file which then adds the CrLf.

    However, there is a side-effect with using the clipboard approach – the user will lose whatever was previously stored in the clipboard. The other side of the coin – the clipboard now has what was returned by the function.
    This ‘leakage’ may be an issue in some cases.

    To cater for these points, it really needs to store the old clipboard value and restore it before the code ends.