在項目中,對豹紋進行壓縮、加密后,最后一步一般是 base64 編碼。因為 base64 編碼的字符串更適合不同平臺,不同語言的傳輸。
base64 編碼的優(yōu)點:
- 算法是編碼,不是壓縮,編碼后只會增加字節(jié)數(shù)(一般是比之前的多1/3,比如之前是3, 編碼后是4)
- 算法簡單,基本不影響效率
- 算法可逆,解碼很方便,不用于私密傳輸。
- 畢竟編碼了,肉眼不能直接讀出原始內(nèi)容。
- 加密后的字符串只有【0-9a-zA-Z+/=】 不可打印字符(轉(zhuǎn)譯字符)也可以傳輸
為啥要編碼
計算機中任何數(shù)據(jù)都是 ASCII 碼存儲的, ascii 是 128-255 之間的不可見字符。在網(wǎng)絡(luò)上進行數(shù)據(jù)交換,從 A 到 B, 往往要經(jīng)過多個路由器,不同設(shè)備之間對字符的處理方式有一些不同,不可見字符有可能被錯誤處理,是不利于傳輸?shù)?,因此要先做一個 base64 編碼,變成可見字符,這樣出錯的可能性比較大。
在這里插入圖片描述
看看英文版怎么說:
When you have some binary data that you want to ship across a network, you generally don't do it by just streaming the bits and bytes over the wire in a raw format. Why? because some media are made for streaming text. You never know -- some protocols may interpret your binary data as control characters (like a modem), or your binary data could be screwed up because the underlying protocol might think that you've entered a special character combination (like how FTP translates line endings). So to get around this, people encode the binary data into characters. Base64 is one of these types of encodings. Why 64? Because you can generally rely on the same 64 characters being present in many character sets, and you can be reasonably confident that your data's going to end up on the other side of the wire uncorrupted.
使用場景
- 對于證書來說,尤其是根證書,一般是 base64 編碼的,在網(wǎng)上被很多人下載
- 電子郵件的附件一般是 base64 編碼,因為附件往往有不可見字符
- 比如 http 協(xié)議中 key , value 字段的值,必須進行 URLEncode,因為有寫特殊符號,有特殊含義,那么需要把這些字符傳輸完再解析回來。
- xml 中如果像嵌入另外一個 xml 文件,直接嵌入,往往 xml 標簽就亂套了, 不容易解析,因此,需要把 xml 編譯成字節(jié)數(shù)組的字符串,編譯成可見字符。
- 網(wǎng)頁中的一些小圖片,可以直接以 base64 編碼的方式嵌入,不用再鏈接請求消耗網(wǎng)絡(luò)資源。
- 較老的純文本協(xié)議 SMTP ,這些文本偶爾傳輸一個文件時,需要用 base64
base64 編碼步驟
- 將待編碼的字符串轉(zhuǎn)換成二進制表示出來
- 3個字節(jié)為一組,也就是24位二進制為一組
- 將這個24位分成4組,每 6個為一組,每組簽名補 00 將6為二進制轉(zhuǎn)換成8個二進制,從原來的3字節(jié)轉(zhuǎn)換為4字節(jié)
- 計算這4個字節(jié)對應(yīng)的十進制,然后跟 ASCII 表對應(yīng),拼接字符串形成最后的 base64 編碼。
base64 源碼
base64.h
#include "Base64.h"
const std::string CBase64::base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
int CBase64::find_utf_8_bit_head(const unsigned char *src_content,int src_size )
{
int i_ret = -1;
int byteNum = 0; //字符數(shù)
if( src_content )
{
for(int i = src_size-1; i >= 0; i--)
{
if( 0 == (src_content[i] >> 7 ) )
{
byteNum = 1;
i_ret = src_size - i;
break;
}
if( 0x06 == (src_content[i]>> 5) )
{
byteNum = 2;
i_ret = src_size - i;
break;
}
if( 0x0E == (src_content[i] >> 4) )
{
byteNum = 3;
i_ret = src_size - i;
break;
}
if( 0x1E == (src_content[i] >> 3) )
{
byteNum = 4;
i_ret = src_size - i;
break;
}
if( 0x3E == (src_content[i] >> 2) )
{
byteNum = 5;
i_ret = src_size - i;
break;
}
if( 0x7E == (src_content[i] >> 1) )
{
byteNum = 6;
i_ret = src_size - i;
break;
}
}
if( i_ret == byteNum ) i_ret = -1;
}
return i_ret;
}
std::string CBase64::base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
//CString CBase64::Base64Encode(LPCTSTR lpszSrc)
//{
// char* strSrc = new char[_tcslen(lpszSrc)+1];
// ZeroMemory(strSrc, _tcslen(lpszSrc)+1);
// strcpy(strSrc, (char*)(_bstr_t(lpszSrc)));
// std::string str = base64_encode((unsigned char*)strSrc, (int)strlen(strSrc));
// CString strDst = str.c_str();
// return strDst;
//}
std::string CBase64::Base64Encode(char* lpszSrc)
{
int str_len = strlen(lpszSrc);
int find_index = find_utf_8_bit_head((unsigned char*)lpszSrc, str_len);
if(find_index > -1)
{
memset(lpszSrc+(str_len-find_index), 0, find_index);
}
str_len = strlen(lpszSrc);
return base64_encode((unsigned char*)lpszSrc, str_len);
}
std::string CBase64::base64_decode(const unsigned char* bytes_to_encode, unsigned int in_len) {
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( bytes_to_encode[in_] != '=') /*&& is_base64(bytes_to_encode[in_])*/) {
char_array_4[i++] = bytes_to_encode[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
//CString CBase64::Base64Decode(LPCTSTR lpszSrc)
//{
// char* strSrc = new char[_tcslen(lpszSrc)+1];
// ZeroMemory(strSrc, _tcslen(lpszSrc)+1);
// strcpy(strSrc, (char*)(_bstr_t(lpszSrc)));
// std::string str = base64_decode((unsigned char*)strSrc, (int)strlen(strSrc));
// CString strDst = str.c_str();
// return strDst;
//}
std::string CBase64::Base64Decode(char* lpszSrc)
{
return base64_decode((unsigned char*)lpszSrc, (int)strlen(lpszSrc));
}
base64.cpp
#include "Base64.h"
const std::string CBase64::base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
int CBase64::find_utf_8_bit_head(const unsigned char *src_content,int src_size )
{
int i_ret = -1;
int byteNum = 0; //字符數(shù)
if( src_content )
{
for(int i = src_size-1; i >= 0; i--)
{
if( 0 == (src_content[i] >> 7 ) )
{
byteNum = 1;
i_ret = src_size - i;
break;
}
if( 0x06 == (src_content[i]>> 5) )
{
byteNum = 2;
i_ret = src_size - i;
break;
}
if( 0x0E == (src_content[i] >> 4) )
{
byteNum = 3;
i_ret = src_size - i;
break;
}
if( 0x1E == (src_content[i] >> 3) )
{
byteNum = 4;
i_ret = src_size - i;
break;
}
if( 0x3E == (src_content[i] >> 2) )
{
byteNum = 5;
i_ret = src_size - i;
break;
}
if( 0x7E == (src_content[i] >> 1) )
{
byteNum = 6;
i_ret = src_size - i;
break;
}
}
if( i_ret == byteNum ) i_ret = -1;
}
return i_ret;
}
std::string CBase64::base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
//CString CBase64::Base64Encode(LPCTSTR lpszSrc)
//{
// char* strSrc = new char[_tcslen(lpszSrc)+1];
// ZeroMemory(strSrc, _tcslen(lpszSrc)+1);
// strcpy(strSrc, (char*)(_bstr_t(lpszSrc)));
// std::string str = base64_encode((unsigned char*)strSrc, (int)strlen(strSrc));
// CString strDst = str.c_str();
// return strDst;
//}
std::string CBase64::Base64Encode(char* lpszSrc)
{
int str_len = strlen(lpszSrc);
int find_index = find_utf_8_bit_head((unsigned char*)lpszSrc, str_len);
if(find_index > -1)
{
memset(lpszSrc+(str_len-find_index), 0, find_index);
}
str_len = strlen(lpszSrc);
return base64_encode((unsigned char*)lpszSrc, str_len);
}
std::string CBase64::base64_decode(const unsigned char* bytes_to_encode, unsigned int in_len) {
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( bytes_to_encode[in_] != '=') /*&& is_base64(bytes_to_encode[in_])*/) {
char_array_4[i++] = bytes_to_encode[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
//CString CBase64::Base64Decode(LPCTSTR lpszSrc)
//{
// char* strSrc = new char[_tcslen(lpszSrc)+1];
// ZeroMemory(strSrc, _tcslen(lpszSrc)+1);
// strcpy(strSrc, (char*)(_bstr_t(lpszSrc)));
// std::string str = base64_decode((unsigned char*)strSrc, (int)strlen(strSrc));
// CString strDst = str.c_str();
// return strDst;
//}
std::string CBase64::Base64Decode(char* lpszSrc)
{
return base64_decode((unsigned char*)lpszSrc, (int)strlen(lpszSrc));
}
歡迎關(guān)注公眾號:程序員開發(fā)者社區(qū)
參考資料
- https://opensource.sensorsdata.cn/question-daily/2020-03-31/