Base64常用於對電子郵件、短信、URL等進行編碼和傳輸,在Python和Mysql中都有實現方式。
但這里要說的是它編碼的基本原理和步驟。
1. 首先相信大家都會看到這個表:Base64對應的字符表,一共64個字符,包括26個字母的大小寫、10個阿拉伯數字、+號和/號;附:(還有一個' =' 號一般用於后綴)。
2. Base64並不加密信息,因為它屬於編碼方式,不屬於加密系統;可以隨時對其信息進行解碼。
3. Base64是網絡上最常見的用於傳輸8Bit字節碼的編碼方式之一,Base64是一種基於上述64個可打印ASCII字符來表示二進制字節流數據的方法,還有' =' 號用於后綴。
Base64編碼是一種從二進制到字符的過程,解碼則相反。
4. 其編碼規則主要有:
- 把3個字節變成4個字節。
- 每76個字符加一個換行符。
- 結束符也要進行處理。
5. 編碼步驟:
(1)對原始數據,分字節,求二進制字符串;
(2)對二進制串,6位為一組進行分組,不足末尾補0;
(3)在各分組前面補2個0成8位,求各分組的十進制值,根據十進制對應上表找編碼字符;
(4)字節數對3取余數,余數為0,不加等號;余數為1,在上述編碼符號串的末尾加2個等號;余數為2,末尾加1個等號。
6. 編碼示例:
(1)原始數據是英文字符,sss = 'SE'
流程:
首先,求取 'SE' 的二進制編碼(utf-8和ASCII等在英文時一致),sss.encode('utf-8') = b 'SE',b表示bytes類型,'SE'只是打印出來的符號,實際上其二進制是ASCII碼的大寫'S'和'E'的編碼連接而成:01010011(二進制,其十進制是83,'S'),01000101(二進制,其十進制是69,'E')—— 即,將輸入字符串按字節切分,取得每個字節對應的二進制值(若不足8比特則高位補0);
其次,將該二進制字符串:01010011 01000101,按照6位一組進行切分(因為2的6次方剛好是64,在Base64的編碼范圍內),最后一組如果不足6位則末尾補0;於是得到:010100 110100 010100 的3組二進制串。
然后,各自在前面補2個0得到:00010100 00110100 00010100,轉化成十進制為:20,52,20;對應到上面的表中得到:'U0U',注意中間這個是0。
最后,將N字節的原始數據,每個字節8位,按照6位一組進行划分,(而6和8的最小公倍數為24),所以要划分的二進制位數必須是24的倍數(或者字節數是3的倍數),而這里的 'SE' 原始數據只有2個字節,2%3=2,所以在結尾需要補上1個等號 '='。
綜合以上得到:'U0U='
注:由於某字節數M%3的值,(即M除以3的余數)只有0,1,2共三種情形,0表示整除(不用加等號 '=');那么余數為1,則要加上2個等號 '=';余數為2則要加上1個等號 '='。
(2)原始數據是中英文,sss='線?' ,這里的問號是英文
流程:
同理,首先求取sss字符串的二進制編碼,sss.encode('utf-8') = b'\xe7\xba\xbf?',b表示bytes字節流類型,\x表示十六進制,寫的清楚一點就是:e7 ba bf ? ;
則該字符串的二進制數據(進制轉換)為:11100111(e7)10111010(ba)10111111(bf)00111111(英文?的ASCII碼,二進制);
其次,將上述字符串6位一組進行划分,不足補0,得到:111001 111011 101010 111111 001111 110000;
然后各自在前面補2個0得到:00111001 00111011 00101010 00111111 00001111 00110000,十進制值也就是:57,59,42,63,15,48;對應上表也就是:'57q/Pw'
最后,原始數據共4個字節,4%3=1,所以加上兩個等號 '='。
綜合以上得到:'57q/Pw=='
import base64 sss = 'SE' aaa = base64.b64encode(sss.encode('utf-8')) #base64編碼前,需要把數據變成字節流bytes print('aaa:',aaa) bbb = base64.b64decode(aaa) #解碼 print('bbb:',bbb)
7. 解碼:
解碼就是編碼的逆過程:
(1)先去掉等號;
(2)再根據編碼表,找編碼字符對應的編碼值;
(3)取各編碼值的8位二進制值,去掉每個二進制的前2位的0值,然后連接形成二進制串;
(4)對上述二進制串,從前到后,每8位構成一個字節的數據;多余的末尾0值去掉;
(5)此時得到的就是原始數據的二進制編碼;再根據編碼方式(例如 utf-8)等進行解碼。
8. 解碼示例:
對於上述編碼的 'U0U=':
首先,去掉等號 '=',得到 'U0U';
其次,根據編碼表,找到對應的編碼值:20,52,20;
然后,取8位二進制值為:00010100 00110100 00010100;每一個去掉前面2位的0,得到:010100 110100 010100;
最后,從前到后,每8位構成一個字節數據,去掉末尾多余的0:010100 110100 010100;所以末尾2個0去掉,此時得到的就是原始數據的二進制編碼,可以繼續utf-8解碼形成原始數據;
9. Base64編碼的python代碼
# python 實現base64編碼 def base64_func(str_): # str_為原始字符串 oldstr = '' newstr = [] base_str = '' base64_list = ['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', '+', '/'] # 首先將原始字符串轉化為二進制字節流,這里用的是 utf-8編碼,也可以用bytes函數實現 byte_str = str_.encode('utf-8') #會形成一個或多個字節的二進制字節流,是可以遍歷的(可迭代),並且遍歷的結果是以十進制顯示的 for ii in byte_str: oldstr = oldstr + '{:08}'.format(int(bin(ii).replace('0b', ''))) #用bin轉換后是0b開頭的,所以先把0b去掉;int將字符串轉化成數值型,然后再在前面補0補齊成8位字符串{:08},並各字節進行連接 #把轉換后且連接的二進制按照6位一組分組,最后一組不足6位的末尾補0 for jj in range(0, len(oldstr), 6): #第三位6相當於步長 newstr.append('{:0<6}'.format(oldstr[jj:jj + 6])) #{:0<6}中的<表示左對齊,0表示填充0;oldstr[jj:jj + 6]中,如果jj+6超出字符串長度,則會直接取到末尾,列表也是 #在base_list中找到對應的字符,拼接 for ss in range(len(newstr)): base_str += base64_list[int(newstr[ss], 2)] #二進制先轉十進制,查找 #判斷base_str字符串結尾補幾個等號‘=’ if len(str_) % 3 == 1: base_str += '==' elif len(str_) % 3 == 2: base_str += '=' return bytes(base_str,'utf-8') # 也可直接返回:base_str ss = base64_func('線?') print(ss)
# 歡迎交流
參考: