In fact, the algorithm of Base64 encryption and decryption is not very complicated, first defining 64-bit keys, 64 characters are fixed, but the order can vary with their own design. E.g:
Char [] Basetable = new char [64] {
'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', ' ', '/'};
Next, when encryption is for each character that needs to be encrypted, converted to one of the above 64 characters by a certain algorithm; and when decrypting, any one of the characters in the 64 characters is referred to in the character. . There are many ways to do every character, here is not introduced. It is important to note that "=" characters, it is very important in the base64 encryption algorithm, it is a role.
The following is the full code:
// ----------------------------- Base64 Class ----------------- ---------------------
/ / -------------------------------------------------------------------------------------------- ---------------------------------
// --- File: CLSBase64
// --- Description: The Class File to Encode String or Decode String in Base Algorith
// --- Author: knight
//--Date:OCT.8, 2005
/ / -------------------------------------------------------------------------------------------- ---------------------------------
// --------------------------- {base64 class} ------------------------------------------------------------------------------------------------------------------------------------------ ---------------------
Using system;
Namespace Base64
{
///
/// Summary Description for Clsbase64.
/// summary>
PUBLIC CLASS CLSBASE64 {
Private char [] Source;
PRIVATE CHAR [] Lookuptable;
Private Int Length, Length2, Length3;
PRIVATE INT blockCount;
PRIVATE INT PADDINGCOUNT;
Public CLSBase64 ()
{
//
// Todo: add constructor logic here
//
Source = NULL;
Length = Length2 = length3 = 0;
Blockcount = 0;
Paddingcount = 0;
}
///
/// Create Base64 char Array Using Default Base64 Char Array
/// summary>
/// param>
///
Private char [] createbase64char (ref char [] createpara)
{
Char [] Basetable = new char [64] {
'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', ' ', '/'};
const Int create_type = 8;
BYTE BPARAVALUE = 0;
BYTE BTEMP;
For (int i = 0; i { Btemp = (Byte) (CreatePara [i]); Switch (btemp% create_type) { Case 1: // 00000001 Btemp = (Byte) (btemp ^ 0x01); Break; Case 2: // 00000010bTemp = (BYTE) (btemp ^ 0x02); Break; Case 3: // 00000100 Btemp = (Byte) (btemp ^ 0x04); Break; Case 4: // 00001000 Btemp = (Byte) (btemp ^ 0x08); Break; Case 5: // 00010000 Btemp = (Byte) (btemp ^ 0x10); Break; Case 6: // 00100000 Btemp = (Byte) (btemp ^ 0x20); Break; Case 7: // 01000000 Btemp = (Byte) (btemp ^ 0x40); Break; DEFAULT: // 10000000 Btemp = (Byte) (btemp ^ 0x80); Break; } BPARAVALUE = (Byte) (BPaRue ^ Btemp); } CHAR chrtemp; INT NINDEX; Switch (bparavalue% create_type) { Case 1: // Exechange 0 <-> 1, 2 <-> 3, 4 <-> 5, 6 <-> 7 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; Basetable [NINDEX] = BaseTable [NINDEX 1]; BaseTable [NINDEX 1] = Chrtemp; Chrtemp = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = BaseTable [NINDEX 3]; BaseTable [NINDEX 3] = Chrtemp; Chrtemp = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = BaseTable [NINDEX 5]; BaseTable [NINDEX 5] = Chrtemp; Chrtemp = BaseTable [NINDEX 6]; Basetable [NINDEX 6] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; } Break; Case 2: // Exechange 0 <-> 2, 1 <-> 3, 4 <-> 6, 5 <-> 7 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; BaseTable [Nindex] = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX 3]; BaseTable [NINDEX 3] = Chrtemp; Chrtemp = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = BaseTable [NINDEX 6]; BaseTable [NINDEX 6] = Chrtemp; Chrtemp = baseteable [NINDEX 5]; BaseTable [NINDEX 5] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; } Break; Case 3: // Exechange 0 <-> 3, 1 <-> 2, 4 <-> 7, 5 <-> 6 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; BaseTable [NINDEX] = BaseTable [NINDEX 3]; BaseTable [NINDEX 3] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = Chrtemp; Chrtemp = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; Chrtemp = baseteable [NINDEX 5]; Basetable [NINDEX 5] = BaseTable [NINDEX 6]; BaseTable [NINDEX 6] = Chrtemp; } Break; Case 4: // mirror exechange For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; Basetable [NINDEX] = BaseTable [NINDEX CREATE_TYPE - 1]; BaseTable [NINDEX CREATE_TYPE - 1] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX CREATE_TYPE - 2]; BaseTable [NINDEX CREATE_TYPE - 2] = Chrtemp; Chrtemp = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = BaseTable [NINDEX CREATE_TYPE - 3]; BaseTable [NINDEX CREATE_TYPE - 3] = Chrtemp; Chrtemp = BaseTable [NINDEX 3]; BaseTable [NINDEX 3] = BaseTable [NINDEX CREATE_TYPE - 4]; BaseTable [NINDEX CREATE_TYPE - 4] = Chrtemp; } Break; Case 5: // Exechange 0 <-> 4, 1 <-> 5, 2 <-> 6, 3 <-> 7 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; Basetable [NINDEX] = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX 5]; BaseTable [NINDEX 5] = Chrtemp; Chrtemp = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = BaseTable [NINDEX 6]; BaseTable [NINDEX 6] = Chrtemp; Chrtemp = BaseTable [NINDEX 3]; Basetable [NINDEX 3] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; } Break; Case 6: // Exechange 0 <-> 5, 1 <-> 6, 2 <-> 7, 3 <-> 4 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; BaseTable [Nindex] = BaseTable [NINDEX 5]; BaseTable [NINDEX 5] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX 6]; BaseTable [NINDEX 6] = Chrtemp; Chrtemp = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; Chrtemp = BaseTable [NINDEX 3]; BaseTable [Nindex 3] = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = chrtemp; Break; Case 7: // exechange 0 <-> 6, 1 <-> 7, 2 <-> 4, 3 <-> 5 For (int i = 0; I { NINDEX = I * CREATE_TYPE; Chrtemp = baseteable [NINDEX]; BaseTable [Nindex] = BaseTable [NINDEX 6]; BaseTable [NINDEX 6] = Chrtemp; chrtemp = baseteable [NINDEX 1]; BaseTable [NINDEX 1] = BaseTable [NINDEX 7]; BaseTable [NINDEX 7] = Chrtemp; Chrtemp = BaseTable [NINDEX 2]; BaseTable [NINDEX 2] = BaseTable [NINDEX 4]; BaseTable [NINDEX 4] = Chrtemp; Chrtemp = BaseTable [NINDEX 3]; BaseTable [Nindex 3] = BaseTable [NINDEX 5]; BaseTable [NINDEX 5] = Chrtemp; } Break; DEFAULT: Break; } Return BaseTable; } /// /// Encode String At Specific Parameter /// summary> /// /// param> /// Public char [] getencoded (char [] Para Byte [] Input) { Length = input.length; IF ((Length% 3) == 0) { Paddingcount = 0; Blockcount = Length / 3; } Else { Paddingcount = 3- (Length% 3); // NEED TO Add Padding Blockcount = (Length Paddingcount) / 3; } Length2 = Length Paddingcount; // or blockcount * 3 Byte [] Source2; Source2 = new byte [length2]; // Copy Data over Insert Padding For (int x = 0; x { IF (x { Source2 [x] = INPUT [x]; } Else { Source2 [x] = 0; } } BYTE B1, B2, B3; Byte Temp, Temp1, Temp2, Temp3, Temp4; Byte [] buffer = new byte [blockcount * 4]; char [] result = new char [blockcount * 4]; For (int x = 0; x { B1 = source2 [x * 3]; B2 = source2 [x * 3 1]; B3 = Source2 [x * 3 2]; TEMP1 = (Byte) ((B1 & 252) >> 2); // first Temp = (BYTE) ((B1 & 3) << 4); TEMP2 = (BYTE) ((B2 & 240) >> 4); Temp2 = Temp; // Second Temp = (BYTE) ((B2 & 15) << 2); TEMP3 = (Byte) ((B3 & 192) >> 6); TEMP3 = Temp; // third TEMP4 = (Byte) (B3 & 63); // four Buffer [x * 4] = TEMP1; Buffer [x * 4 1] = TEMP2; Buffer [x * 4 2] = TEMP3; Buffer [x * 4 3] = TEMP4; } Lookuptable = CreateBase64char (REF Para ); For (int x = 0; x { Result [x] = Sixbit2Char (buffer [x]); } // Covert Last "a" S to "=", based on Paddingcount Switch (Paddingcount) { Case 0: Break; Case 1: Result [blockcount * 4-1] = '='; Break; Case 2: Result [blockcount * 4-1] = '='; Result [blockcount * 4-2] = '='; Break; DEFAULT: BREAK; } Return Result; } Private char sixbit2char (byte b) { IF ((b> = 0) && (b <= 63)) { Return Lookuptable [(int) B]; } Else { // Should not happen; Return ''; } } /// /// Decode String Using Specific Parameter /// summary> /// /// param> /// Public Byte [] getDecoded (char [] Para CHAR [] Input) { INT TEMP = 0; Source = INPUT; Length = input.length; IF ((Length% 4)! = 0) Return null; // the string is not encoded with my base64; // Find how Many Padding There Are While (INPUT [Length - Temp - 1] == '=' && Temp <3) { TEMP ; } IF (Temp == 3) Return null; // the string is not encoded with my base64; Paddingcount = temp; // Calculate the blockcount; // Assuming All Whitespace and carriage returns / newline were removed. Blockcount = Length / 4; Length2 = blockcount * 3; Byte [] buffer = new byte [length]; // first conversion result Byte [] buffer2 = new byte [length2]; // decoded array with Padding Lookuptable = CreateBase64char (REF Para ); FOR (int x = 0; x { Buffer [x] = char2sixbit (source [x]); } BYTE B, B1, B2, B3; Byte Temp1, Temp2, Temp3, Temp4 For (int x = 0; x { Temp1 = buffer [x * 4]; Temp2 = buffer [x * 4 1]; TEMP3 = Buffer [x * 4 2]; TEMP4 = Buffer [x * 4 3]; B = (byte) (Temp1 << 2); B1 = (Byte) ((Temp2 & 48) >> 4); B1 = B; B = (byte) ((Temp2 & 15) << 4); B2 = (Byte) ((Temp3 & 60) >> 2); B2 = B; B = (Byte) ((Temp3 & 3) << 6); B3 = TEMP4; B3 = B; Buffer2 [x * 3] = B1; Buffer2 [x * 3 1] = b2; Buffer2 [x * 3 2] = B3; } // Remove Paddings Length3 = longth2-paddingcount; Byte [] result = new byte [length3]; FOR (int x = 0; x { Result [x] = buffer2 [x]; } Return Result; } Private Byte Char2Sixbit (Char C) { IF (c == '=') Return 0; Else { FOR (int x = 0; x <64; x ) { IF (Lookuptable [x] == C) Return (Byte) x; } // Should Not Reach Here Return 0; } } } }