Base32 Decoding


Answer :

I had a need for a base32 encoder/decoder, so I spent a couple hours this afternoon throwing this together. I believe it conforms to the standards listed here: http://tools.ietf.org/html/rfc4648#section-6.

public class Base32Encoding {     public static byte[] ToBytes(string input)     {         if (string.IsNullOrEmpty(input))         {             throw new ArgumentNullException("input");         }          input = input.TrimEnd('='); //remove padding characters         int byteCount = input.Length * 5 / 8; //this must be TRUNCATED         byte[] returnArray = new byte[byteCount];          byte curByte = 0, bitsRemaining = 8;         int mask = 0, arrayIndex = 0;          foreach (char c in input)         {             int cValue = CharToValue(c);              if (bitsRemaining > 5)             {                 mask = cValue << (bitsRemaining - 5);                 curByte = (byte)(curByte | mask);                 bitsRemaining -= 5;             }             else             {                 mask = cValue >> (5 - bitsRemaining);                 curByte = (byte)(curByte | mask);                 returnArray[arrayIndex++] = curByte;                 curByte = (byte)(cValue << (3 + bitsRemaining));                 bitsRemaining += 3;             }         }          //if we didn't end with a full byte         if (arrayIndex != byteCount)         {             returnArray[arrayIndex] = curByte;         }          return returnArray;     }      public static string ToString(byte[] input)     {         if (input == null || input.Length == 0)         {             throw new ArgumentNullException("input");         }          int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;         char[] returnArray = new char[charCount];          byte nextChar = 0, bitsRemaining = 5;         int arrayIndex = 0;          foreach (byte b in input)         {             nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));             returnArray[arrayIndex++] = ValueToChar(nextChar);              if (bitsRemaining < 4)             {                 nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);                 returnArray[arrayIndex++] = ValueToChar(nextChar);                 bitsRemaining += 5;             }              bitsRemaining -= 3;             nextChar = (byte)((b << bitsRemaining) & 31);         }          //if we didn't end with a full char         if (arrayIndex != charCount)         {             returnArray[arrayIndex++] = ValueToChar(nextChar);             while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; //padding         }          return new string(returnArray);     }      private static int CharToValue(char c)     {         int value = (int)c;          //65-90 == uppercase letters         if (value < 91 && value > 64)         {             return value - 65;         }         //50-55 == numbers 2-7         if (value < 56 && value > 49)         {             return value - 24;         }         //97-122 == lowercase letters         if (value < 123 && value > 96)         {             return value - 97;         }          throw new ArgumentException("Character is not a Base32 character.", "c");     }      private static char ValueToChar(byte b)     {         if (b < 26)         {             return (char)(b + 65);         }          if (b < 32)         {             return (char)(b + 24);         }          throw new ArgumentException("Byte is not a value Base32 value.", "b");     }  } 

Check this FromBase32String implementation for .NET found here.


Edit: The above link was dead; you can find an archived copy at archive.org

The actual code read:

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;       } } 

This is a really old question, but I happened to stumble on it wanting the same thing for OTP tokens. It turns out that there is base 32 functionality built into the OTP.NET package on NuGet:

Base32Encoding.ToBytes("(your base 32 string here)") 

The reverse is also possible:

Base32Encoding.ToString(new byte[] { /* your bytes here */ }) 

Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?