Base64 是一種基于 64 個可打印字符來表示二進制數(shù)據(jù)的表示方法鲁冯。
1.base64 算法的由來
base64 最早是用作解決電子郵件的傳輸問題,由于歷史原因摇肌,早期電子郵件只允許傳輸 ASCII 碼字符,如果想傳輸一封帶有非 ASCII 字符的郵件,在遇到一些老舊的網(wǎng)關(guān)就可能會對字符最高位進行調(diào)整访得,導(dǎo)致收到的郵件出現(xiàn)亂碼。
2.base64 不是加密算法
base64 算法的編碼和解碼方法可以作為加密和解密操作陕凹,但是不能叫做加密算法悍抑,因為其算法和充當(dāng)密鑰的索引表都是公開的鳄炉。最多是讓在你身后的人一時看不懂,所謂防君子不防小人传趾。
3.Base 編碼方法
轉(zhuǎn)換的時候迎膜,將三個 byte 的數(shù)據(jù),先后放入一個 24bit 的緩沖區(qū)中浆兰,先來的 byte 占高位磕仅。數(shù)據(jù)不足 3byte 的話,剩下的 bit 用 0 補足簸呈。然后榕订,每次取出 6 個 bit,按照其值選擇索引表的字符作為編碼后的輸出蜕便。不斷進行劫恒,直到全部輸入數(shù)據(jù)轉(zhuǎn)換完成。
這里就不舉例說明轿腺,具體可以參考維基百科两嘴。
4.base64 索引表如下
| 數(shù)值 | 字符 | 數(shù)值 | 字符 | 數(shù)值 | 字符 | 數(shù)值 | 字符 |
| - | - | | - | - | | - | - | | - | - |
| 0 | A | 16 | Q | 32 | g | 48 | w |
| 1 | B | 17 | R | 33 | h | 49 | x |
| 2 | C | 18 | S | 34 | i | 50 | y |
| 3 | D | 19 | T | 35 | j | 51 | z |
| 4 | E | 20 | U | 36 | k | 52 | 0 |
| 5 |F |21 |V |37 |l |53 |1
| 6 |G |22 |W |38 |m |54 |2
| 7 |H |23 |X |39 |n |55 |3
| 8 |I |24 |Y |40 |o |56 |4
| 9 |J |25 |Z |41 |p |57 |5
| 10 |K |26 |a |42 |q |58 |6
| 11 |L |27 |b |43 |r |59 |7
| 12 |M |28 |c |44 |s |60 |8
| 13 |N |29 |d |45 |t |61 |9
| 14 |O |30 |e |46 |u |62 |+
| 15 |P |31 |f |47 |v |63 |/
5.一個簡單的編碼方法和譯碼方法實現(xiàn):
var base64Encode = function(data) {
var map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var out = '';
for (var i = 0, len = data.length; i < len; i += 3) {
var binStr = '',
newStr = '',
threeChar = data.slice(i, i+3);
for (var j = 0; j < 3; j++) {
var t = threeChar.charCodeAt(j).toString(2);
while (t.length < 8) t = '0' + t;
binStr += t;
}
for (var k = 0; k < 24; k += 6) {
newStr += map[parseInt(binStr.slice(k, k+6), 2)];
}
if (i+3-len == 1) newStr = newStr.slice(0, 3) + '=';
if (i+3-len == 2) newStr = newStr.slice(0, 2) + '==';
out += newStr;
}
return out;
};
var base64Decode = function(code) {
var map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var ascii = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
var out = '';
for (var i = 0, len = code.length; i < len; i += 4) {
var fourChar = code.slice(i, i+4),
binStr = '',
newStr = '';
for (var j = 0; j < 4; j++) {
var t = map.indexOf(fourChar.charAt(j)).toString(2);
while (t.length < 6) t = '0' + t;
binStr += t;
}
for (var k = 0; k < 24; k += 8) {
var char = ascii[parseInt(binStr.slice(k, k+8), 2) - 32];
if (char !== undefined) newStr += char;
}
out += newStr;
}
return out;
};
HTML5 提供的通用 Base64 方法 API
1.編碼: window.btoa(stringToEncode)
只能將 ASCII 字符串或二進制數(shù)據(jù)轉(zhuǎn)換成一個 base64 編碼過的字符串,該方法不能直接作用于 Unicode 字符串。
2.解碼: window.atob(encodedData)
將已經(jīng)被 base64 編碼過的數(shù)據(jù)進行解碼族壳。
3.作用于 UTF-8 編碼的文字
但是這兩個 Web API 功能很簡單憔辫,并不能直接作用于 Unicode 字符串,所以當(dāng)調(diào)用 btoa()
時若傳入的不是 ASCII 或二進制字符串仿荆,比如漢字就會出錯贰您。
下面是別人提供的簡單解決方法:
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent(str)));
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob(str)));
}
作者在這里使用了一個小小的Hack技巧。encodeURIComponent()
是ECMAscript中Global對象的URI方法拢操,對URI進行編碼锦亦,可以作用于所有Unicode字符。而 escape()
是已廢棄的URI編碼方法令境,功能和 encodeURIComponent()
相同杠园,但是只能編碼ASCII字符。
即 encodeURIComponent(str)
相當(dāng)于 escape(unicodeToASCII(str))
舔庶,則 unescape(encodeURIComponent(str))
等同于 unicodeToASCII(str)
,所以就將 Unicode 字符轉(zhuǎn)換成了 ASCII 字符返劲。( unescape()
是和 escape()
對應(yīng)的解碼方法)
關(guān)于文字集和文字編碼方面的知識,比如 UTF-8 是基于 Unicode 文字集的一種廣泛使用的編碼方式栖茉,具體此處不再贅述篮绿。
Data URL與Base64
這里主要說說 Data URL 模式和 Base64 ,比如下面這段代碼:
console.log("\n\n\n%c", 'font-size:0;margin-top:20px;line-height:36px;padding-top:50px;padding-left:158px;background:url("data:image/png;base64,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");background-repeat:no-repeat;')
這是一個真實的小例子吕漂,可以在百度網(wǎng)盤看到亲配,會在控制臺打印出百度云logo。這里用到了 console.log()
的一些稍微高級一點的用法,支持類似C語言 printf()
風(fēng)格的打印方式吼虎,占位符 %c
可以使用一些CSS樣式語句犬钢。比如這里使用的:
font-size: 0;
margin-top: 20px;
line-height: 36px;
padding-top: 50px;
padding-left: 158px;
background: url("data:image/png;base64...");
background-repeat: no-repeat;
關(guān)于 console.log()
的用法以及 console
對象的其他方法、屬性思灰,具體此處不再贅述玷犹。
回到 url,可以看到一長串?dāng)?shù)據(jù)洒疚,在開頭是這樣的:
data:image/png;base64...
這就是 Data URL Scheme 的語法格式歹颓,后面是用 Base64 編碼的圖片數(shù)據(jù)。
完整的圖片就像下面這樣油湖,可以直接復(fù)制到地址欄查看:
data:image/png;base64,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
不過巍扛,F(xiàn)irefox 似乎不支持在控制臺使用 Data URL,大概是由于這個原因乏德,有時候可以降級在控制臺直接使用一張圖片撤奸。
參考資料:
- https://developer.mozilla.org/zh-CN/docs/Web/API/Window.btoa
- https://developer.mozilla.org/zh-CN/docs/Web/API/Window.atob
- RFC 2397 of the Internet Engineering Task Force (IETF)
- Javascript高級程序設(shè)計(第3版)[人民郵電出版社]
- Java加密與解密的藝術(shù)[機械工業(yè)出版社]
【原文鏈接:http://mirreal.github.io/blog/2014/11/06/base64-note/】