前言
- 對網(wǎng)絡(luò)通信有所了解的同學(xué)盯仪,應(yīng)該都聽過 Base64 編碼紊搪。例如,我們一段數(shù)據(jù)通過 MD5 磨总、SHA 等手段加密后嗦明,經(jīng)過 Base64 編碼為字符串就可以很方便地在網(wǎng)路上傳輸。那么 Base64 也算是一種加密算法嗎蚪燕?
- 在這篇文章里娶牌,我將帶你理解 Base64 的基本原理 & 實(shí)現(xiàn)。如果能幫上忙馆纳,請務(wù)必點(diǎn)贊加關(guān)注诗良,這真的對我非常重要。
系列文章
- 《密碼學(xué) | 廬山真面鲁驶!你認(rèn)為 Base64 是加密算法嗎鉴裹?》
- 《密碼學(xué) | 蓄勢待發(fā)!說說什么是散列算法钥弯?》
- 《密碼學(xué) | 高屋建瓴径荔!摘要贷盲、簽名與數(shù)字證書都是什么厂抽?》
相關(guān)文章
目錄
1. 基本原理
Base64
是一種將二進(jìn)制流表示為 64 個字符的編碼方式睛蛛。標(biāo)準(zhǔn)的 Base64 使用的索引表為:
舉個例子鹦马,字符串"Base64 編碼"
經(jīng)過編碼后的結(jié)果為:QmFzZTY0IOe8lueggQ==
胧谈。當(dāng)然,這里隱含了以UTF-8
作為字符編碼的前提荸频,如果使用了其他的字符編碼方式菱肖,用Base64
編碼后就不是這個結(jié)果了。很多在線編解碼的網(wǎng)站其實(shí)也是默認(rèn)使用了UTF-8
旭从,但是沒有明確說明稳强。
1.1 標(biāo)準(zhǔn) Base64 編碼步驟
下面解釋一下Base64
的編碼步驟:
步驟1:數(shù)據(jù)輸入
在這一步驟,需要將原數(shù)據(jù)(字符串遇绞、圖片键袱、音頻等任何數(shù)據(jù))轉(zhuǎn)換為二進(jìn)制流。例如前面舉的字符串的例子摹闽,則需要經(jīng)過字符編碼轉(zhuǎn)換為二進(jìn)制流蹄咖。-
步驟2:分組轉(zhuǎn)換
- 從二進(jìn)制流頭部開始,每 6 位為一組付鹿,若不足 6 位澜汤,則低位補(bǔ)0
- 每 6 位組成一個新的字節(jié),高位 2 位補(bǔ) 0 舵匾,此時已經(jīng)獲得二進(jìn)制的
Base64
編碼
步驟3:轉(zhuǎn)換為字符串
將二進(jìn)制的Base64
編碼每個字節(jié)映射為一個字符俊抵,例如0000 0000
映射為A
,0011 1111
映射為/
坐梯,此時已經(jīng)獲得Base64
編碼字符串步驟4:末尾補(bǔ)位
標(biāo)準(zhǔn)Base64
編碼字符串的長度為 4 的倍數(shù)徽诲,否則,在末尾補(bǔ)充=
吵血。例如前面的QmFzZTY0IOe8lueggQ==
長度就是補(bǔ)充了兩個=
后谎替,長度為 20。
整個編碼步驟并不復(fù)雜蹋辅,我們用一張示意圖表示為:
1.2 非標(biāo)準(zhǔn) Base64
Url Base 64
標(biāo)準(zhǔn)Base 64
中使用了'/'
钱贯,這在URL
和文件系統(tǒng)中存在沖突,因此延伸出 Url Base64 算法侦另,主要就是將'+'
和'/'
符號替換成了'-'
和'_'
符號秩命。MIME Base 64
這是一種MIME
友好格式,它輸出每行為 76 個字符褒傅,每行末需追加回車換行符\r\n
弃锐,不論每行是否夠 76 個字符,都要添加一個回車換行符
1.3 意義
Base64
能夠?qū)⑷魏螖?shù)據(jù)轉(zhuǎn)換為易移植的字符串殿托,避免了傳輸過程中失真問題霹菊。最初,Base64
是為了解決電子郵件中無法直接使用非ASCII
字符的問題碌尔。一段數(shù)據(jù)先經(jīng)過Base64
編碼為ASCII
字符串后浇辜,可以在接收端,通過Base64
解碼還原為原數(shù)據(jù)后唾戚,而無需擔(dān)心傳輸過程中失真柳洋。
很多時候,我們都將Base64
編碼作為數(shù)據(jù)加密后的傳輸 / 存儲格式叹坦。例如熊镣,一段明文數(shù)據(jù)通過MD5 、SHA
等手段加密后募书,經(jīng)過Base64
編碼為字符串绪囱,就可以很方便地進(jìn)行傳輸 & 存儲。再比如莹捡,網(wǎng)絡(luò)上的數(shù)字證書其實(shí)也是使用Base64
編碼的形式傳輸?shù)墓沓常覀兛梢栽跒g覽器上查看百度官網(wǎng)的數(shù)字證書:
需要注意的是,Base64
并不是一種加密方式篮赢,明文使用Base64
編碼后的字符串通過索引表可以直接還原為明文齿椅。因此,Base64
只能作為一種數(shù)據(jù)的存儲格式启泣。
2. 算法實(shí)現(xiàn)
2.1 Java 環(huán)境
在Java 8
之前涣脚,JDK中并沒有提供Base64
的算法實(shí)現(xiàn),這其實(shí)挺讓人納悶的寥茫。雖然源碼中sun.misc.BASE64Encoder
遣蚀,但是它其實(shí)并不是公有 API,而是 sun 團(tuán)隊(duì)內(nèi)部使用的 API纱耻,最好不要在生產(chǎn)中使用芭梯。從Java 8
,JDK 總算是補(bǔ)充了Base64
的實(shí)現(xiàn)膝迎,例如:
import java.util.Base64;
標(biāo)準(zhǔn) Base 64
System.out.println(Base64.getEncoder().encodeToString("".getBytes()));
Url Base 64
System.out.println(Base64.getUrlEncoder().encodeToString("".getBytes()));
MIME Base 64
System.out.println(Base64.getMimeEncoder().encodeToString("".getBytes()));
在Java 8
之前粥帚,Bouncy Castle
和Apache
也提供了Base64
的算法實(shí)現(xiàn)。
2.2 Android環(huán)境
Android SDK
提供了Base64
的算法實(shí)現(xiàn)限次,例如:
import android.util.Base64;
System.out.println(Base64.encodeToString("".getBytes(),Base64.DEFAULT));
相對于Java 8
的算法實(shí)現(xiàn)芒涡,Android
提供的 API 更為靈活,可以通過flag
自定義控制算法的輸出卖漫。
3. 總結(jié)
-
Base 64
能夠?qū)⑷魏螖?shù)據(jù)轉(zhuǎn)換為易移植的字符串费尽,避免了傳輸過程中失真問題。 - 需要注意的是羊始,
Base 64
不是一種加密方式旱幼,只是一種編碼方式。很多時候突委,我們都將Base64
編碼作為數(shù)據(jù)加密后的傳輸 / 存儲格式
參考資料
- 《Java加密與解密的藝術(shù)》(第5章) —— 梁棟 著
- 《HTTP權(quán)威指南》 —— [美] David Gourley柏卤,Brian Totty等 著
- 《Base64》 —— 維基百科
推薦閱讀
- Java | 帶你理解 ServiceLoader 的原理與設(shè)計(jì)思想
- Java | 請概述一下 Class 文件的結(jié)構(gòu)
- Java | 聊一聊編譯過程(編譯前端 & 編譯后端)
- Java | 為什么 Java 實(shí)現(xiàn)了平臺無關(guān)性?
- Android | 一個進(jìn)程有多少個 Context 對象(答對的不多)
- Android | 帶你理解 NativeAllocationRegistry 的原理與設(shè)計(jì)思想
- Android | 一文帶你全面了解 AspectJ 框架
- 計(jì)算機(jī)組成原理 | Unicode 和 UTF-8是什么關(guān)系冬三?
- 計(jì)算機(jī)組成原理 | 為什么浮點(diǎn)數(shù)運(yùn)算不精確?(阿里筆試)