[比較] 10 min read

[比較] Base64 vs Base64URL vs Base32

三種編碼、同一份 RFC。這裡說明它們真正的差異 —— 字母表、開銷、可讀性、大小寫敏感性 —— 以及如何為 URL、檔名、電子郵件、QR code 與「口說出來的」代碼挑選正確變體。

April 2026 | comparison

// 快速比較表

                 Base64          Base64URL        Base32
                 (RFC 4648 §4)   (RFC 4648 §5)    (RFC 4648 §6)
────────────────────────────────────────────────────────────────
Alphabet size    64              64               32
Bits per char    6               6                5
Characters used  A-Z a-z 0-9     A-Z a-z 0-9      A-Z 2-7
                 + /             - _              (+ = for pad)
Padding          = (required)    = (optional)     = (optional)
Case-sensitive   Yes             Yes              No (A = a)
Size overhead    ~33%            ~33%             ~60%
URL-safe         No              Yes              Yes
Filename-safe    No              Yes              Yes
DNS-safe         No              Yes              Yes
Human-readable   Medium          Medium           High
Human-spoken     Painful         Painful          Doable
QR-code friendly OK              OK               Excellent
                 (alphanumeric)  (alphanumeric)   (alphanumeric mode)

// 它們的共同點

三者皆在 RFC 4648 中定義 —— 這份 2006 年的單一文件統整了「以 N 為底把二進位轉為文字」的家族編碼。它們共用相同的底層演算法:取二進位輸入,把位元重新分組成 log₂(字母表大小) 的區塊,把每個區塊對應到一個字元,並在輸出字邊界上補齊填充。

• Base64:6 位元區塊 → 每 3 個位元組對應 4 個字元(4/3 比例,大約 33% 大)
• Base32:5 位元區塊 → 每 5 個位元組對應 8 個字元(8/5 比例,大約 60% 大)
• Base16(十六進位):4 位元區塊 → 每 1 個位元組對應 2 個字元(2/1 比例,100% 大)

三者皆可逆、具決定性,並保留輸入的每一個位元組。它們是編碼,不是壓縮,也不是加密。任何拿到字串的人都能解碼回來。

// 何時該選標準 BASE64 (§4)

標準 Base64 是非 URL 文字通道的預設選擇。MIME 郵件內容、PEM 包裹的憑證、HTTP Basic Auth、S/MIME、XML-DSIG、data URI,以及大多數「文字中嵌二進位」的檔案格式容器都使用它。字元 + / = 在引號屬性值中、郵件標頭(折行後)中,以及 XML/JSON 字串中都是安全的。

當下游消費者是接受任意可列印 ASCII 的文字協定時——尤其是 RFC 規格層級明確指定時(MIME:RFC 2045;PEM:RFC 7468;HTTP Basic Auth:RFC 7617;data URI:RFC 2397)——請使用標準 Base64。

  • > 電子郵件附件(MIME base64 傳輸編碼)
  • > PEM 憑證、金鑰、CRL(-----BEGIN ... -----)
  • > HTTP Basic Authentication 標頭值
  • > Data URI:data:image/png;base64,...
  • > S/MIME 與 XML-ENC 酬載
  • > 傳統的 SOAP / XML-DSIG 簽章
  • > JSON 文件中任何之後不會放進 URL 的二進位欄位

// 何時該選 BASE64URL (§5)

只要你的 Base64 輸出碰到 URL、cookie 值、檔名、DNS 標籤,或任何 + / = 會需要百分比編碼的地方,就改用 Base64URL。它用相同的 64 字元字母表,只作兩處替換(+ → -/ → _),並依慣例省略填充。

  • > JWT 權杖 —— 標頭、酬載與簽章都使用 base64url(RFC 7515)
  • > OAuth 2.0 PKCE 的 code_challenge(RFC 7636)
  • > OpenID Connect 的 state 與 nonce 參數
  • > 魔法連結、邀請權杖、密碼重設權杖
  • > 可能被複製進 URL 的 cookie 值
  • > 從雜湊值產生的檔名 —— 避免檔名中的 /
  • > DNS 標籤、TXT 紀錄 —— 允許連字號,不允許斜線
  • > 以內容定址的儲存金鑰
  • > 由隨機位元組產生的短 URL 識別碼

// 何時該選 BASE32 (§6)

Base32 只使用 32 個字元:大寫 A–Z 與數字 2–7。體積開銷約 60% —— 比 Base64 差得多 —— 但你可以換到三項 Base64 無法匹敵的特定特性。

大小寫不敏感。字母表只有大寫。讀字串或打字的人可以不管大小寫;JBSWY3DPjbswy3dp 解碼結果相同。

消除模糊字元。數字 0、1、8、9 被排除,因為它們在常見字型中看起來像 O、I、B 與 g。只使用 2–7。這讓人類從紙本或手機螢幕上抄寫時可靠得多。

QR code 字母數字模式相容。QR code 有一種特殊的「字母數字模式」,以 5.5 位元 / 字元編碼,使用 ASCII 的子集合。Base32 完全落在這個子集合中(加上填充),所以相同酬載以 Base32 編碼後的 QR code 會比 Base64 編碼後小得多。

  • > TOTP / HOTP 密鑰種子 —— Google Authenticator、1Password、Authy 全部使用 Base32
  • > Tor .onion v3 位址 —— 以 56 字元 Base32 編碼的 ed25519 金鑰
  • > 以磁力連結分享的 BitTorrent info-hash
  • > 類 geohash 的人類可分享位置代碼
  • > 授權金鑰與產品序號
  • > 列印出的復原碼(2FA 備用碼、錢包助記詞)
  • > 經由語音通道的類 DTMF 口頭傳遞
  • > 需要大小寫不敏感儲存的系統(DNS 標籤)

// 體積開銷 —— 具體例子

// Input: a 32-byte SHA-256 hash
// Raw: 0x89abcdef…                             (32 bytes, binary — can't put in text)
// Hex (Base16): 40b2e2…                        (64 chars, 100% overhead)
// Base32:       5ENM4H2TQWMZ3O4OQBJAFY5Q       (56 chars, 75% overhead)
// Base64:       ia+N7/eZtRsPj5TqFoqUlD…        (44 chars, 37% overhead)
// Base64URL:    ia-N7_eZtRsPj5TqFoqUlD…        (43 chars, 34% overhead, no padding)

// Input: a 16-byte UUID
// Hex:       e7a6c1d0-4b7d-4c6c-8e2f-9f1a3e4b5c6d (36 chars incl. dashes)
// Base32:    5WTMDUCLPVGGZDRPTF…                  (26 chars)
// Base64:    56bB0Et9TGyOL58aPktcbQ==             (24 chars)
// Base64URL: 56bB0Et9TGyOL58aPktcbQ               (22 chars, no padding)

// 人類可讀性測試

這正是 Base32 大放異彩之處。試著大聲念出這些字串:

a+b/c1D2e3F/+g= —— Base64。「小寫 a、加號、小寫 b、斜線、小寫 c、1、大寫 D、2、小寫 e、3、大寫 F、斜線、加號、小寫 g、等號。」光是大小寫就容易抄錯。

JBSWY3DPEHPK3PXP —— Base32。「J-B-S-W-Y、3、D-P-E-H-P-K、3、P-X-P。」大小寫無關緊要。沒有 0/O1/l 的模糊。透過電話念出來也能可靠地傳達。

這正是 TOTP 使用 Base32 的原因:總得有人從 QR code 的備援畫面把種子打進自己的驗證器 App。若用 Base64,光是大小寫敏感就會製造無止境的客服工單。

// QR CODE 尺寸比較

QR code 有一種特殊的「字母數字模式」,用 45 個字元的子集合以 5.5 位元 / 字元的密度編碼:0–9、A–Z(只限大寫)、空白,以及 $ % * + - . / :。任何超出此子集的內容都會讓 QR code 切到「位元組模式」,改為 8 位元 / 字元——結果就是 QR code 明顯變大。

Base32 完全落在字母數字子集內。Base64 則否——小寫字母與 +/= 會強迫進入位元組模式(嚴格說 +/ 也在字母數字集合裡,但只要有任何小寫字母就會強迫切換)。這代表同一份酬載以 Base32 編碼時,QR code 能小得多——常常是好讀的 21×21 QR 與擁擠的 33×33 QR 的差別。

// 解碼陷阱

  • > 大小寫敏感 —— Base64 解碼器會拒絕大小寫錯誤的輸入(SGVsbG8=sgvSbg8=)。Base32 解碼器通常會在查表前把輸入正規化成大寫,因此能容忍任何大小寫。
  • > 填充 —— 標準 Base64 必須有 = 填充;JWT/base64url 禁止填充;Base32 讓它可選(RFC 4648 §6)。永遠確認你的解碼器期望為何。
  • > 空白 —— MIME Base64 會在 76 欄以 CR-LF 折行。許多解碼器能容忍空白,有些不行。餵給 atob() 或同等函式前先去除空白。
  • > 字母表衝突 —— 把 Base64 餵給 Base32 解碼器(或反過來)起初看似能用——ABC 在兩者中都有效——直到遇到 += 才無聲失敗。
  • > Crockford Base32 是 Stripe ID 與部分區塊鏈系統使用的非 RFC 變體。它使用不同的字母表(排除 I、L、O、U)並支援檢查碼。別和 RFC 4648 Base32 搞混。
  • > Base32 Extended Hex(RFC 4648 §7) —— 另一種保留字典序的 Base32 字母表。用於 DNSSEC 的 NSEC3 紀錄。容易與標準 Base32 搞混。

// 決策流程圖

Does the output go into a URL, cookie, filename, DNS, JWT, or OAuth flow?
│
├─ Yes  →  Does a human need to type or speak the string?
│         │
│         ├─ Yes  →  Base32 (uppercase, no ambiguous chars)
│         │         e.g., TOTP seeds, recovery codes
│         │
│         └─ No   →  Base64URL (more compact, URL-safe)
│                   e.g., JWT, short tokens, hash-named files
│
└─ No  →  Does the output go into a QR code that must stay tiny?
          │
          ├─ Yes  →  Base32 (fits in QR alphanumeric mode)
          │
          └─ No   →  Standard Base64
                    e.g., email MIME, PEM, HTTP Basic, data URI

// 為什麼不用 BASE16(十六進位)?

十六進位(RFC 4648 §8 稱為 Base16)是萬用後備方案。每個 shell 工具、除錯器與協定都懂它。它大小寫不敏感、對人類極易讀、也極易實作。但它會把酬載尺寸加倍(100% 開銷),所以只用在小型、固定長度的識別碼上:SHA-256 雜湊(64 個十六進位字元 = 32 位元組)、UUID(32 個十六進位字元 = 16 位元組)、MAC 位址、除錯器中的記憶體位址。

超過幾十位元組以後,十六進位的傳輸成本會明顯難以忍受。Base64 比十六進位小 50%,Base32 則小 25%。這正是為什麼 Base64 贏得了電子郵件與網頁嵌入的用例,而十六進位則停留在除錯與雜湊顯示情境。

// 那 BASE58 / BASE62 / BASE85 呢?

還有一些非 RFC 的以 N 為底的編碼存在於特定領域:
Base58 —— 比特幣地址、Flickr 照片 ID。排除四個模糊字元(0、O、I、l)與 +/,以便人類抄寫。約 37% 開銷。
Base62 —— 短網址、Twitter snowflake ID。只使用英數字(無特殊字元),在 URL 中無需跳脫。約 34% 開銷。
Base85 / Ascii85 / Z85 —— PostScript、PDF、較舊的 ZeroMQ 訊框。約 25% 開銷(比 Base64 更緊湊)但含有棘手的字元選擇,可能導致 XML/JSON 跳脫地獄。

這些挺有趣,但都不是 RFC 4648 標準。如果你要發佈一個公開協定,Base64 或 Base64URL 幾乎永遠是更安全的預設,因為每種語言的標準函式庫都已原生支援。若你選了 Base58,就得把相依套件推送給每一位消費者。

// 並排試用

Base64 編碼器 —— 標準字母表,附 URL 安全切換
Base64URL 編碼器 —— URL 安全、已剝除填充
Base32 編碼器 —— RFC 4648 §6 字母表
Base16(十六進位)編碼器 —— 供比較
Base58 編碼器 —— 比特幣式的人類友善字母表

延伸閱讀:
什麼是 Base64?它是如何運作的?
URL 安全 vs 標準 Base64 —— 完整故事
Base64 處理 UTF-8 與 Unicode