Base64 vs 16進数エンコード
Base64と16進数(hex)エンコードを比較。サイズの違い、可読性のトレードオフ、それぞれのエンコード形式を使うべき場面を詳しく解説します。
Concept
詳細な説明
Base64と16進数は、どちらもバイナリデータを印刷可能なテキストとして表現する方法ですが、効率性、可読性、一般的な用途で大きく異なります。
1バイトをエンコードした場合のサイズ比較:
- 元のデータ:1バイト(8ビット)
- 16進数:2文字(各16進数字は4ビットを表現)
- Base64:約1.33文字(各Base64文字は6ビットを表現)
100バイトをエンコードした具体例:
- 16進数:200文字(2倍に膨張)
- Base64:136文字(パディング込みで約1.33倍に膨張)
つまり、同じデータに対してBase64は16進数より約33%コンパクトです。埋め込み画像やファイル添付のような大きなペイロードでは、この差は無視できません。
可読性:
短い値では16進数の方が人間にとって読みやすいです。48656C6C6F のような16進文字列は、文字ごとに頭の中でデコードできます(0x48 = H, 0x65 = e など)。SGVsbG8= のようなBase64文字列はデコードしない限り意味不明です。
16進数はバイトレベルでの操作も容易です。16進文字2つが正確に1バイトに対応するため、個々のバイトの検査、ハッシュの比較、ファイルシグネチャ(マジックバイト)の識別が簡単です。
16進数を使うべきケース:
- ハッシュ値(MD5、SHA-256)の表示。慣習として16進数が使われます。
- 生のバイト、メモリアドレス、パケット内容を示すデバッグ出力
- CSSのカラーコード(
#FF5733) - コンパクトさより可読性が重要な短い識別子
Base64を使うべきケース:
- テキストベースプロトコル(JSON、XML、メール)でのバイナリデータ転送
- HTML/CSSへのファイル埋め込み(data URI)
- API認証トークンや資格情報
- エンコード後のサイズを最小限にしたい場面
JavaScriptでのエンコード比較:
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
// Hex
const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
// "48656c6c6f"
// Base64
const base64 = btoa(String.fromCharCode(...bytes));
// "SGVsbG8="
どちらも暗号化ではありません。 どちらも簡単に元に戻すことができ、セキュリティは一切提供しません。エンコーディング形式であり、暗号操作ではないのです。
ユースケース
設定ファイルにバイナリの暗号鍵を格納する際に16進数とBase64のどちらを使うか選ぶ場面で、フットプリントが小さいBase64が好まれます。