日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

对象base64转码_什么是 Base64 编码

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对象base64转码_什么是 Base64 编码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是 Base64

Base64 是二進制到字符編碼的一種方案,將二進制數據使用 ASCII 字符串格式表示,即翻譯為基數為 64 的一種表示。每個 Base64 數字表示一個 6 比特的數據。三個字節(共 24 個比特)因此可以被表示為 4 個 Base64 數字。

Base64 常用于處理文本數據的場合,表示、傳輸、存儲一些二進制數據。

Base64 編碼表

從 0 到 25 ,也就是從 000000 到 011001,是 ASCII 字符 A - Z

從 26 到 51,也就是從 011010 到 110011,是 ASCII 字符 a - z

從 52 到 61,也就是從 110100 到 111101,是 ASCII 字符 0 - 9

62 (111110)是 ASCII 字符 +

63 (111111)是 ASCII 字符 /

綴詞(padding) =

因為 Base64 是每 6 個比特進行一次編碼,而現代電腦上的編碼值被分為了一個個 8 比特的字節,因此,在 Base64 編碼的文本中,每 4 個字符表示三個字節的未編碼的文本或數據。這就意味著,當未編碼的輸入的字節數不是 3 的倍數時,編碼輸出必須加上綴詞來使得輸出的長度是 4 的倍數。這個綴詞便是 = ,它表明:不再需要更多的比特來進行解碼。

= 數量規則如下:若源數據的字節數是 3 的倍數,則不需要加 =

若源數據的字節數除 3 余 1,則加兩個 =

若源數據的字節數除 3 余 2,則加一個 =

舉個例子來說明 = 的使用:

字符串 "Man" 的 ASCII 編碼是 01001101 ,01100001 ,01101110 ,(0x4d,0x61,0x6e)。拆成六個一組,就是 010011 ,010110 ,000101 ,101110 。對應于 Base64 編碼表中的 T,W,F,u,故編碼后 ASCII 編碼的"Man" 對應于 "TWFu"。

字符串 "Ma" 的 ASCII 是 01001101 ,01100001 。拆開得到 010011 ,010110 ,0001 。最后一組還少兩個比特,補零得到 000100 。對應于 Base64 編碼得到 T,W,E,編碼結果為 "TWE="。此處的 = 表明補了兩個比特。

字符串 "M" 的 ASCII 是 01001101 ,拆開之,得到 010011 ,01 。最后一組要補四個零,得到 010000 。對應 Base64 得到 T,Q。編碼結果為 "TQ==",== 表明補了四個比特。

實際上,綴詞 = 并不是必須的,因為缺少的字節可以從編碼文本的長度中計算得到。例如 “YW55IGNhcm5hbCBwbGVhc3VyZS4” 這個編碼串共有 27 個字符,不是 4 的倍數, 且由 mod(27, 4) = 1 可知它補充了兩個比特。通過這些信息就可以知道源文本(或數據)(若為 ASCII 編碼)是 “any carnal pleasure.”。但是,如果多個 Base64 編碼字符串被連接在一起,= 是必要的,因為需要使用它來區分不同來源的字符串。

Base64 的解碼

當對 Base64 進行解碼時,四個字符通常會被轉化為三個字節。當存在綴詞時則可能是兩個或一個,一個 = 表明四個字符會被轉化為兩個字節,兩個 = 表明四字符會被轉為一個字節。上面的例子便是如此。

如果沒有綴詞,在對所有的四字符組進行轉碼后,若還有剩下的字符,剩下的字符數一定小于四。這種情況下,只可能剩下兩個或三個字符。若剩下兩個字符,則轉為一個字節,若為三個則轉為兩個字節。

一個簡單的 C 實現

以下代碼在 MINGW 下通過編譯并通過了下面的測試。

簡便起見,我沒用使用 stdint 頭文件,所有下面的代碼想要正確運行的話,必須滿足 int 是 32 位。

編碼

要想將一個個字節編碼為 Base64,首先需要一張二進制碼(000000 - 111111)到 64 個字符的映射表:

char base64_encode_table[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', '+', '/'

};

由于現在的計算機中一個字節是 8 位,而 Base64 編碼中每 6 位進行一次編碼,在處理過程中若直接使用字節(字符)數組可能不是太方便。考慮到 3 * 8 = 4 * 6,先編寫一次性對 3 個字節進行處理的函數會方便不少,而且若最后還剩下 1 或 2 個字節,可以一并處理。

void base64_convert3(char * dststr, unsigned char c1, unsigned char c2, unsigned char c3, int num)

{

// dststr must be big enough to contain four char

// num is the number of byte to convert

int convert = 0;

convert = (c1 << 16) | (c2 << 8) | c3;

for (int i = 0; i < 4; i++)

{

int temp = (convert >> (i * 6)) & 0x3f; //0x3f = 00111111

dststr[3 - i] = base64_encode_table[temp];

}

for (int i = 3; i > num; i--)

{

dststr[i] = '=';

}

}

上面的函數的三個字符參數 c1, c2, c3 是順序排列的 3 個字節,參數 num 是處理字節的個數。如果 num 的值不為 3,那么 c2 或 c3 的值應該設為 0 來確保得到正確的結果。

這個函數沒有對參數的合理性進行檢驗。

接下來就可以完成編碼函數了。

int base64_encoder(char * dststr, char * srcstr, int num, int * dstlength)

{

// num is the number of byte

// dstlength is the number of encoded char, include '='

// dststr must be big enough to carry encoded char

// return non-zero means failed

if (dststr == NULL || srcstr == NULL || num <= 0 || dstlength == NULL)

{

return 1;

}

int cnt = 0;

int i = 0;

for (i = 0; i <= num - 3; i += 3)

{

base64_convert3(dststr + cnt, srcstr[i], srcstr[i + 1], srcstr[i + 2], 3);

cnt += 4;

}

if (i == num)

{

dstlength[0] = cnt;

return 0;

}

else if (i == num - 1)

{

base64_convert3(dststr + cnt, srcstr[i], 0, 0, 1);

cnt += 4;

dstlength[0] = cnt;

return 0;

}

else if (i == num - 2)

{

base64_convert3(dststr + cnt, srcstr[i], srcstr[i + 1], 0, 2);

cnt += 4;

dstlength[0] = cnt;

return 0;

}

else

{

return 1;

}

return 1;

}

該函數做了最低限度的參數檢查。dststr 代表編碼后字符串的目標位置,srcstr 表示源字符串,num 是源字符串的長度,dstlength 指向一個整型變量,用于存儲得到的編碼的長度。

解碼

與編碼相似,解碼也需要一張映射表,不過 Base64 只規定了從二進制到字符進行編碼,而沒有規定字符的編碼,至于字符編碼是 ASCII 還是其他的比如 UTF-8,EBCDEC 。為了簡便起見,這里使用 ASCII。可以使用一個一個 if else 來去掉字符集依賴性,不過也太麻煩了點:

unsigned char base64_decode_table(unsigned char ch)

{

//use ascii code

if (isupper(ch))

{

return ch - 65; // 'A' is 65

}

else if (islower(ch))

{

return ch - 97 + 26; // 'a' is 97

}

else if (isdigit(ch))

{

return ch - 48 + 52; // '0' is 48

}

else if (ch == '+')

{

return 62;

}

else if (ch == '/')

{

return 63;

}

else

{

return 255;

}

}

同樣,與編碼類似,解碼時也可以考慮將四個字符看成一組,這樣處理帶 = 時更方便:

void base64_convert4(char * dststr, unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, int num)

{

// num is the number of char

// dststr must not be null

int convert = 0;

convert = base64_decode_table(c4);

convert = convert | (base64_decode_table(c3) << 6);

convert = convert | (base64_decode_table(c2) << 12);

convert = convert | (base64_decode_table(c1) << 18);

for (int i = 0; i <= num - 2; i++)

{

dststr[i] = convert >> (8 * (2 - i)) & 0xff;

}

}

接下來就可以編寫解碼函數了,因為要處理使用 = 和不使用 = 的情況,代碼的選擇支有點多,看起來有點長:

int base64_decoder(char * dststr, char * srcstr, int num, int *dstlength)

{

//the min value of num is 2

if (dststr == NULL || srcstr == NULL || num < 2 || dstlength == NULL)

return 1;

int i;

int cnt = 0;

for (i = 0; i <= num - 8; i += 4)

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], srcstr[i + 2], srcstr[i + 3], 4);

cnt += 3;

}

if (i == num - 4)

{

if (srcstr[num - 1] != '=')

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], srcstr[i + 2], srcstr[i + 3], 4);

cnt += 3;

dstlength[0] = cnt;

return 0;

}

else

{

if (srcstr[num - 2] == '=')

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], 0, 0, 2);

cnt += 1;

dstlength[0] = cnt;

return 0;

}

else

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], srcstr[i + 2], 0, 3);

cnt += 2;

dstlength[0] = cnt;

return 0;

}

}

}

else if (i == num - 3)

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], srcstr[i + 2], 0, 3);

cnt += 2;

dstlength[0] = cnt;

return 0;

}

else if (i == num - 2)

{

base64_convert4(dststr + cnt, srcstr[i], srcstr[i + 1], 0, 0, 2);

cnt += 1;

dstlength[0] = cnt;

return 0;

}

else

{

return 1;

}

return 1;

}

測試

int main(void)

{

char man[] = "Man";

char trans_man[3][20];

int len[3];

//test encode

for (int i = 0; i < 3; i++)

{

base64_encoder(trans_man[i], man, 3 - i, len + i);

trans_man[i][len[i]] = '\0';

printf("%s\n", trans_man[i]);

}

//test decode

char restore[3][20];

int lenres[3];

for (int i = 0; i < 3; i++)

{

base64_decoder(restore[i], trans_man[i], 4, lenres + i);

restore[i][lenres[i]] = '\0';

printf("%s\n", restore[i]);

}

//test for situation without '='

base64_decoder(restore[0], trans_man[1], 3, lenres);

restore[0][lenres[0]] = '\0';

printf("%s\n", restore[0]);

base64_decoder(restore[0], trans_man[2], 2, lenres);

restore[0][lenres[0]] = '\0';

printf("%s\n", restore[0]);

char myself[] = "include-yy";

char myself_encode[20];

int myself_len;

base64_encoder(myself_encode, myself, 10, &myself_len);

myself_encode[myself_len] = '\0';

printf("\n%s\n", myself_encode);

base64_decoder(restore[0], myself_encode, myself_len, lenres);

restore[0][lenres[0]] = '\0';

printf("%s\n", restore[0]);

return 0;

}

輸出結果應該為:

TWFu

TWE=

TQ==

Man

Ma

M

Ma

M

aW5jbHVkZS15eQ==

include-yy

在 Python 中使用 Base64

Python 隨處可見,用起來也比 C 方便的多,故學習 Python 的用法肯定還是有用的。

Python 的 base64 模塊

base64 模塊提供了將二進制數據編碼為可打印 ASCII 字符和將編碼解碼為二進制數據的函數。

base64 模塊提供的函數不限于操作 base64,還有 base16,base32 等,不過這里只關注 base64 的編碼和解碼。

接口函數

base64.b64encode(s, altchars=None)

該函數將類字節對象(bytes-like object)使用 base64 進行編碼,并返回編碼后的字節。

altchars 必須是長度至少為 2 的類字節對象,這些字符指定了代替 + 和 / 的字符。這就允許該函數生成 URL 安全的 Base64 字符串。

base64.b64decode(s, altchars=None, validate=False)

該函數被編碼的字符串解碼并返回解碼字節。

altchars 必須是長度至少為 2 的類字節對象或 ASCII 字符串,這些字符串指定了用來代替 + 和 / 的字符。

validate 默認為 False ,既不是 base-64 字符也不是備用字母表中的字符會被丟棄。如果 validate 為 True ,非 base64 字符會導致 binascii.Error 。

具體用法

首先,導入 python 的 base64 模塊

import base64

創建一個字符串,并使用 encode 方法,將其轉化為字節對象:

s = 'include-yy'

s = s.encode()

(encode 方法的默認編碼是 'uft-8')

接著使用 base64.b64encode() ,便可得到結果:

base.b64encode(s)

想要解碼,則調用 base64.b64decode()

s2 = base.b64encode(s)

base64.b64decode(s2.encode());

參考資料

總結

以上是生活随笔為你收集整理的对象base64转码_什么是 Base64 编码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。