Logo




Subscribe:
RSS 2.0 | Atom 1.0
Categories:

Sign In


[Giagnocavo]Michael::Write()

 Tuesday, January 13, 2004
Base32 in .NET
I haven't seen any .NET Base32 implementations, but various people have expressed interest in having some simpler way to represent binary data (such as an encrypted keycode).  So, I'm posting a sample Base32 encoding.  Note that this does not conform to the Base32 standard encoding, but uses it's own set of characters (useful for keycodes, where we don't want to have to differentiate between 0 and O.  Thanks to Juan Gabriel for making the code much better :).

Update 2004-2-5: Thanks to Philippe Cheng for fixing a bug that caused extra (harmless) output. (See comments for details).

using System;
using System.Text;
 
public sealed class Base32 {
 
      // the valid chars for the encoding
      private static string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP";
 
      /// <summary>
      /// Converts an array of bytes to a Base32-k string.
      /// </summary>
      public static string ToBase32String(byte[] bytes) {
            StringBuilder sb = new StringBuilder();         // holds the base32 chars
            byte index;
            int hi = 5;
            int currentByte = 0;
 
            while (currentByte < bytes.Length) {
                  // do we need to use the next byte?
                  if (hi > 8) {
                        // get the last piece from the current byte, shift it to the right
                        // and increment the byte counter
                        index = (byte)(bytes[currentByte++] >> (hi - 5));
                        if (currentByte != bytes.Length) {
                              // if we are not at the end, get the first piece from
                              // the next byte, clear it and shift it to the left
                              index = (byte)(((byte)(bytes[currentByte] << (16 - hi)) >> 3) | index);
                        }
 
                        hi -= 3;
                  } else if(hi == 8) {
                        index = (byte)(bytes[currentByte++] >> 3);
                        hi -= 3;
                  } else {
 
                        // simply get the stuff from the current byte
                        index = (byte)((byte)(bytes[currentByte] << (8 - hi)) >> 3);
                        hi += 5;
                  }
 
                  sb.Append(ValidChars[index]);
            }
 
            return sb.ToString();
      }
 
 
      /// <summary>
      /// Converts a Base32-k string into an array of bytes.
      /// </summary>
      /// <exception cref="System.ArgumentException">
      /// Input string <paramref name="s">s</paramref> contains invalid Base32-k characters.
      /// </exception>
      public static byte[] FromBase32String(string str) {
            int numBytes = str.Length * 5 / 8;
            byte[] bytes = new Byte[numBytes];
 
            // all UPPERCASE chars
            str = str.ToUpper();
 
            int bit_buffer;
            int currentCharIndex;
            int bits_in_buffer;
 
            if (str.Length < 3) {
                  bytes[0] = (byte)(ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5);
                  return bytes;
            }
 
            bit_buffer = (ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5);
            bits_in_buffer = 10;
            currentCharIndex = 2;
            for (int i = 0; i < bytes.Length; i++) {
                  bytes[i] = (byte)bit_buffer;
                  bit_buffer >>= 8;
                  bits_in_buffer -= 8;
                  while (bits_in_buffer < 8 && currentCharIndex < str.Length) {
                        bit_buffer |= ValidChars.IndexOf(str[currentCharIndex++]) << bits_in_buffer;
                        bits_in_buffer += 5;
                  }
            }
 
            return bytes;
      }
}

 
Code | Security
Tuesday, January 13, 2004 1:22:46 PM UTC  #    Comments [3]  |  Trackback Tracked by:
"http://tpoaef7.biz/james-blunt-lyrics.html" (http://tpoaef7.biz/james-blunt-lyr... [Pingback]


Thursday, January 29, 2004 11:07:59 PM UTC
I believe there's a bug in the code. It happens when the number of bits is an exact multiple of 5 (a 5 byte array for example) and the algorithm continues even though it ran out of bits. So when you generate Base32 from a 5 byte array it will always append "Q" at the end because Q it at index 0.

The Fix:
In ToBase32String...
if(hi > 8)
{
blah blah
}
// BEGIN INSERTED CODE
else if(hi == 8)
{
index = (byte)(bytes[currentByte++] >> 3);
hi -= 3;
}
// END INSERTED CODE
else
{
blah blah
}
Saturday, January 31, 2004 3:08:49 AM UTC
Holy cannoli! It does have a bug! Thanks for the feedback, Philippe. Mike is surely going to make the changes necessary. All the tests we did were to check for "round trip" correctness, so, this bug never popped up. Nice catch!

-JG
Thursday, February 05, 2004 10:32:08 PM UTC
Thanks Philippe, I added the fix!
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview