Thursday, February 07, 2013

Working with Base64 Strings in PowerShell

Base64 is an encoding method that enables transfer of arbitrary binary data through restrictive networks. The most obvious, to me anyway, case of this is email. The SMTP protocol was designed to transfer 7-bit (aka ASCII) characters. If you want to transmit binary data over such a 7-bit transport, you need to encode it some how – and that’s what Base64 does for you. There are loads of other uses for Base64.

For IT Pros, Base 64 can be encoded text that you need to see decoded. I got asked about this the other week in class. You can use .NET it’s current Unicode format using System.Convert and System.Text.Encoding. You can also covert Base 64 encoded strings back into Unicode by using the same .net methods, as you can see in this screen shot:

 

SNAGHTML76cd8c86

That works, when you can remember the magic incantation(s) but something simpler would be nice, my students mentioned. The obvious answer is to just use PowerShell’s Extensible Type System (ETS) and add a couple of properties onto System.String objects representing encoded/decoded Base 64. This is easy – just create a types.ps1xml file (mine is named My.Types.Ps1xml) that looks like this:

<Types>
<Type>
  <Name>System.String</Name>
    <Members>
      <ScriptProperty>
        <Name>ToBase64String</Name>
          <GetScriptBlock>
             [System.Convert]::ToBase64String([System.
Text.Encoding]::Unicode.GetBytes($this))
          </GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>FromBase64String</Name>
          <GetScriptBlock>
             [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($this))
          </GetScriptBlock>
      </ScriptProperty>
    </Members>
  </Type>
</Types>

With that file saved you can add it into your PowerShell environment by using the Update-TypeData cmdlet, specifying your PS1XML file (e.g. Update-TypeData c:\foo\My.Types.PS1XML). Once that’s complete, System.String in nicely extended, as you can see here:

SNAGHTML7708cf12

I have added this bit of type-XML to my type extensions file that I load in my $Profile – which means the ability to covert from/to Base64 is, as it were, now baked into PowerShell.

[Later]
Thanks to Bryan Price for catching two typos in this post.

 

4 comments:

Bryan Price said...

A couple of typos.

It's test.ps1xml

There is not a period between ps1 and xml.

Also, I couldn't figure out what the problem was, but the last line of that file needs to be , with a /.

Thomas said...

Thanks for the catch(es) - these are now fixed, with a bit more detail added just in case.

This shows how typing (vs cut/pasting) is error prone!

The article has been fixed.

Bryan Price said...

I'm glad you could figure out what I had typed. I didn't realize that Blogger had simply removed the element.

<Types>

Thomas said...

As soon as I looked at the XML, I could see the issue. I cut the element from my own ps1xml file (which has a bunch more types!), and manually added in the and the closing tag - just forgot to close it properly.

Anyway - thanks for the catch!