Base16 エンコーダーの使い方
- 入力欄にテキストを入力するか貼り付けます。入力に合わせて Base16 が出力欄に表示されます。
- 入力欄の下の文字コードで、文字をどのバイトにするかを決めます。デフォルトは UTF-8 です。
- デコードするには、ツールの上の Base16(RFC 4648)→ テキストをクリックするか、⇄ 入れ替えボタンを押します。後者は現在の出力を入力欄に移します。入力中の小文字、空白、コロンも受け付けます。
- 結果は出力をコピーするかダウンロードします。変換元と変換先のメニューで Base32 や Base64 などの形式に切り替えて比較することもできます。
区切り文字、0x 接頭辞、小文字出力のある 16進数が必要なら、テキストを 16進数ににそのオプションがあります。
Base16 と RFC 4648
RFC 4648 は Base64、Base32、Base16 を並べて定義しており、中でも Base16 は 3 つのうち最も単純で、パディングも改行もビットの組み替えも必要ありません。各バイトを 4 ビットずつ 2 つに分け、それぞれを 1 文字に対応させるだけです。RFC 自身のテストベクターは次のとおりです。
| 入力 | Base16 |
|---|---|
| (空) | (空) |
f | 66 |
fo | 666F |
foo | 666F6F |
foob | 666F6F62 |
fooba | 666F6F6261 |
foobar | 666F6F626172 |
出力の長さは常にバイト数のちょうど 2 倍なので、Base16 にはパディング文字が要りません。Base64 と Base32 は 1 つのブロックに複数のバイトをまとめるため、最後のブロックを = で埋める必要があります。それぞれのエンコーディングがどこで規定されているかは RFC の概要にまとめています。
Base16、Base32、Base64 の比較
Hello, world の 12 バイトを RFC 4648 の各エンコーディングで表すと次のようになります。
| エンコーディング | 出力 | 長さ |
|---|---|---|
| Base16 | 48656C6C6F2C20776F726C64 | 24 |
| Base32 | JBSWY3DPFQQHO33SNRSA==== | 24(パディングなしで 20) |
| Base64 | SGVsbG8sIHdvcmxk | 16 |
Base16 はサイズと引き換えにわかりやすさを取っています。バイトをそのまま読み取って値を 1 桁ずつ比較できるうえ、大文字小文字を区別しないものも含めて、英字と数字を扱えるどんなシステムでも壊れません。Base64 は 3 分の 1 短く、バイト列を JSON、メール、URL の中で運ぶときの標準です。Base58 や Base85 を含めた比較はエンコーディングの比較で扱っています。
Base16 を見かける場所
- ハッシュのダイジェストやチェックサム。
sha256sumなどのツールでは通常小文字で表示されます。 - OpenPGP の鍵のフィンガープリント。GnuPG は 4 桁ずつ区切った大文字の 16進数で表示します。
- RFC やその他の仕様のテストベクター。長さよりもバイト値が曖昧でないことが重要な場面です。
- 大文字小文字を区別しない、あるいは英数字だけのデータが必要なプロトコルや形式。
API が Base64 で求めるダイジェストなど、そうした値を Base64 に移すには 16進数を Base64 にを、逆方向には Base64 を 16進数にを使ってください。
コードでの Base16
import base64
base64.b16encode(b"Hello").decode() # '48656C6C6F'
base64.b16decode("48656c6c6f", casefold=True) # b'Hello'
printf 'Hello' | basenc --base16 # 48656C6C6F
echo 48656C6C6F | basenc --base16 -d # Hello
basenc は GNU coreutils 8.31 以降に含まれています。Node.js では Buffer.from("Hello").toString("hex").toUpperCase() で同じ結果が得られます。これらのモジュールの Base64 側については Python と Bash のページで扱っています。
よくある質問
Base16 は 16進数と同じですか?
バイト列については同じです。Base16 は RFC 4648 が 16進数エンコーディングに付けた名前で、各バイトが 0123456789ABCDEF の 2 文字になります。RFC は大文字を指定していますが、普段使う 16進数は小文字であることも多いです。
Base16 は元のデータよりどれくらい大きくなりますか?
ちょうど 2 倍、つまり 100% の増加です。Base32 は 60%、Base64 は約 33% なので、Base16 は RFC 4648 のエンコーディングの中で最もコンパクトでなく、最も読みやすい方式です。
Python の b16decode が文字列を拒否するのはなぜですか?
base64.b16decode はデフォルトでは大文字しか受け付けません。小文字の入力には casefold=True を渡すか、大文字小文字と空白の両方を受け付ける bytes.fromhex() を使ってください。