文章目錄
base16、base32和base64,轉碼原理
基本概念
ASCII 是用128(2的8次方)個字符,對二進制數據進行編碼的方式
base64編碼是用64(2的6次方)個字符,對二進制數據進行編碼的方式
base32就是用32(2的5次方)個字符,對二進制數據進行編碼的方式
base16就是用16(2的4次方)個字符,對二進制數據進行編碼的方式
基於base16編解碼源碼介紹
就是把二進制數據轉成16進制,顯示16進制的值就可以了
16進制一個字符是4位,正常一個字節是8位,切一半就轉成16進制了。
所以,base16轉碼後空間擴大一倍,4位轉成一個字符, 1個字節轉成兩個字符
#include <iostream>
using namespace std;
static const char BASE16_ENC_TAB[] = "0123456789ABCDEF";
// '0' ~'9' => 48~57 'A'~'F' = > 65~70
static const char BASE16_DEC_TAB[128] = {
-1, //0
-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, //1-10
-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, //11-20
-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, //21-30
-1,-1,-1,-1,-1, -1,-1,-1,-1,-1, //31-40
-1,-1,-1,-1,-1, -1,-1, 0, 1, 2, //41-50
3, 4, 5, 6 ,7, 8, 9, -1,-1,-1, //51-60
-1,-1,-1,-1,10, 11,12,13,14,15 //61-70 'A'~'F'
};
int Base16Encode(const unsigned char* in, int size, char* out)
{
for (int i = 0; i < size; i++)
{
//一個字節取出高4位和低4位 1000 0001 0000 1000
char h = in[i] >> 4; //移位丟棄低位,右移4位 (0~15)
char l = in[i] & 0x0F; // 0000 1111 去掉高位 (0~15)
out[i * 2] = BASE16_ENC_TAB[h]; //(0~15) 映射到對應字符
out[i * 2 + 1] = BASE16_ENC_TAB[l];
}
//base16 轉碼後空間擴大一倍 4位轉成一個字符 1個字節轉成兩個字符
return size * 2;
}
int Base16Decode(const string &in, unsigned char* out)
{
//講兩個字符拼成一個字節 B2E2CAD442617365313600
for (int i = 0; i < in.size(); i += 2)
{
unsigned char ch = (int)in[i]; //高位轉換的字符 'B'=>66 :10
unsigned char cl = (int)in[i + 1]; //低位轉換的字符 '2'=>50 :2
unsigned char h = BASE16_DEC_TAB[ch]; //轉換成原來的值
unsigned char l = BASE16_DEC_TAB[cl];
// 兩個4位拼成一個字節(8位)
/// 1000 >>4 1000 0000
// 0001 0000 0001
// |1000 0001
out[i / 2] = (int)(h << 4 | l);
}
return in.size() / 2;
}
int main(int argc,char *argv[])
{
cout << "Test Base16" << endl;
const unsigned char data[] = "測試Base16";
int len = sizeof(data);
char out1[1024] = { 0 };
unsigned char out2[1024] = { 0 };
cout << data << endl;
int re = Base16Encode(data, len, out1);
cout << re << ":" << out1 << endl;
re = Base16Decode(out1, out2);
cout << re << ":" << (char*)out2 << endl;
return 0;
}
輸出結果
解碼的時候’b’字符轉換成ASCII碼值位66,所以66位改爲10的值。
Base-64編碼
Encoding VS. Encryption
很多人都以爲編碼(Encoding)和加密(Encryption)是同一個意思。編碼和加密都是對格式的一種轉換,但是它們是有區別的。編碼是 公開的,比如下面要介紹的Base 64編碼,任何人都可以解碼;而加密則相反,你只希望自己或者特定的人才可以對內容進行解密。
作用及原理
Base 64 Encoding有什麼用?舉個簡單的例子,你使用SMTP協議 (Simple Mail Transfer Protocol 簡單郵件傳輸協議)來發送郵件。因爲這個協議是基於文本的協議,所以如果郵件中包含一幅圖片,我們知道圖片的存儲格式是二進制數據(binary data),而非文本格式,我們必須將二進制的數據編碼成文本格式,這時候Base 64 Encoding就派上用場了。
Base64編碼的作用:由於某些系統中只能使用ASCII字符。Base64就是用來將非ASCII字符的數據轉換成ASCII字符的一種方法。它使用下面表中所使用的字符與編碼。
而且base64特別適合在http,mime協議下快速傳輸數據。
base64其實不是安全領域下的加密解密算法。雖然有時候經常看到所謂的base64加密解密。其實base64只能算是一個編碼算法,對數據內容進行編碼來適合傳輸。雖然base64編碼過後原文也變成不能看到的字符格式,但是這種方式很初級,很簡單。
X.509公鑰證書也好,電子郵件數據也好,經常要用到Base64編碼,那麼爲什麼要作一下這樣的編碼呢?
我們知道在計算機中任何數據都是按ascii碼存儲的,而ascii碼的128~255之間的值是不可見字符。而在網絡上交換數據時,比如說從A地傳到B地,往往要經過多個路由設備,由於不同的設備對字符的處理方式有一些不同,這樣那些不可見字符就有可能被處理錯誤,這是不利於傳輸的。所以就先把數據先做一個Base64編碼,統統變成可見字符,這樣出錯的可能性就大降低了。
如一個xml當中包含另一個xml數據,此時如果將xml數據直接寫入顯然不合適,將xml進行適當編碼存入較爲方便,事實上xml當中的字符一般都是可見字符(0-127之間),但是由於中文的存在,可能存在不可見字符,直接將字符打印在外層xml的數據中顯然不合理,那麼怎麼辦呢?
可以使用base64進行編碼,然後存入xml,解碼反之
其實還有個辦法,將byte的值寫在xml當中,空格或者,分開,這樣也可以將byte數據傳入,不過這樣更浪費空間,並且不易保存.
另一個,比如http協議當中的key value字段,必須進行URLEncode 不然出現的等號可能使解析失敗 空格也會使http請求解析出現問題,比如 請求行就是以空格來劃分的 POST /guowuxin/hehe HTTP/1.1
又比如有些文本協議不支持不可見字符的傳遞,只能用大於32的可見字符來傳遞信息(協議規定)
索引表
base64索引表:
base32索引表:
base16索引表:
轉碼原理
轉碼
這裏只介紹Base-64轉碼,其他的原理一樣
2的6次方即爲64
Base-64編碼將一個8位子節序列拆散爲6位的片段,併爲每6位分配一個字符(見索引表)。這64個字符都是很常見的,可以安全地放在HTTP首部字段中。這64個字符中包括大小寫字母、數字、+和/,特殊字符=(即結尾處使用的=號)
示例:
在結尾還差的補等於號。
上面的三個字符“Man”是原文,下面的四個字符“TWFu”是Base64編碼後的字符
經過base64編碼後,字符串理論上比之前長1/3,也就是原來的4/3。(除下面兩種情況外)。
base64填充
base64編碼收到一個8bit字節數據,將這個二進制序列每6bit劃分一個塊。二進制序列有時不能正好平均地分爲6位的塊,在這種情況下,就在序列末尾填充零位,使二進制序列的長度成爲24的倍數(6和8的最小公倍數)。
示例:
輸入字符串爲”a:a”爲3個字節(24位)。24是24的倍數,因此按照上面給出的例子計算。無需填充就會得到base64編碼爲”YTph”。
輸入字符串變爲”a:aa”爲4個字節(32位)。要湊爲24的倍數,最小的值是48。因此要添加16個填充碼。
a:a – 011000 010011 101001 100001 – YTph
a:aa – 011000 010011 101001 100001 011000 01xxxx xxxxxx xxxxxx – YTphYQ==
a:aaa – 011000 010011 101001 100001 011000 010110 0001xx xxxxxx – YTphYWE=
a:aaaa – 011000 010011 101001 100001 011000 010110 000101 1000001 – YTphYWFh