VBS: Decoding Base64 Strings (in 10 lines of code)
September 11, 2009 5 Comments
This code snippet can be used to decode Base64 encoded strings into plain text, which I have found useful recently when working on VBscript scripts that require decoding the Base64-encoded SNMP community strings stored in OpsMgr. I thought it would be worth sharing.
Function Decode(strB64)
strXML = “<B64DECODE xmlns:dt=” & Chr(34) & _
“urn:schemas-microsoft-com:datatypes” & Chr(34) & ” ” & _
“dt:dt=” & Chr(34) & “bin.base64” & Chr(34) & “>” & _
strB64 & “</B64DECODE>”
Set oXMLDoc = CreateObject(“MSXML2.DOMDocument.3.0”)
oXMLDoc.LoadXML(strXML)
decode = oXMLDoc.selectsinglenode(“B64DECODE”).nodeTypedValue
set oXMLDoc = nothing
End Function
Kristopher,
Do you have a code snippet to encode to Base64? I’ve made attempts but they never match the strings within SCOM. I assume MS is doing something special with the string but I have not figured out what. Online Base64 decoders do some very interesting things when decoding…
Example:
String:
public_node_1
Base64:
cHVibGljX25vZGVfMQ==
SCOMBase64:
cAB1AGIAbABpAGMAXwBuAG8AZABlAF8AMQA=
Online Decoder:
p�u�b�l�i�c�_�n�o�d�e�_�1�
Ok, I got this figured out. There were two hang ups that I had to work through. In order to encode with the MSXML2.DOMDocument, the input has to be a byte array, and for this to work, the string that first has to converted from the default Ansi character set to Unicode. The issue I was having with the leading question mark character was because of the ADODB.Stream conversion inserting a Unicode byte order mark (bytes 1 and 2: FF FE) sequence into the Unicode stream.
So, this script looks to work and encode strings into Base64 strings that match the OpsMgr community strings. The function uses ADODB.Stream to convert the Ansi string into Unicode, then reads two bytes of the stream, effectively discarding the first two bytes, to get rid of the Byte Order Mark. The remaining bytes of the stream are read into a variable, which is then used with the MSXML2.DOMDocument to convert to Base64.
Function Encode(Str)
‘Use ADODB.Stream to write Ansi string to Unicode stream
Set objStream = CreateObject(“ADODB.Stream”)
objStream.Type = 2
objStream.Open
objStream.Charset = “unicode”
objStream.WriteText Str
objstream.Flush
‘Read the stream back as a byte array
objStream.Position = 0
objStream.Type = 1
temp = objstream.read(2) ‘read two bytes of the stream to discard the byte order mark
bArray = objStream.Read
objStream.Close
‘Convert byte array to Base64
set objXML = createobject(“MSXML2.DOMDocument.3.0”)
Set objNode = objXML.createElement(“b64”)
objNode.dataType = “bin.base64”
objNode.nodeTypedValue = bArray
Encode = objNode.Text
Set Stream = Nothing
set objNode = nothing
set objXML = nothing
End Function
Hi David:
This code works fine on windows xp but somehow i am getting error on tablet. Here is the situation. I have two computers one is where tomcat is installed on windows xp and if i uses this server then this code works fine and with other tablet if same tomcat is installed and i uses this server to any other workstation it throws error like “Object required” on the line
decode = oXMLDoc.selectsinglenode(“B64DECODE”).nodeTypedValue
please help
Thanks
Kanwaljit
This is a bit tricky. It’s remarkably easy to do in PowerShell, and returns the correct SCOM-friendly base64 string:
Param([string]$sText)
$encoded=[System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($sText))
write-host $encoded
$decoded=[System.Text.Encoding]::UNICODE.GetString([System.Convert]::FromBase64String($encoded))
write-host $decoded
In VBScript, you have to first convert the input string to a bytearray, and then you can use the MSXML2.DOMDocument menthod to encode the byte array to a Base64 string. I believe that the issue you are seeing with online Base64 encoders and many of the sample scripts is that they are not handling the unicode charset correctly. I’ve been playing around with a VBS script to do this, but haven’t quite figured it out. I can encode a string to Base64 and decode it, but it’s not matching the encoded string that OpsMgr is using.
It looks like the problem I am having with VBScript is the insertion of a leading ? character in the string. I haven’t been able to figure that out yet. I’ve tried using an encoding script that I found online (using ADODB.Stream first to convert to an x-ansi character set) and I get the same question mark as with the xml domdocument method. Frustrating.