[COMPARE] Base64 vs Base64URL vs Base32
3つのエンコーディング、1つのRFC。実際に何が違うのか — アルファベット、オーバーヘッド、可読性、大文字小文字の区別 — そしてURL、ファイル名、メール、QRコード、人が声に出すコードに、正しいものを選ぶ方法を解説します。
// クイック比較表
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)
// 共通していること
3つすべてがRFC 4648で定義されています — 2006年の単一の文書で「base-N バイナリ-テキストエンコーディング」ファミリーを統一しました。同じ基礎アルゴリズムを共有しています:バイナリ入力を取り、ビットをlog₂(アルファベットサイズ)の塊に再グルーピングし、各塊を文字にマッピングし、出力ワード境界に揃えるためにパディングする。
• Base64:6ビットの塊 → 3バイトにつき4文字(4/3比、約33%増)
• Base32:5ビットの塊 → 5バイトにつき8文字(8/5比、約60%増)
• Base16(16進):4ビットの塊 → 1バイトにつき2文字(2/1比、100%増)
3つとも可逆、決定的、入力のすべてのバイトを保持します。エンコーディングであり、圧縮でも暗号化でもありません。文字列を持つ誰もがデコードして復元できます。
// BASE64(標準、§4)を選ぶべきとき
標準Base64は、URL以外のあらゆるテキストチャネルのデフォルトです。MIMEメール本文、PEMラップ証明書、HTTP Basic認証、S/MIME、XML-DSIG、データURI、そしてほとんどのファイル形式のテキスト内バイナリコンテナがこれを使います。文字 + / = はすべて、引用属性値の中、メールヘッダーの中(行折り返し時)、XML/JSON文字列の中で安全です。
下流の消費者が任意の印字可能ASCIIを受け入れるテキストプロトコルのときは、標準Base64を使ってください。とくにRFCレベルの仕様が明示的に言及している場合は(MIME:RFC 2045、PEM:RFC 7468、HTTP Basic認証:RFC 7617、データURI:RFC 2397)。
- > メール添付(MIME base64転送エンコーディング)
- > PEM証明書、鍵、CRL(-----BEGIN ... -----)
- > HTTP Basic認証ヘッダー値
- > データURI:data:image/png;base64,...
- > S/MIMEおよびXML-ENCペイロード
- > 古典的なSOAP / XML-DSIG署名
- > URLに入れないJSONドキュメント内のあらゆるバイナリフィールド
// BASE64URL(§5)を選ぶべきとき
Base64出力がURL、Cookie値、ファイル名、DNSラベル、あるいは + / = がパーセントエンコーディングを必要とする場所に触れた瞬間に、Base64URLに切り替えてください。同じ64文字のアルファベットを、2つの入れ替え(+ → -、/ → _)で使用し、慣例的にパディングを削除します。
- > 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では得られない3つの非常に明確な特性が得られます。
大文字小文字の区別がない。アルファベットは大文字のみです。文字列を読んだり入力したりする人間は大文字小文字を無視できます。JBSWY3DP と jbswy3dp は同じようにデコードされます。
曖昧さのない文字。数字の0、1、8、9は、一般的なフォントでO、I、B、gに似ているため除外されます。2–7のみが使われます。これにより、印刷されたページや電話画面からの人間による転記がずっと信頼できます。
QRコードの英数字モード互換性。QRコードには特別な「英数字」モードがあり、ASCIIのサブセットを使って文字あたり5.5ビットをエンコードします。Base32はそのサブセット(+ パディング)に完全に収まるため、QRエンコードされたBase32文字列はBase64よりかなり小さくなります。
- > TOTP / HOTPシークレットシード — Google Authenticator、1Password、Authyはすべてbase32
- > Tor .onion v3アドレス — ed25519鍵の56文字Base32エンコーディング
- > マグネットリンクで共有される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、イチ、大文字のD、ニ、小文字のe、サン、大文字のF、スラッシュ、プラス、小文字のg、イコール。」大文字小文字だけでも転記ミスを招きます。
• JBSWY3DPEHPK3PXP — Base32。「J-B-S-W-Y、サン、D-P-E-H-P-K、サン、P-X-P。」大文字小文字は問題なし。0/O や 1/l の曖昧さもなし。電話口で高い信頼で読み上げられます。
これこそTOTPがBase32を使う理由です:誰かがQRコードのフォールバック画面から認証アプリにシードを入力する必要があるのです。Base64の大文字小文字区別は、無限のサポートチケットを生み出すでしょう。
// QRコードサイズの比較
QRコードには特別な「英数字モード」があり、45文字のサブセット(0–9、A–Z(大文字のみ)、スペース、そして $ % * + - . / :)を使って文字あたり5.5ビットを詰め込みます。このサブセット外のものはQRコードを「バイトモード」に追い込み、そこでは文字あたり8ビットが使われます — QRコードが大幅に大きくなります。
Base32は完全に英数字サブセット内に収まります。Base64はそうではありません — 小文字と +/= はバイトモードを強制します(正確には +/ は英数字セットにありますが、小文字があるとバイトモードに切り替わります)。これは、同じペイロードでもBase32でエンコードすると小さなQRコードに収まることを意味します — しばしば読みやすい21×21のQRと混雑した33×33のQRの違いを生みます。
// デコードの落とし穴
-
>
大文字小文字の区別 — Base64デコーダーは大文字小文字が違う入力を拒否します(
SGVsbG8=≠sgvSbg8=)。Base32デコーダーは通常ルックアップ前に大文字に正規化するため、任意の大文字小文字を許容します。 -
>
パディング — 標準Base64は
=パディングを必須とし、JWT/base64urlはそれを禁止し、Base32はオプションとします(RFC 4648 §6)。デコーダーが何を期待するかを常に確認してください。 -
>
空白文字 — MIME Base64はCR-LFで76桁折り返しされます。多くのデコーダーは空白を許容しますが、そうでないものもあります。
atob()やそれに相当するものに渡す前に削除してください。 -
>
アルファベットの衝突 — Base64をBase32デコーダーに食わせる(あるいは逆)と、最初はうまくいくように見えます —
A、B、Cは両方で有効 — が、+や=に遭遇するとサイレントに失敗します。 - > 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(16進)ではないのか?
16進数(RFC 4648 §8はこれをBase16と呼びます)は汎用のフォールバックです。あらゆるシェルツール、デバッガ、プロトコルがこれを理解します。大文字小文字を区別せず、人間にとって自明に読みやすく、実装も自明です。しかしペイロードのサイズを倍にします(100%オーバーヘッド)。そのため、SHA-256ハッシュ(64 hex文字 = 32バイト)、UUID(32 hex文字 = 16バイト)、MACアドレス、デバッガのメモリアドレスのような、小さな固定長識別子にしか使われません。
数十バイトを超えるものになると、16進のサイズコストはワイヤー上で本当に苦痛になります。Base64は16進より50%小さく、Base32は25%小さくなります。だからこそBase64がメールとウェブ埋め込みのユースケースを勝ち取り、16進はデバッグやハッシュ表示のシナリオに留まったのです。
// BASE58 / BASE62 / BASE85 はどうか?
非RFCのbase-Nエンコーディングは、特定のニッチ用途で存在します:
• Base58 — Bitcoinアドレス、FlickrのフォトID。4つの曖昧な文字(0、O、I、l)と +/ を除外し、人間の転記を容易にします。オーバーヘッド約37%。
• Base62 — URL短縮、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(16進)エンコーダー — 比較用
• Base58エンコーダー — Bitcoinスタイルの人間に優しいアルファベット
さらに読む:
• Base64とは何か、どのように動作するのか?
• URLセーフ vs 標準Base64 — 全貌
• UTF-8とUnicodeのためのBase64