Base64 詳解:6 位元分組、約 33% 大小膨脹、填充與 base64url 對比標準

Base64 是什麼——以及它不是什麼

Base64 是一種二進位轉文字的編碼方案。它將任意二進位資料轉換為可列印的 ASCII 字元字串,使該資料可以安全地嵌入到為人類可讀文字設計的環境中。Base64 不是壓縮——它會讓資料變得更大。它也不是加密——任何擁有編碼字串的人都能輕易還原原始位元組。其名稱來自它使用恰好 64 個字元的字母表,因為 2⁶ = 64,每個字元恰好可以代表 6 位元的輸入。

Base64 並非作為獨立標準而發明;它源於需要透過只可靠傳輸 7 位元 ASCII 的 SMTP 基礎設施傳送二進位電子郵件附件的需求。RFC 2045(1996 年)定義了 MIME,並為電子郵件標準化了這種編碼。十年後,RFC 4648(2006 年)將 base64 及其變體——包括 base32 和 base64url——整合到單一參考文件中。RFC 4648 至今仍是任何需要二進位轉文字編碼的新協定所使用的權威規範。

6 位元分組:三個輸入位元組如何變成四個字元

Base64 的核心是一個簡單的位元重新打包操作。二進位資料以 8 位元位元組的形式到達;base64 將這些位元重新分組為 6 位元的塊,每個塊映射到 64 個字元字母表中的一個字元。因為 6 和 8 的最小公倍數是 24,自然的處理單位是3 位元組 = 24 位元 → 4 個字元(4 × 6 位元)。以 ASCII 字串 Man 為具體例子:三個位元組為 0x4D0x610x6E,得到位元序列 01001101 01100001 01101110。重新分組為四個 6 位元值:010011(19 → T)、010110(22 → W)、000101(5 → F)、101110(46 → u)。編碼結果為 TWFu

這個 3 對 4 的位元組比率是大小膨脹的直接來源。對於每 3 個輸入位元組,無論實際位元組值為何,輸出始終是 4 個字元。對於 n 個位元組的輸入,編碼輸出為 ceil(n / 3) × 4 個字元(在填充之前),這意味著輸出始終比輸入大 33%(精確地說是 4/3 倍)。1 KB 的檔案編碼後約為 1.37 KB;1 MB 的圖像編碼後約為 1.37 MB。

字母表:A–Z、a–z、0–9、+、/

標準 base64 字母表按以下順序將 6 位元值 0–63 映射到可列印的 ASCII 字元:值 0–25 映射到大寫 AZ,值 26–51 映射到小寫 az,值 52–61 映射到數字 09,值 62 映射到 +,值 63 映射到 /。這種順序將字母置於數字之前——與 ASCII 數字順序相反——出於根植於 MIME 相容性的歷史原因。+/ 在 URL 中具有特殊含義,幾十年來造成了互操作性問題。

一個常見的誤解是 base64 與字元集無關。事實並非如此:字母表是固定的 ASCII。遇到 65 個字元集(64 個資料字元加上用於填充的 =)之外的字元的解碼器,必須根據規範上下文拒絕輸入或跳過它。RFC 4648 建議在嚴格模式下拒絕非字母表字元。等號 = 是一個標記,不是資料字元——它標記填充,不應出現在編碼字串的末尾以外的位置。

填充:等號的存在原因以及何時可以省略

由於編碼每次處理 3 個位元組,長度不能被 3 整除的輸入在末尾會留下一個不完整的組。填充解決了這個問題:它強制使編碼輸出始終是 4 個字元的倍數,使得可以僅從輸出長度計算原始位元組數。如果輸入有 1 個餘數位元組,則附加 2 個填充字元 ==。如果輸入有 2 個餘數位元組,則附加 1 個填充字元 =

透過其他方式已知總長度的上下文中,填充是可選的。RFC 7515(JSON Web 簽名規範)明確要求實作在編碼 JWT 元件時省略 = 填充,因為 JWT 三個部分之間的點已經界定了各段。因此,JWT 中的 base64url 編碼值從不以 = 結尾。恢復填充很簡單:在字串長度是 4 的倍數之前附加 = 字元。大多數現代 base64 函式庫無需特殊配置即可接受帶填充和不帶填充的輸入。

Base64url:JWT 和 OAuth 令牌中使用的 URL 安全變體

標準 base64 的 +/ 字元在 URL 上下文中存在問題。在查詢字串中,+ 被解釋為空格;/ 是路徑段分隔符。Base64url 定義於 RFC 4648 第 5 節,將 + 替換為 -,將 / 替換為 _。這兩個字元在 URL 中無需百分比編碼即可安全使用。在 base64url 上下文中通常也省略填充 =,以避免 URL 中出現 %3D

Base64url 用於需要緊湊、URL 安全的二進位表示的任何地方:JWT 的標頭和酬載部分是 base64url 編碼的 JSON;OAuth 2.0 授權碼通常是 base64url 編碼的隨機位元組;PKCE(RFC 7636)代碼驗證器和挑戰也使用 base64url。資料膨脹比率與標準 base64 完全相同——恰好 4/3——因為只有字母表不同,位元分組演算法相同。解碼 base64url 與解碼標準 base64 的操作相同,只需先將 -+_/ 進行替換。

實際大小影響以及如何在 base64 和二進位之間選擇

約 33% 的開銷是 base64 的主要實際成本。對於Data URI——使用 data:image/png;base64,... 直接在 HTML 或 CSS 中嵌入圖像、字體或 SVG——這種權衡是消除一次 HTTP 往返,代價是更大的文件。這對於小型資源(通常低於 4–8 KB)有益:節省的往返時間超過了大小增加,尤其是在高延遲連線上。對於較大的資源,大小增加會降低效能,因為更大的 HTML 文件需要更長時間解析,阻塞渲染,且無法與頁面分開快取。

HTTP 基本驗證將憑證編碼為 Authorization: Basic ... 標頭中的 base64(使用者名稱:密碼)。這不是安全措施——使用者名稱和密碼可以透過解碼輕易還原。基本驗證需要 HTTPS 才能安全;base64 編碼的存在僅因為 HTTP 標頭規範要求可列印的 ASCII。如果酬載包含敏感資訊——私鑰、社會安全號碼、醫療記錄——base64 編碼不能替代加密。請使用已驗證加密(例如 AES-GCM)或 JSON Web 加密(JWE,RFC 7516)來保護機密資料。