cv.cm

知識 · 文字、資料與資安

Base64 編碼是什麼?

閱讀約 5 分鐘

簡答

Base64 是只用 64 個可列印字元來表示二進位資料的方法:A–Z、a–z、0–9、+ 和 /,並以 = 作為補位。它把每 3 個位元組拆成四組 6 位元,每組對應一個字元,所以「Man」會變成「TWFu」。這讓二進位資料能安全地透過只接受文字的管道傳送,例如電子郵件、JSON 和 URL,代價是大小增加約 33%。它是一種編碼,不是加密。

開啟Base64

Base64 運作步驟

Base64 定義於 RFC 4648。因為 64 = 2⁶,每個輸出字元剛好承載 6 位元,3 個位元組(24 位元)正好對應 4 個字元。

步驟Man
ASCII 碼7797110
二進位(各 8 位元)010011010110000101101110
  1. 把 24 個位元接起來:010011010110000101101110。
  2. 切成四組 6 位元:010011 010110 000101 101110。
  3. 換算成數字:19、22、5、46。
  4. 逐一查對照表(0 = A、25 = Z、26 = a、51 = z、52 = 0、61 = 9、62 = +、63 = /):T、W、F、u。
  5. 結果:TWFu。

用 = 補位

輸入長度不是 3 的倍數時,最後一組會以 0 位元補滿,並用 = 標示缺少的位元組,因此輸出長度一定是 4 的倍數。

輸入位元組數Base64
M1TQ==
Ma2TWE=
Man3TWFu
Hello5SGVsbG8=
é(UTF-8 位元組 C3 A9)2w6k=

n 個位元組編碼後的長度是 4 × ceil(n ÷ 3) 個字元。1 MB 的檔案會變成約 1.33 MB 的文字;MIME 電子郵件每 76 個字元還會加一個換行,額外負擔再略高一點。

Base64 用在哪裡

  • 電子郵件附件:早期郵件系統只能傳送 7 位元文字,所以 MIME 以 Base64 編碼檔案。
  • Data URL:直接內嵌在 HTML 或 CSS 中的小圖片,寫成 data:image/png;base64,iVBORw0KGgo...。
  • 需要傳送圖片、金鑰或憑證等二進位資料的 JSON 與 XML API。
  • JSON Web Token(JWT),其標頭和酬載是以 Base64url 編碼的 JSON。
  • TLS 憑證與金鑰的 PEM 檔,會把 Base64 包在 -----BEGIN CERTIFICATE----- 這類標記行之間。
  • HTTP Basic 驗證,會把 username:password 以 Base64 編碼後送出。

把圖片以 Data URL 內嵌可以省一次網路請求,但大小會增加 33%,也無法單獨快取,所以通常只對非常小的圖片划算。

Base64、Base64url 與其他編碼

標準 Base64 使用 + 和 /,這兩個字元在 URL 和檔案名稱中有特殊意義。同一份 RFC 中的 URL 安全版本把它們換成 - 和 _,而且常省略 = 補位。

編碼字元大小增幅用途範例
Base16(十六進位)0–9、A–F100%雜湊值、色碼
Base32A–Z、2–760%雙重驗證金鑰
Base64A–Z、a–z、0–9、+、/33%電子郵件、Data URL、PEM
Base64urlA–Z、a–z、0–9、-、_33%JWT、URL 參數

常見錯誤

  • 文字必須先轉成位元組,通常是 UTF-8。在 JavaScript 中,若字串含有表情符號或中文等 Latin-1 以外的字元,沒有先做 UTF-8 編碼,btoa() 就會拋出錯誤。
  • 混用標準與 URL 安全的字元表會導致解碼失敗;用標準解碼器之前,先把 - 和 _ 換回 + 和 /。
  • 缺少補位可能讓嚴格的解碼器失敗;請補上 =,直到長度是 4 的倍數。
  • 電子郵件式編碼產生的換行,必須先移除,有些解碼器才肯接受。

常見問題

為什麼 Base64 會讓資料變大?

每 3 個位元組變成 4 個字元,而每個字元都要用一整個位元組儲存,所以輸出比輸入大約多 33%。

Base64 安全嗎?

不安全。它什麼都沒隱藏,解碼也不需要金鑰。要保護資料請用 AES 等真正的加密,Base64 只用來把結果以文字形式傳送。

Base64 結尾的 = 是什麼意思?

那是補位。一個 = 表示最後一組有 2 個位元組,== 表示只有 1 個位元組。

怎麼辨認 Base64 字串?

它只包含英文字母、數字、+ 和 /(或 - 和 _),長度通常是 4 的倍數,結尾可能有一或兩個 = 號。以 eyJ 開頭的字串常是 Base64 編碼的 JSON,因為以 {" 開頭的 JSON 文字編碼後會以 eyJ 開頭。

所有知識文章