Search code examples
powershellregistry

How to convert a hash string to byte array in PowerShell?


When my scripts run, I read a hash, and I would like to write it to the registry. I figured out that the following command will do it:

New-ItemProperty  $RegPath -Name $AttrName -PropertyType Binary -Value $byteArray

I also found the How to set a binary registry value (REG_BINARY) with PowerShell?.

However all answers suppose that the string is in form of:

"50,33,01,00,00,00,00,00,...."

but I only can read my hash in the following form:

"F5442930B1778ED31A....."

I can not figure out, how can I convert this to a byte array, with values F5, 44 etc.


Solution

  • vonPryz sensibly suggests simply storing the hash directly as a string (REG_SZ) in the registry.

    If you really want to store the data as type REG_BINARY, i.e., as an array of bytes, you must convert back and forth between the string representation.

    To convert to a [byte[]] array (using a shortened sample hash string):

    PS> [byte[]] -split ('F54429' -replace '..', '0x$& ')
    245 # 1st byte: decimal representation of 0xF5
    68  # 2nd byte: decimal representation of 0x44
    41  # ...
    

    -replace '..', '0x$& ' prefixes each pair of characters (hex digits) - .., referenced in the replacement operand as $& - with 0x and inserts a space afterwards. -split splits the resulting string into an array of 0xHH strings (H representing a hex digit), which PowerShell's automatic type conversions recognize as the elements of a [byte[]] array in a cast. In other words: the above is the equivalent of:
    [byte[]] ('0xF5', '0x44', '0x29')

    The above is PowerShell's default output representation of resulting array
    [byte[]] (0xF5, 0x44, 0x29).

    Update: In PowerShell (Core) 7.1+ / .NET 5+ , a simpler solution is now available, via the new [System.Convert]::FromHexString() and [System.Convert]::ToHexString() methods:

    # PowerShell (Core) 7.1+ / .NET 5+
    # -> (0xF5, 0x44, 0x29)
    [System.Convert]::FromHexString('F54429')
    
    # -> 'F54429'
    [System.Convert]::ToHexString([byte[]] (0xF5, 0x44, 0x29))
    

    To convert from a [byte[]] array (back to a string):

    [System.BitConverter]::ToString() outputs two-hex-digit representations separated with -, so to get the desired representation, all - instances must be removed, using a -replace operation here:

    # -> 'F54429'
    [System.BitConverter]::ToString([byte[]] (0xf5, 0x44, 0x29)) -replace '-'
    

    To put it all together:

    # Sample hash string.
    $hashString = 'F54429'
    
    # Convert the hash string to a byte array.
    $hashByteArray = [byte[]] -split ($hashString -replace '..', '0x$& ')
    
    # Create a REG_BINARY registry value from the byte array.
    Set-ItemProperty -LiteralPath HKCU:\ -Name tmp -Type Binary -Value $hashByteArray
    
    # Read the byte array back from the registry (PSv5+)
    $hashByteArray2 = Get-ItemPropertyValue -LiteralPath HKCU:\ -Name tmp
    
    # Convert it back to a string.
    $hashString2 = [System.BitConverter]::ToString($hashByteArray2) -replace '-'
    
    # (Clean up.)
    Remove-ItemProperty -LiteralPath HKCU:\ -Name tmp