前幾天,在處理IOS-SDK,遇到了歷史遺留關(guān)于base64相關(guān)的問題,于是翻查資料,并總結(jié)如下
Base64 內(nèi)容傳輸編碼
Base64 內(nèi)容傳輸編碼旨在表示任意形式的八位字節(jié)序列督函,不需要人為可讀。編碼和解碼算法很簡(jiǎn)單激挪,但是編碼數(shù)據(jù)始終只比原始數(shù)據(jù)大 33%的未編碼的數(shù)據(jù)辰狡。這種編碼實(shí)際上使用的編碼與 RFC 1421 中定義的隱私增強(qiáng)郵件 (PEM) 應(yīng)用程序中的編碼相同。
說明:
使用 65 個(gè)字符的 US-ASCII 子集垄分,每個(gè)可打印字符可以使用2進(jìn)制的 6 位表示搓译。(額外的第 65 個(gè)字符,“=”锋喜, 用于表示特殊的處理功能些己。)
即: 0011 1111 表示 "/" (10進(jìn)制63), 0011 1110 表示"+"(10進(jìn)制62) 如圖。 由于6位只能到63 即 64個(gè)字符嘿般,所以使用額外的第65個(gè)字符"="來表示特殊的處理功能段标,即常說的對(duì)齊
編碼過程:
將24位的輸入位組表示為輸出由4個(gè)編碼字符(一個(gè)字符8位)組成的字符串。 從左到右炉奴,24位輸入組由3個(gè)8位輸入組串聯(lián)而成逼庞。這24位然后被視為4個(gè)連接的6位組,每組在base64字母表中轉(zhuǎn)換成一個(gè)數(shù)字瞻赶。當(dāng)通過base64編碼對(duì)位流進(jìn)行編碼時(shí)赛糟,位流必須假定最有效位在前面。也就是說砸逊,流中的第一個(gè)比特將是進(jìn)入的高階比特第一個(gè)8位字節(jié)璧南,第8位將是低階位第一個(gè)8位字節(jié),以此類推师逸。
比如: UTF-8編碼下A進(jìn)行base64Encode后輸出是QQ==
A在十進(jìn)制下是65轉(zhuǎn)換成2進(jìn)制為 0100 0001 (一個(gè)字節(jié)8位)
一個(gè)字節(jié)只能組成2個(gè)6位 不足的補(bǔ)0
視為4個(gè)連接的6位組: 01 0000 01 0000
補(bǔ)全為8位: 0001 0000 0001 0000
其中 0001 0000 轉(zhuǎn)為10進(jìn)制即16司倚, 對(duì)應(yīng)表 RFC2045_Base64.png 為Q
然后會(huì)轉(zhuǎn)換成ASCII下的 0101 0001 0101 0001 0011 1101 0011 1101
故A進(jìn)行base64Encode后輸出是QQ==(=是用來對(duì)齊的,因?yàn)橐獦?gòu)成4個(gè)字節(jié)即32位)
參考JAVA的Base64.java 的具體做法是:
由于只有一個(gè)字符所以重點(diǎn)在 if(sp < end)里面
b0 = 65 (src[sp++] = src[0] = A = 65)
dst[0] = base64[16] (RFC2045_Base64.png) 即dst[0] = Q (ASCII 值為 81)
然后sp == end (都是1)
des[1] = base64[16] (RFC2045_Base64.png) 即dst[0] = Q (ASCII 值為 81)
des[2] = '='
des[3] = '='
所以得到的byte[] 的長(zhǎng)度為4 值為 QQ==
其他情況同理可得
細(xì)心的朋友可能發(fā)現(xiàn)了上圖中有個(gè)toBase64URL并且是RFC 4648篓像,結(jié)合上面的RFC 3548
他們的差異總得來說就是3548過時(shí)了动知,但是實(shí)際上區(qū)別也并不算大
而我所遇到的問題恰恰也就是這些問題---因?yàn)楹蠖私涌谏?jí)而OC代碼混用接口,導(dǎo)致Base64解碼失斣北纭(實(shí)際情況很簡(jiǎn)單盒粮,但是因?yàn)閷?duì)OC代碼的不熟悉,對(duì)上一個(gè)編寫代碼的人的風(fēng)格也掌握不到位奠滑,所以導(dǎo)致理解出了問題----雖然我至今也不理解為什么他要這樣做)