一、什么是Base64?
百度百科中對Base64有一個很好的解釋:“Base64是網絡上最常見的用於傳輸8Bit字節碼的編碼方式之一,Base64就是一種基於64個可打印字符來表示二進制數據的方法”。
什么是“可打印字符”呢?為什么要用它來傳輸8Bit字節碼呢?在回答這兩個問題之前我們有必要來思考一下什么情況下需要使用到Base64?Base64一般用於在HTTP協議下傳輸二進制數據,由於HTTP協議是文本協議,所以在HTTP協議下傳輸二進制數據需要將二進制數據轉換為字符數據。然而直接轉換是不行的。因為網絡傳輸只能傳輸可打印字符。什么是可打印字符?在ASCII碼中規定,0~31、127這33個字符屬於控制字符,32~126這95個字符屬於可打印字符,也就是說網絡傳輸只能傳輸這95個字符,不在這個范圍內的字符無法傳輸。那么該怎么才能傳輸其他字符呢?其中一種方式就是使用Base64。
Base64,就是使用64個可打印字符來表示二進制數據的方法。Base64的索引與對應字符的關系如下表所示:
也就是說,如果將索引轉換為對應的二進制數據的話需要至多6個Bit。然而ASCII碼需要8個Bit來表示,那么怎么使用6個Bit來表示8個Bit的數據呢?6個Bit當然不能存儲8個Bit的數據,但是4*6個Bit可以存儲3*8個Bit的數據啊!如下表所示:
可以看到“Son”通過Base64編碼轉換成了“U29u”。這是剛剛好的情況,3個ASCII字符剛好轉換成對應的4個Base64字符。但是,當需要轉換的字符數不是3的倍數的情況下該怎么辦呢?Base64規定,當需要轉換的字符不是3的倍數時,一律采用補0的方式湊足3的倍數,具體如下表所示:
每6個Bit為一組,第一組轉換后為字符“U”,第二組末尾補4個0轉換后為字符“w”。剩下的使用“=”替代。即字符“S”通過Base64編碼后為“Uw==”。這就是Base64的編碼過程。
延伸
上面我們已經看到了Base64就是用6位(2的6次冪就是64)表示字符,因此成為Base64。同理,Base32就是用5位,Base16就是用4位。大家可以按照上面的步驟進行演化一下。
二、Java中實現Base64
Java已經替我們寫好Base64的實現細節,使用的時候直接調用即可。具體代碼如下所示:
package com.first; import org.junit.Test; import java.io.UnsupportedEncodingException; import java.util.Base64; public class Test { @Test public void test() throws UnsupportedEncodingException { // 編碼 String encode = Base64.getEncoder().encodeToString("Son".getBytes("UTF-8")); System.out.println(encode); // 解碼 byte[] decode = Base64.getDecoder().decode(encode); System.out.println(new String(decode, "UTF-8")); } }
三、 Base64的編碼過程分析
假設需要編碼的字符串是 Jasmine
具體轉換步驟:
第一步 將待轉換的字符串轉為一個個字符
第二步 計算每一個字符對應的ASCII碼十進制
第三步 計算出十進制對應的二進制,若不足8位,在前面添加0進行補全
第四步 將8位的二進制碼,按照6個6個一組划分,若不能整除6,在最末添加0補足6位
第五步 計算對應的十進制編碼
第六步 按照base64表,查看對應的字符
第七步 將加密后的字符3個3個分成一組,不足3位的添加=進行補全
第八步 得到最終結果
同時得到base64位編碼后的特征:
1)長度是3的倍數
2)只含有65中字符,大寫的A至Z,小寫的a至z,數字0到9,以及3種符號+/ =,=最多兩個,且在末尾
轉換表
切忌誤用
可能會有人在不理解Base64編碼的情況下,將其誤用於數據加密或數據校驗。
Base64是一種數據編碼方式,目的是讓數據符合傳輸協議的要求。標准Base64編碼解碼無需額外信息即完全可逆,即使你自己自定義字符集設計一種類Base64的編碼方式用於數據加密,在多數場景下也較容易破解。
另一篇關於BASE64的詳細介紹: Base64編碼原理與應用