VBS: Decoding Base64 Strings (in 10 lines of code)

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

Advertisements

About Kristopher Bash
Kris is a Senior Program Manager at Microsoft, working on UNIX and Linux management features in Microsoft System Center. Prior to joining Microsoft, Kris worked in systems management, server administration, and IT operations for nearly 15 years.

5 Responses to VBS: Decoding Base64 Strings (in 10 lines of code)

  1. David Gibbons says:

    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�

    • Kristopher Bash says:

      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

    • kanwaljit says:

      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

  2. Kristopher Bash says:

    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.

    • Kristopher Bash says:

      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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: