Contacted Tomas last Friday for some help; because I couldn't get it to work.
But finally I managed to get it to work. The answer Tomas provided contains all the needed components, however I got a hard time to implement it. Especially the Crockford's Base32.
I've created a PowerShell function for it. Hopefully it can help more people out. Like what Tomas already wrote:
- Convert to UTF16LE; in PowerShell this is a convert to Unicode (which automatically creates a UTF16 Little Endian format. (When you ouput the Byte array it will mostly contain the character followed by an '0' byte).
- Then compute a SHA256 on the whole byte array and pull the first 8 bytes from it. And put the result into a byte array.
- The hard part for me; Crockford's Base32 encoding. Base32 is a 5bit encoding; so we need to read 5 bits at a time. So I converted the whole byte array to a binary string.
Padding it with zeros to 65 characters; because it has to be a multiple of 5.
Then read 5 bits, convert it to decimal. And lookup the decimal index in de encoding string. Read the character on this index and add it to a string. Repeat with every 5 bits.
Final string should be the PublisherId.
Tomas; thanks for your help.
Function Get-PublisherIdFromPublisher ($Publisher) {
$EncUTF16LE = [system.Text.Encoding]::Unicode
$EncSha256 = [System.Security.Cryptography.HashAlgorithm]::Create("SHA256")
# Convert to UTF16 Little Endian
$UTF16LE = $EncUTF16LE.GetBytes($Publisher)
# Calculate SHA256 hash on UTF16LE Byte array. Store first 8 bytes in new Byte Array
$Bytes = @()
(($EncSha256.ComputeHasH($UTF16LE))[0..7]) | % { $Bytes += '{0:x2}' -f $_ }
# Convert Byte Array to Binary string; Adding padding zeros on end to it has 13*5 bytes
$BytesAsBinaryString = -join $Bytes.ForEach{ [convert]::tostring([convert]::ToByte($_,16),2).padleft(8,'0') }
$BytesAsBinaryString = $BytesAsBinaryString.PadRight(65,'0')
# Crockford Base32 encode. Read each 5 bits; convert to decimal. Lookup position in lookup table
$Coded = $null
For ($i=0;$i -lt (($BytesAsBinaryString.Length)); $i+=5) {
$String = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
[int]$Int = [convert]::Toint32($BytesAsBinaryString.Substring($i,5),2)
$Coded += $String.Substring($Int,1)
}
Return $Coded.tolower()
}