Base64編碼和解碼原理


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)

 

# 歡迎交流

參考:

https://blog.csdn.net/u013412497/article/details/51552335

https://baike.baidu.com/item/base64/8545775?fr=aladdin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM