BASE64編碼是一種常用的將十六進位資料轉換為可見字元的編碼。與ASCII碼相比,它佔用的空間較小。BASE64編碼在rfc3548中定義。
1、base64編解碼原理
關於這個編碼的規則:
1)把3個字元變成4個字元
2)每76個字元加一個分行符號
3)最後的結束符也要處理
將資料編碼成BASE64編碼時,3字元轉4字元後,每個字元6bit,得到一個數字:0-63。但是由於0-63中有很多不可列印字元,需要進行二次映射,映射的規則就是
0~25:A~Z
26~51:a~z
52~61:0~9
62:+
63:/
比如有資料:0x30 0x82 0x02
編碼過程如下:
1)得到16進位資料: 30 82 02
2)得到位元據: 00110000 10000010 00000010
3)每6bit分組: 001100 001000 001000 000010
4)得到數字: 12 8 8 2
5)根據查表得到結果 : M I I C
BASE64填充:在不夠的情況下在右邊加0。
有三種情況:
1) 輸入資料位元數是24的整數倍(輸入位元組為3位元組整數倍),則無填充;
2) 輸入資料最後編碼的是1個位元組(輸入資料位元組數除3餘1),即8位元,則需要填充2個"==",因為要補齊6位元,需要加2個00;
3)輸入資料最後編碼是2個位元組(輸入資料位元組數除3餘2),則需要填充1個"=",因為補齊6位元,需要加一個00。
舉例如下:
對0x30編碼:
1) 0x30的二進位為:00110000
2) 分組為:001100 00
3) 填充2個00:001100 000000
4) 得到數字:12 0
5) 查表得到的編碼為MA,另外加上兩個==
所以最終編碼為:MA==
2、Base64編解碼,下面代碼參考開源軟體cyassl:
#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br />enum {<br /> BAD = 0xFF, /* invalid encoding */<br /> PAD = '=',<br /> PEM_LINE_SZ = 64<br />};</p><p>static<br />const char base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */<br /> 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,<br /> BAD, BAD, BAD, BAD, BAD, BAD, BAD,<br /> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,<br /> 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,<br /> 20, 21, 22, 23, 24, 25,<br /> BAD, BAD, BAD, BAD, BAD, BAD,<br /> 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,<br /> 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,<br /> 46, 47, 48, 49, 50, 51<br /> };</p><p>int Base64Decode(const char* in, int inLen, char * out, int * outLen)<br />{<br /> int i = 0;<br /> int j = 0;</p><p> while (inLen > 3) {<br /> char b1, b2, b3;<br /> char e1 = in[j++];<br /> char e2 = in[j++];<br /> char e3 = in[j++];<br /> char e4 = in[j++];</p><p> int pad3 = 0;<br /> int pad4 = 0;</p><p> if (e1 == 0) /* end file 0's */<br /> break;<br /> if (e3 == PAD)<br /> pad3 = 1;<br /> if (e4 == PAD)<br /> pad4 = 1;</p><p> e1 = base64Decode[e1 - 0x2B];<br /> e2 = base64Decode[e2 - 0x2B];<br /> e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];<br /> e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];</p><p> b1 = (e1 << 2) | (e2 >> 4);<br /> b2 = ((e2 & 0xF) << 4) | (e3 >> 2);<br /> b3 = ((e3 & 0x3) << 6) | e4;</p><p> out[i++] = b1;<br /> if (!pad3)<br /> out[i++] = b2;<br /> if (!pad4)<br /> out[i++] = b3;<br /> else<br /> break;</p><p> inLen -= 4;<br /> if (in[j] == ' ' || in[j] == '/r' || in[j] == '/n') {<br /> char endLine = in[j++];<br /> inLen--;<br /> while (endLine == ' ') { /* allow trailing whitespace */<br /> endLine = in[j++];<br /> inLen--;<br /> }<br /> if (endLine == '/r') {<br /> endLine = in[j++];<br /> inLen--;<br /> }<br /> if (endLine != '/n')<br /> return -1;<br /> }<br /> }<br /> *outLen = i;<br /> return 0;<br />}</p><p>static<br />const char base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',<br /> 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',<br /> 'U', 'V', 'W', 'X', 'Y', 'Z',<br /> 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',<br /> 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',<br /> 'u', 'v', 'w', 'x', 'y', 'z',<br /> '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',<br /> '+', '/'<br /> };</p><p>int Base64Encode(const char* in, int inLen, char * out, int* outLen)<br />{<br /> int i = 0,j = 0,n = 0; /* new line counter */<br /> int outSz = (inLen + 3 - 1) / 3 * 4;</p><p> if (outSz > *outLen) return -1;</p><p> while (inLen > 2) {<br /> char b1 = in[j++];<br /> char b2 = in[j++];<br /> char b3 = in[j++];</p><p> /* encoded idx */<br /> char e1 = b1 >> 2;<br /> char e2 = ((b1 & 0x3) << 4) | (b2 >> 4);<br /> char e3 = ((b2 & 0xF) << 2) | (b3 >> 6);<br /> char e4 = b3 & 0x3F;</p><p> /* store */<br /> out[i++] = base64Encode[e1];<br /> out[i++] = base64Encode[e2];<br /> out[i++] = base64Encode[e3];<br /> out[i++] = base64Encode[e4];</p><p> inLen -= 3;</p><p> if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)<br /> out[i++] = '/n';<br /> }</p><p> /* last integral */<br /> if (inLen) {<br /> int twoBytes = (inLen == 2);</p><p> char b1 = in[j++];<br /> char b2 = (twoBytes) ? in[j++] : 0;</p><p> char e1 = b1 >> 2;<br /> char e2 = ((b1 & 0x3) << 4) | (b2 >> 4);<br /> char e3 = (b2 & 0xF) << 2;</p><p> out[i++] = base64Encode[e1];<br /> out[i++] = base64Encode[e2];<br /> out[i++] = (twoBytes) ? base64Encode[e3] : PAD;<br /> out[i++] = PAD;<br /> } </p><p> //out[i++] = '/n';<br /> if (i != outSz)<br /> return -1;<br /> *outLen = outSz;</p><p> return 0;<br />}</p><p>int main()<br />{<br /> char * sstr = "123Hello987World+=%456";<br /> char encrystr[256];<br /> int len = 256;<br /> memset(encrystr,'/0',256);<br /> Base64Encode(sstr,strlen(sstr),encrystr, &len);<br /> printf("estr : %s/n",encrystr);<br /> char decrystr[256];<br /> memset(decrystr,'/0',256);<br /> Base64Decode(encrystr,len,decrystr,&len);<br /> printf("dstr : %s/n",decrystr);<br /> return 0;<br />}<br />