什麼是 Base64?
Base64 用六十四個可讀字元改寫位元組,讓資料能穿過為文本設計的通道:郵件正文、JSON 字串、XML 屬性、URL。每三個位元組變成四個字元,名字由此而來 — 字母表有六十四個符號,每個恰好承載 6 個位元。
它是傳輸編碼,不是安全措施,也不是壓縮。輸出比輸入大約三分之一,任何拿到字串的人都能直接還原。想知道資料是否被改動,那是雜湊(雜湊生成器);想讓內容保密,那是加密。Base64 兩樣都不做。
要記住的那個數字:三個輸入位元組變成四個輸出字元。本頁其他一切都由此推出。四個字元承載 24 個位元,而 24 個位元恰好是三個位元組,所以資料永遠不會丟失或憑空出現 — 除了最末尾,輸入可能填不滿最後一組三個位元組。
本頁可用的五種字母表
前兩行是標準,後三行是圍繞 Unix 成長起來的慣例。五種字母表每字元承載的 6 個位元相同,區別只在用哪六十四個字元來承載,因此同樣的位元組會變成五個不同的字串。字串內部沒有任何資訊說明它出自哪個字母表,這就是字母表選擇器預設為標準、URL-safe 核取方塊是第二行快捷方式的原因。
頁面如何判斷候選:選擇器是兩個方向的預設值。解碼時,右側面板還會讀字串本身 — - 和 _ 只可能來自 URL-safe 字母表,+ 或 / 只可能來自標準字母表,靠前的 / 或 . 則指向兩種 Unix 字母表。所有能讀取當前輸入的字母表都會列在那裡,並附上它是不是候選及原因。
換行:76 與 64 字元
MIME 要求 Base64 能放進郵件而不讓某一行長得離譜,最終定為每行 76 個字元、以 CRLF 分隔。包裹證書和金鑰的 PEM 檔案用 64。換行不屬於資料:解碼器會先去掉換行把各行接回去再做別的事,因此帶換行和不帶換行的字串解碼出完全相同的位元組。除最後一行外,每行都容納整數個四字元組,這正是接回去是安全的原因。
本頁預設把輸出放在一行,除非您選擇寬度;解碼器則接受帶或不帶換行的輸入。本頁寫出的換行是普通換行符,這是文本框能容納的形式;MIME 郵件正文傳統上在每個換行前加一個回車,而現實中每種解碼器兩者都接受。
填充,以及為什麼可以去掉
當輸入不是三位元組的倍數時,最後一組四個字元不完整,由一個或兩個 = 補齊。它們完全不承載資料:只是說明四個字元裡有幾個是真的。解碼器也可以從長度推算這一點,這就是 URL-safe Base64 傳統上不留填充的原因 — = 在 URL 或檔名裡很彆扭,有些系統還會對它做百分號編碼。
選項行的核取方塊在選中 URL-safe 字母表時保留填充。其餘一切不變;承載資料的字元兩種情況下完全相同。
常見誤解
- “Base64 能隱藏資料。”不能。它是不帶金鑰的替換,全部意義就在於任何讀者都能撤銷它。把密碼或令牌包一層 Base64,誰能不能讀絲毫沒有變化。
- “Base64 是壓縮。”恰恰相反:每三個輸入位元組變成四個輸出字元,文本比它承載的資料大三分之一。
- “換行是值的一部分。”它們只是排版。增刪換行永遠不會改變還原出的位元組。
- “URL-safe 是另一種編碼。”是同一編碼換掉兩個字元:
+ 變 -、/ 變 _,使字串可以放在 URL 路徑或查詢值裡而無需轉義。
- “能解出來的字串一定是合法 Base64。”字母表字元組成的任何字串都是合法 Base64,因為 6 位元值的任意組合都對應一串有效位元組。字串只在下一步、當這些位元組被拿去對照應有格式時才會暴露問題。
- “填充能說明用的是哪個字母表。”不能,而且多數情況下字元也說明不了:標準與 URL-safe 字母表在六十四個符號中有六十二個相同,短字串常常在兩者中讀出同一結果。
常見問題
為什麼 Base64 字串有時結尾一個 =,有時兩個?一個 = 表示最後一組含三個有效字元,即兩個輸入位元組;兩個 = 表示含兩個,即一個輸入位元組。沒有 = 說明輸入長度是 3 的倍數。
Base64 能表示任意二進位制檔案嗎?能,這正是它的主要用途。本頁把輸入當作 UTF-8 文本;需要編碼非文本內容時,專用的 檔案轉 Base64 工具會讀取原始位元組。
在 API 裡該用哪種字母表?以接收方的文件為準。它說 URL-safe 就用 URL-safe;它沒說而值要放進 URL 時,去掉填充的 URL-safe 是穩妥的選擇。
輸出區分大小寫嗎?完全區分。a 和 A 是不同的值,這也是 Base64 輸錯一個字元的容錯能力遠不如 Base32 或 Crockford Base32 的原因。