比較表
ここで扱うエンコーディングはどれも、任意のバイト列を印字可能なテキストに変換し、損失なく元に戻せます。違うのは使う文字の数と種類、そして出力がどれだけ大きくなるかです。
| エンコーディング | アルファベット | 出力サイズ | 大文字小文字の区別 | URLセーフ | 主な用途 |
|---|---|---|---|---|---|
| 16進数(Base16) | 0-9 a-f | 200% | なし | はい | ハッシュ、MAC アドレス、バイトダンプ、カラーコード |
| Base32(RFC 4648) | A-Z 2-7、パディング = | 160% | なし(仕様上は大文字) | = がなければ可 | TOTP のシークレット、Tor の onion アドレス、DNSSEC(base32hex) |
| Base58(Bitcoin) | 1-9 A-Z a-z から 0 O I l を除く | 約 137% | あり | はい | Bitcoin アドレス、IPFS CIDv0(Qm…)、Solana の鍵 |
| Base64 | A-Z a-z 0-9 + /、パディング = | 133% | あり | いいえ | メールの添付ファイル、Data URI、PEM、JSON のペイロード |
| Base64URL | A-Z a-z 0-9 - _ | 133% | あり | はい | JWT、URL トークン、ファイル名 |
| Ascii85 | ! から u と z | 125% | あり | いいえ | PDF や PostScript のストリーム |
| Z85 | .-:+=^!/*?&<>()[]{}@%$# を含む 85 文字 | 125% | あり | いいえ | ZeroMQ の CURVE 鍵 |
| Base45(RFC 9285) | 0-9 A-Z、空白、$%*+-./: | 150% | なし(大文字のみ) | いいえ | QR コード、EU デジタル COVID 証明書 |
「出力サイズ」は、大きな入力に対するエンコード後の長さを入力の長さとの比で示したものです。Base64 は 3 バイトにつき 4 文字、Base32 は 5 バイトにつき 8 文字、Base85 は 4 バイトにつき 5 文字、Base45 は 2 バイトにつき 3 文字が必要です。Base58 には固定のブロックサイズがないため、比率は log(256) / log(58)、約 1.366 になります。特定の入力に対する正確な数値は、サイズ計算ツールですべて一度に確認できます。
同じ入力を各方式でエンコード
12 バイトの ASCII 文字列 Hello world! を 9 通りにエンコードした結果です。12 バイトは 3 でも 4 でも割り切れるので、Base64 と Base85 の各バリアントにパディングは不要です。
| エンコーディング | 出力 | 長さ |
|---|---|---|
| 16進数 | 48656c6c6f20776f726c6421 | 24 |
| Base32 | JBSWY3DPEB3W64TMMQQQ==== | 24(パディングなしで 20) |
| Base32hex | 91IMOR3F41RMUSJCCGGG==== | 24 |
| Base58(Bitcoin のアルファベット) | 2NEpo7TZRhna7vSvL | 17 |
| Base64 | SGVsbG8gd29ybGQh | 16 |
| Base45 | %69 VD82EK4F.KESTC | 18 |
| Ascii85 | 87cURD]j7BEbo80 | 15 |
| Z85 | nm=QNzY<mxA+]nf | 15 |
| Base85(RFC 1924 / git) | NM&qnZy<MXa%^NF | 15 |
この例では出力に + も / も含まれないので、Base64URL は Base64 と同じになります。違いが出るのは特定のバイトだけで、たとえば fb ef be は Base64 では ++++、Base64URL では ---- です。
表のほとんどは Python の標準ライブラリでまかなえます。z85encode は Python 3.13 で追加されました。
import base64
data = b"Hello world!"
print(data.hex()) # 48656c6c6f20776f726c6421
print(base64.b32encode(data).decode()) # JBSWY3DPEB3W64TMMQQQ====
print(base64.b64encode(data).decode()) # SGVsbG8gd29ybGQh
print(base64.a85encode(data).decode()) # 87cURD]j7BEbo80
print(base64.b85encode(data).decode()) # NM&qnZy<MXa%^NF
print(base64.z85encode(data).decode()) # nm=QNzY<mxA+]nf
Base58 は標準ライブラリにありませんが、1 つの大きな整数の基数変換にすぎないので、数行で書けます。
B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
def b58encode(data: bytes) -> str:
n = int.from_bytes(data, "big")
out = ""
while n:
n, r = divmod(n, 58)
out = B58[r] + out
zeros = len(data) - len(data.lstrip(b"\0"))
return "1" * zeros + out
print(b58encode(b"Hello world!")) # 2NEpo7TZRhna7vSvL
print(b58encode(b"\0\0\x01")) # 112
先頭のゼロバイトは 1 つずつ文字どおりの 1 になります。大きな整数には先頭のゼロを覚えておく方法がないからです。バージョンバイトがゼロで始まる従来型の Bitcoin アドレスが、すべて 1 で始まるのはこのためです。
各エンコーディングの用途
16進数
16進数は 1 バイトに 2 文字を使うため、ここで挙げた中で最も大きくなりますが、最も読みやすい方式です。1 文字がちょうど 4 ビットに対応するので、オフセット n のバイトは必ず 2n 文字目と 2n+1 文字目にあります。ハッシュ、チェックサム、デバッグ用のダンプがほぼ必ず 16進数なのはこの性質のためです。デコーダーは DEADBEEF と deadbeef のどちらも受け付けます。変換には Base64 から 16進数へと 16進数から Base64 へを使ってください。
Base32
Base32 は大文字と 2〜7 の数字だけを使います。大文字小文字を区別しない環境(DNS 名、一部のファイルシステム、スマートフォンにコードを手入力する人)でも壊れず、O、I、B と見間違えやすい 0、1、8 も避けています。認証アプリは TOTP のシークレットを Base32 で保存し、Tor v3 の onion アドレスは 56 文字の小文字 Base32 です。RFC 4648 は、元のバイト列の並び順を保つ base32hex(0-9 A-V)も定義しています。Base32 エンコーダーでお試しください。
Base58
Base58 は Bitcoin から始まりました。紛らわしい 0、O、I、l と、ダブルクリックでの選択や URL を壊す + と / を取り除いています。Bitcoin アドレスはさらにバージョンバイトと 4 バイトのチェックサムを加えた Base58Check という形式です。IPFS CIDv0 のハッシュも Base58 で、マルチハッシュのバイト 12 20 で始まるため、必ず Qm から始まります。入力全体を 1 つの数として扱うので、変換時間は長さの 2 乗で増えます。そのため Base58 は鍵やハッシュのような短い値に使われます。Base58 エンコーダーでお試しください。
Ascii85、Z85、git の Base85
Base85 ファミリーは 4 バイトを 5 文字に詰め込み、広く対応しているエンコーディングの中では最も高密度です。難点はアルファベットで、85 個の印字可能文字を使う以上、バリアントによっては引用符、バックスラッシュ、<、>、& が含まれます。
- Ascii85(Adobe)は
!からuまでを使い、出力を<~と~>で囲み、4 つのゼロバイトを 1 文字のzで表します。PostScript と PDF(ASCII85Decodeフィルター)で使われています。 - Z85(ZeroMQ)は、C や JSON の文字列リテラル内でも安全な文字を選んでおり、引用符やバックスラッシュを含みません。入力の長さは 4 の倍数である必要があります。32 バイトの CURVE 鍵は 40 文字になります。
- RFC 1924 の Base85 は、IPv6 アドレス用のエイプリルフールの提案でした。そのアルファベットは git のバイナリパッチと Python の
b85encodeに残っています。
Base85 ツールは 3 つすべてに対応しており、Z85 には専用のページがあります。
Base45
Base45 は QR コードのために作られました。QR コードの英数字モードは、ちょうど 45 種類の文字(数字、大文字、空白、$%*+-./:)を 1 文字あたり 5.5 ビットで格納しますが、バイトモードでは 1 文字 8 ビットです。Base45 は 2 バイトをこの文字 3 つに変換するので、QR コード内での増加は約 3% で済みます。Base64 のテキストはバイトモードを使うしかなく、33% 増えます。EU デジタル COVID 証明書が Base45 を採用したのはまさにこの理由です。Base45 エンコーダーでお試しください。
選び方
受け取る側が期待するエンコーディングを選んでください。JWT のライブラリなら Base64URL、認証アプリなら Base32、Bitcoin のウォレットなら Base58Check です。両端を自分で管理できる場合は、次の目安が使えます。
- JSON、XML、メール、HTTP のボディに入れるバイト列: Base64。どの言語にも高速な組み込み実装があり、33% の増加は許容範囲です。
- URL、Cookie、ファイル名の中: パディングなしの Base64URL。
- 人が値を読んだり、入力したり、見比べたりする: 短いハッシュなら 16進数、大文字小文字が失われうるなら Base32、コンパクトで紛らわしい文字のない見た目にしたいなら Base58。
- 1 バイトでも削りたく、デコーダーも自分で管理できる: Z85 か Ascii85。
- QR コード: Base45。
トレードオフは常に同じです。アルファベットが大きいほど出力は短くなり、どこかでエスケープが必要になる文字が増えます。Base64 が 3 分の 1 大きくなる理由は Base64 のサイズ増加を、URLセーフなバリアントについては Base64 と Base64URL の違いをご覧ください。
よくある質問
最もコンパクトなバイナリ・テキスト変換はどれですか?
一般的なものでは、増加率 25% の Base85(Ascii85 と Z85)、次いで 33% の Base64 です。basE91 はわずかに上回りますが、対応している環境はまれです。必要なら Base91 ツールをご覧ください。
Bitcoin が Base64 ではなく Base58 を使うのはなぜですか?
Base58 は 0、O、I、l、+、/ を除いているので、アドレスを読み上げたり、手で書き写したり、テキスト欄でダブルクリックして選択したりしやすくなります。代償は多倍長整数の変換が遅いことですが、25 バイトのアドレスでは問題になりません。
Base32 や Base58 で大文字と小文字は区別されますか?
RFC 4648 のアルファベットは大文字で、厳格なデコーダーは小文字を拒否します。両方を受け付けるものも多く、Python では casefold=True が必要です。Base58 は大文字と小文字を区別し、a と A は別の数字です。16進数は、ほぼすべてのデコーダーで大文字小文字を区別しません。
Base64 を Base58 や Base32 に直接変換できますか?
はい。いったんバイト列にデコードしてから、もう一度エンコードします。Base64 から Base58 へと Base64 から Base32 への変換ツールは、この 2 段階をブラウザ内で行います。