Listing 1: A Custom Base64 Encoder
public class MyConverter
{
public static string ToBase64String(byte[] value)
{
// Base64 chars
char[] base64Chars = new char[]
{ 'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/' };
int numBlocks;
int padBytes;
if ((value.Length % 3) == 0)
{
numBlocks = value.Length / 3;
padBytes = 0;
}
else
{
numBlocks = 1 + (value.Length / 3);
padBytes = 3 - (value.Length % 3);
}
if (padBytes < 0 || padBytes > 3)
throw new Exception("Fatal logic error in padding code");
// create a lengthened and padded input byte array
byte[] newValue = new byte[numBlocks * 3];
for (int i = 0; i < newValue.Length; ++i) // not really necesary
newValue[i] = 0;
for (int i = 0; i < value.Length; ++i)
newValue[i] = value[i];
byte[] resultBytes = new byte[numBlocks * 4];
char[] resultChars = new char[numBlocks * 4];
for (int i = 0; i < numBlocks; i++)
{
resultBytes[i * 4 + 0] =
(byte)((newValue[i * 3 + 0] & 0xFC) >> 2);
resultBytes[i * 4 + 1] =
(byte)((newValue[i * 3 + 0] & 0x03) << 4 |
(newValue[i * 3 + 1] & 0xF0) >> 4);
resultBytes[i * 4 + 2] =
(byte)((newValue[i * 3 + 1] & 0x0F) << 2 |
(newValue[i * 3 + 2] & 0xC0) >> 6);
resultBytes[i * 4 + 3] =
(byte)((newValue[i * 3 + 2] & 0x3F));
}
for (int i = 0; i < numBlocks * 4; ++i)
resultChars[i] = base64Chars[resultBytes[i]];
// pad the resultChars array tail with '=' chars
if (padBytes == 0)
;
else if (padBytes == 1)
resultChars[numBlocks * 4 - 1] = '=';
else if (padBytes == 2)
{
resultChars[numBlocks * 4 - 1] = '=';
resultChars[numBlocks * 4 - 2] = '=';
}
string s = new string(resultChars);
return s;
} // ToBase64String()
} // class MyConverter
Listing 2: A Custom Base64 Decoder
public static byte[] FromBase64String(string s)
{
// determine how many trailing '=' signs
int last = s.IndexOf('=');
int padCount = 0;
if (last == -1)
padCount = 0;
else if (last == s.Length - 1)
padCount = 1;
else if (last == s.Length - 2)
padCount = 2;
int numBlocks = s.Length / 4;
byte[] result = new byte[numBlocks * 3];
for (int i = 0; i < numBlocks; ++i)
{
byte[] scratch = new byte[4];
scratch[0] = ValueOf(s[i * 4 + 0]);
scratch[1] = ValueOf(s[i * 4 + 1]);
scratch[2] = ValueOf(s[i * 4 + 2]); // possibly '='
scratch[3] = ValueOf(s[i * 4 + 3]); // possibly '='
result[i * 3 + 0] =
(byte)((scratch[0] << 0x02) |
(scratch[1] & 0x30) >> 4) ;
result[i * 3 + 1] =
(byte)((scratch[1] & 0x0F) << 4 |
(scratch[2] & 0x3C) >> 2);
result[i * 3 + 2] =
(byte)((scratch[2] & 0x03) << 6 | scratch[3]);
}
byte[] finalResult = new byte[result.Length - padCount];
for (int i = 0; i < finalResult.Length; ++i)
finalResult[i] = result[i];
return finalResult;
} // ToByteArray()
private static byte ValueOf(char c) // value for Base64 character
{
if (c >= 'A' && c <= 'Z')
return (byte)((int)c - 65);
else if (c >= 'a' && c <= 'z')
return (byte)((int)c - 71);
else if (c >= '0' && c <= '9')
return (byte)((int)c + 4);
else if (c == '+')
return 62;
else if (c == '/')
return 63;
else
return 0;
}
Listing 3: Base64 Encoding Demo
static void Main(string[] args)
{
try
{
Console.WriteLine("\nStart Base64 encoding demo\n");
string seed = "Hello";
Console.WriteLine(" Seed string to generate some bytes is: '" + seed + "'");
byte[] b = System.Text.Encoding.ASCII.GetBytes(seed);
Console.WriteLine(" In hexadecimal encoding the bytes are:
" + BitConverter.ToString(b) + "\n");
Console.WriteLine("===============\n");
string s1 = Convert.ToBase64String(b);
Console.WriteLine(" Using Framework the Base64 encoding is: " + s1 + "\n");
string s2 = MyConverter.ToBase64String(b);
Console.WriteLine(" Using custom method Base64 encoding is: " + s2 + "\n");
Console.WriteLine("===============\n");
byte[] b1 = Convert.FromBase64String(s1);
string h1 = BitConverter.ToString(b1);
Console.WriteLine(" Using Framework the original bytes are: " + h1 + "\n");
byte[] b2 = MyConverter.FromBase64String(s2);
string h2 = BitConverter.ToString(b2);
Console.WriteLine(" Using custom method original bytes are: " + h2 + "\n");
Console.WriteLine("\nEnd demo");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Fatal: " + ex.Message);
Console.ReadLine();
}
} // Main()