Base64解説:6ビットグループ化、約33%サイズ膨張、パディング、base64urlと標準の違い

Base64とは何か——そして何ではないか

Base64はバイナリからテキストへの変換エンコーディング方式です。任意のバイナリデータを印刷可能なASCII文字の文字列に変換し、人間が読めるテキスト向けに設計されたコンテキストに安全に埋め込めるようにします。Base64は圧縮ではありません——データをより大きくします。暗号化でもありません——エンコードされた文字列を持つ誰もが元のバイトを簡単に復元できます。名前は正確に64文字のアルファベットを使用することに由来しており、2⁶ = 64により各文字が入力の正確に6ビットを表すことができます。

Base64は独立した標準として発明されたのではありません。7ビットASCIIのみを確実に伝送するSMTPインフラストラクチャ上でバイナリメール添付ファイルを送信する必要性から生まれました。MIMEを定義するRFC 2045(1996年)がメール用のエンコーディングを標準化しました。10年後、RFC 4648(2006年)がbase64とその変種——base32とbase64urlを含む——を単一の参照文書に統合しました。RFC 4648は現在でも、バイナリからテキストへのエンコーディングが必要な新しいプロトコルで使用されている権威ある仕様です。

6ビットのグループ化:3つの入力バイトが4文字になる方法

Base64の核心は単純なビット再パッキング操作です。バイナリデータは8ビットのバイトのグループとして到着します。base64はこれらのビットを6ビットのチャンクに再グループ化し、それぞれが64文字のアルファベットの1文字にマッピングされます。6と8の最小公倍数は24なので、自然な処理単位は3バイト = 24ビット → 4文字(4 × 6ビット)です。Manを具体的な例として取り上げます:3つのバイトは0x4D0x610x6Eで、ビット列01001101 01100001 01101110となります。4つの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倍)なります。1KBのファイルは約1.37KBにエンコードされ、1MBの画像は約1.37MBにエンコードされます。

アルファベット:A–Z、a–z、0–9、+、/

標準のbase64アルファベットは、6ビット値0–63を次の順序で印刷可能なASCII文字にマッピングします:値0–25は大文字AZに、値26–51は小文字azに、値52–61は数字09に、値62は+に、値63は/にマッピングされます。この順序はMIME互換性に根ざした歴史的な理由から、数字より前に文字を配置します——これはASCIIの数値順序とは逆です。最後の2つの値に+/を選択したことは、URLで特別な意味を持つため、数十年にわたる相互運用性の問題を引き起こしました。

一般的な誤解として、base64は文字セットに依存しないというものがあります。そうではありません:アルファベットは固定ASCIIです。65文字セット(64のデータ文字+パディング用の=)の外の文字に出会ったデコーダーは、仕様のコンテキストに応じて入力を拒否するかスキップする必要があります。RFC 4648は厳格モードでアルファベット外の文字を拒否することを推奨しています。等号=はデータ文字ではなくセンチネルです——パディングをマークし、エンコードされた文字列の最後以外には絶対に現れてはなりません。

パディング:等号が存在する理由と省略できる場合

エンコーディングは3バイトずつ処理するため、長さが3で割り切れない入力は最後に部分的なグループを残します。パディングはこの問題を解決します:エンコードされた出力が常に4文字の倍数になるよう強制し、出力長だけから元のバイト数を計算できるようにします。入力に1つの余りバイトがある場合、2つのパディング文字==が追加されます。入力に2つの余りバイトがある場合、1つのパディング文字=が追加されます。

パディングは他の手段で全長がわかっているコンテキストでは任意です。JSON Web Signature仕様のRFC 7515は、JWTのドットが既にセグメントを区切っているため、JWTコンポーネントをエンコードする際に実装が=パディングを省略することを明示的に要求しています。したがって、JWTのbase64urlエンコードされた値は決して=で終わりません。パディングの復元は簡単です:文字列長が4の倍数になるまで=文字を追加します。

Base64url:JWTとOAuthトークンで使用されるURL安全な変種

標準のbase64の+/はURLコンテキストで問題があります。クエリ文字列の+application/x-www-form-urlencodedエンコーディングではスペースとして解釈されます。/はパスセグメントの区切り文字です。RFC 4648セクション5で定義されたBase64url+-に、/_に置き換えます。この2つの文字はパーセントエンコーディングなしでURLで安全に使用できます。パディング=もbase64urlコンテキストでは通常省略されます。

Base64urlはコンパクトでURL安全なバイナリ表現が必要な場所で使用されます:JWTのヘッダーとペイロードセクションはbase64urlエンコードされたJSONです。OAuth 2.0認証コードはしばしばbase64urlエンコードされたランダムバイトです。PKCE(RFC 7636)のコードベリファイアとチャレンジもbase64urlを使用します。データ膨張率は標準のbase64と同じです——正確に4/3——アルファベットのみが異なり、ビットグループ化アルゴリズムは同じです。

実際のサイズへの影響とbase64とバイナリの選択方法

約33%のオーバーヘッドがbase64の主な実際的コストです。データURI——data:image/png;base64,...でHTML/CSSに直接画像、フォント、SVGを埋め込む——のトレードオフは、ドキュメントが大きくなる代わりにHTTPのラウンドトリップを1回省略することです。これは小さなリソース(通常4–8 KB未満)に有益です:節約されたラウンドトリップがサイズ増加を上回り、特に高遅延接続でそれが顕著です。大きなリソースでは、HTMLドキュメントが大きくなると解析に時間がかかり、レンダリングをブロックし、ページとは別にキャッシュできないため、サイズ増加はパフォーマンスを低下させます。

HTTP基本認証はAuthorization: Basic ...ヘッダーでbase64(ユーザー名:パスワード)として認証情報をエンコードします。これはセキュリティ対策ではありません——ユーザー名とパスワードはデコードによって簡単に復元できます。基本認証はセキュリティのためにHTTPSが必要です。base64エンコーディングはHTTPヘッダー仕様が印刷可能なASCIIを要求するためだけに存在します。ペイロードに機密情報が含まれる場合、base64は暗号化の代替にはなりません。機密データには認証付き暗号化(例:AES-GCM)またはJSON Web Encryption(JWE、RFC 7516)を使用してください。