Base64 has 64 possible values between 0 and 63. Each value (an index) has a character associated with it. The characters, in order, are A to Z, then a to z, then 0 to 9, and finally + and /. The = character is used as a padding character.
The base64 index 9 is the character J, index 56 is the character 4, and so on. We can have PowerShell make this array for us:
[char[]]$base64Characters = [int][char]'A'..[int][char]'Z' + [int][char]'a'..[int][char]'z' + [int][char]'0'..[int][char]'9' $base64Characters += '+', '/'
The following process is used to convert the ASCII string He to base64.
Convert the characters to bytes:
ASCII |
H |
e |
Code |
72 |
101 |
PowerShell can convert characters to ASCII values using the following:
[int][char]'H' [int][char]'e'
To illustrate the process, the two values are converted into bits:
01001000 01100101
The Convert class can perform this step in PowerShell:
[Convert]::ToString([int][char]'H', 2).PadLeft(8, '0') [Convert]::ToString([int][char]'e', 2).PadLeft(8, '0')
Base64 uses a six-bit boundary (instead of eight), that gives three distinct indexes:
010010 = 2 + 16 = 18 000110 = 2 + 4 = 6 010100 = 4 + 16 = 20 # Padded on the right to make 6 bits
These indexes have base64 characters associated with them, S, G, and U in turn.
The base64 string now needs padding until it fits into a sequence of bytes (is divisible by 8). The entire process, including the padding, is shown following:
The process can be implemented in PowerShell, even if it is slower than Convert.ToBase64String. In this example, the bits are treated as a string:
function ConvertTo-Base64 { param( [string]$String ) # Generate the base64 character set [char[]]$base64Characters = [int][char]'A'..[int][char]'Z' + [int][char]'a'..[int][char]'z' + [int][char]'0'..[int][char]'9' $base64Characters += '+', '/' [String]$bits = $string.ToCharArray() | ForEach-Object { [Convert]::ToString([int][char]$_, 2).PadLeft(8, '0') } $bits = $bits -replace ' ' $base64String = '' # Get the 6-bit fragments and convert each to an index for ($i = 0; $i -lt $bits.Length; $i += 6) { # Get the bits for the index if ($bits.Length - $i -lt 6) { # If fewer than 6 characters remain, get all of them $indexBits = $bits.Substring($i, $bits.Length - $i) } else { # Get 6 characters $indexBits = $bits.Substring($i, 6) } # Pad the right so the 6-bit value is correctly padded # then pad the left so it can be converted to a byte $indexBits = $indexBits.PadRight(6, '0').PadLeft(8, '0') # Convert the bit string to a byte $index = [Convert]::ToByte($indexBits, 2) # Get the base64 character $base64String += $base64Characters[$index] } # Pad the base64 string until length is divisible by 6 and 8 $length = $bits.Length while ($length % 8 -ne 0 -or $length % 6 -ne 0) { if ($length % 6 -eq 0) { # Add the padding character $base64String += '=' } $length++ } return $base64String }