Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base32 Decoding

Tags:

c#

.net

base32

I have a base32 string which I need to convert to a byte array. And I'm having trouble finding a conversion method in the .NET framework. I can find methods for base64 but not for base32.

Convert.FromBase64String – something like this for base32 would be perfect.

Is there such a method in the framework or do I have to roll my own?

like image 844
trampster Avatar asked Mar 13 '09 03:03

trampster


People also ask

What is Base32 decode?

Base32 is a transfer encoding using a 32-character set, which can be beneficial when dealing with case-insensitive filesystems, spoken language or human memory.

What is a Base32 encoding?

Base32 encoding (and Base64) encoding is motivated by situations where you need to encode unrestricted binary within a storage or transport system that allow only data of a certain form such as plain text.

How do I find Base32 encoding?

Base32 is the base-32 numeral system. It uses a set of 32 digits, each of which can be represented by 5 bits (25). One way to represent Base32 numbers in a human-readable way is by using a standard 32-character set, such as the twenty-two upper-case letters A–V and the digits 0-9.


2 Answers

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: https://www.rfc-editor.org/rfc/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");     }  } 
like image 82
Shane Avatar answered Sep 29 '22 16:09

Shane


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;       } } 
like image 29
Christian C. Salvadó Avatar answered Sep 29 '22 17:09

Christian C. Salvadó