Base64 是一種將任意二進位資料編碼為純 ASCII 文字的方式。它使用 64 個可列印字元(A-Z、a-z、0-9、+、/)來表示任意位元組資料,常用於需要在文字協議(如 HTTP、SMTP 電子郵件)中傳輸二進位資料的場景。
名稱「Base64」中的 64 代表這個編碼系統使用的字符集大小,每個 Base64 字元代表 6 個位元(2^6 = 64)。
Base64 不是加密!它只是一種編碼方式,任何人都可以直接解碼,不提供任何安全保護。
| 索引 | 字元 | 索引 | 字元 | 索引 | 字元 | 索引 | 字元 |
|---|---|---|---|---|---|---|---|
| 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 | / |
另外還有一個特殊的 padding 字元 =,用於補足長度。
Base64 編碼將每 3 個位元組(24 位元)轉換為 4 個 Base64 字元(每個字元 6 位元)。步驟如下:
範例:「Man」編碼過程
M = 0x4D = 01001101
a = 0x61 = 01100001
n = 0x6E = 01101110
24 位元:010011 010110 000101 101110
索引:19, 22, 5, 46
結果:T, W, F, u → TWFu
因為 Base64 每次處理 3 個位元組,若原始資料長度不是 3 的倍數,需要補上 padding:
// JavaScript 範例
btoa("A") // → "QQ==" (1 個位元組,補 2 個 =)
btoa("AB") // → "QUI=" (2 個位元組,補 1 個 =)
btoa("ABC") // → "QUJD" (3 個位元組,不補 =)
btoa("Man") // → "TWFu" (3 個位元組,不補 =)
標準 Base64 使用 + 和 / 兩個字元,這兩個字元在 URL 中有特殊含義(+ 代表空格,/ 是路徑分隔符),若直接放入 URL 會導致解析錯誤。
為解決此問題,RFC 4648 定義了 URL-safe Base64 變體:
// JavaScript:標準 Base64 轉 URL-safe Base64
function toUrlSafeBase64(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// 還原 URL-safe Base64 為標準 Base64
function fromUrlSafeBase64(str) {
var b64 = str.replace(/-/g, '+').replace(/_/g, '/');
while (b64.length % 4 !== 0) {
b64 += '=';
}
return atob(b64);
}
JWT 由三個 URL-safe Base64 編碼的部分組成,以 . 分隔:
// JWT 結構:header.payload.signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
// 解碼 payload 部分
atob('eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0')
// → '{"sub":"1234567890","name":"John Doe"}'
將圖片直接嵌入 HTML 或 CSS 中,避免額外的 HTTP 請求:
<!-- HTML 中嵌入小圖片 -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" alt="1x1 pixel">
/* CSS 中嵌入背景圖 */
.icon {
background-image: url('data:image/svg+xml;base64,PHN2Zy4uLjwvc3ZnPg==');
}
HTTP Basic Auth 使用 Base64 編碼傳輸帳號密碼(注意:這不是加密,僅是編碼!):
// 帳號:admin,密碼:password123
const credentials = btoa('admin:password123');
// → "YWRtaW46cGFzc3dvcmQxMjM="
fetch('/api/data', {
headers: {
'Authorization': 'Basic ' + credentials
}
});
電子郵件協議(SMTP)是文字協議,附件(二進位檔案)必須以 Base64 編碼後才能在郵件中傳輸。這也是 Base64 最初被設計出來的原始用途。
Base64 編碼後,資料大小會增加約 33%(每 3 個位元組變成 4 個字元)。若加上換行符(每 76 個字元換行),實際膨脹約 36-37%。在選擇是否使用資料 URI 嵌入圖片時,需考量此因素。
| 原始大小 | Base64 大小 | 增加比例 |
|---|---|---|
| 1 KB | ~1.37 KB | +37% |
| 10 KB | ~13.7 KB | +37% |
| 100 KB | ~137 KB | +37% |
| 1 MB | ~1.37 MB | +37% |
Base64 不是加密!
Base64 只是編碼,任何人都可以直接解碼看到原始內容。不要用 Base64 來「保護」敏感資料(如密碼、API 金鑰),必須另外搭配加密機制。
HTTP Basic Auth 的安全性
HTTP Basic Auth 使用 Base64 傳輸帳號密碼,必須搭配 HTTPS(TLS)使用,否則帳號密碼在傳輸過程中等同明文可見。