16進エンコードの仕組み
ページ上のすべての文字は1つ以上のバイトとして格納されています。16進エンコードはそれらのバイトをbase16で書き直し、1バイトあたり2文字で表現することで、特別なツールなしにバイトストリームを読み取れるようにします。
- テキストをバイトにエンコードする. UTF-8モードでは
new TextEncoder().encode(text)で入力を処理し、バイト値のUint8Arrayを返します。Latin-1モードではcharCodeAt(0) & 0xFFで各コードユニットの下位8ビットを取得します。これはレガシーなISO-8859-1コーデックが行う変換と同一です。 - 各バイトを2桁の16進数で表現する. 各バイトは
byte.toString(16).padStart(2, "0")で2桁の16進数に変換されます。大文字・小文字トグルにより、出力文字を大文字(A-F)または小文字(a-f)で表示します。 - グループ化とプレフィックスを適用する. グループ化はバイト間にセパレーターを挿入します。スペース1つ、ダッシュ、または4バイトごとのスペースを選択できます。0xプレフィックスは文字列全体に1つ付加(グループ化なし)またはバイトごとに付加(スペースグループ化)でき、C配列やバイナリdiffツールの表記規則に合わせられます。
- 逆方向にデコードする. 16進数 → テキストモードは入力からスペース・ダッシュ・
0xプレフィックスをすべて取り除き、残った文字を/^[0-9a-fA-F]+$/で検証し、奇数長の文字列を拒否してから、連続するバイトペアからUint8Arrayを再構築します。UTF-8モードはnew TextDecoder("utf-8", { fatal: true })で配列をデコードし、Latin-1モードは各バイトをString.fromCharCode(b)でマッピングします。 - 高速反復のためのライブモード. ライブモードはデフォルトでオンです。キーストロークごとに150ミリ秒のデバウンスで再変換がスケジュールされ、貼り付けや編集をしながら変換ボタンを押さずに反対側のペインが更新されます。
16進変換ツールを使う理由
- バイナリプロトコルのデバッグ. ModbusやDNP3、CoAPのようなワイヤフォーマットは特定のバイトオフセットにヘッダーを詰め込んでいます。キャプチャしたフレームを16進数で読むと各フィールドが一目でわかり、同じバイトをASCIIに変換するとバイナリフレーミングの中に隠れているプレーンテキストのペイロードが明らかになります。
- 組み込みファームウェアの解析. JTAGやSWDプローブはメモリ内容を16進数で報告します。メモリ領域をASCIIに変換すると、ファームウェア内のどこを参照しているかを示す埋め込み文字列(ファイルパス、エラーメッセージ、ベンダー署名)が見つかります。
- パケットキャプチャの読み取り. Wiresharkとtcpdumpはどちらもバイトペインを持ち、各パケットを左側に16進数、右側にASCIIで表示します。バグレポートやチャットログから16進ブロブをコピーしてここで変換すると、キャプチャツールに再インポートせずにバイトの内容を読み取れます。
- バイトレベルのdiff. 2つのバイナリファイルを比較する際は、どのバイトが変化したかを特定することが重要です。両方を一貫したグループ化で16進数に変換すると、テキストエディターでdiffを揃えられ、組み込みdiffツールで変更されたバイトをハイライト表示できます。
主な用途
Hex ↔ ASCII 変換は、バイトストリームが単なるテキストペイロード以上の意味を持つリバースエンジニアリング・セキュリティ・組み込み作業で広く使われます。
- リバースエンジニアリング:strings耐性バイナリからhexダンプを取り出し、印字可能なASCIIとしてデコードできる連続部分を探し、逆アセンブリ内での位置を特定するアンカーとして利用します。
- ネットワークフォレンジクス:Wiresharkから単一パケットのペイロードを16進数でコピーし、ここに貼り付けて、キャプチャ全体をエクスポートせずにアプリケーション層のテキストを読み取ります。
- 暗号マテリアルの処理:鍵・IV・HMACタグは16進文字列として渡されることが多いです。バイトにデコードして長さがアルゴリズムと一致するか(AES-128なら16バイト、AES-256なら32バイト)を確認してからコンフィグに組み込みます。
変換の実例
「テキスト → 16進数」、UTF-8、小文字、「1バイトごとにスペース」グループ化、プレフィックスなしを選択します。Hiと入力すると出力は48 69になります。プレフィックスをオンにしてグループ化を「なし」にすると同じ入力が0x4869と表示されます。絵文字😀を入力するとUTF-8モードではf0 9f 98 80と表示されます。1つのコードポイントに4バイト使われているため、絵文字は転送サイズが膨らみやすいことがわかります。「16進数 → テキスト」に切り替えて0x48-65-6C 6C 6Fを貼り付けると、パーサーがプレフィックス・ダッシュ・スペースを取り除いてHelloを復元します。
FAQ
16進エンコードとは何ですか?
16進エンコード(hexadecimalエンコード)はバイトストリームをbase16で書き、1バイトあたり2つのASCII文字で表現します。1桁の16進数は4ビットをカバーするため、2桁で8ビット1バイトをカバーします。アルファベットは0-9に続きA-F(またはa-f)で、大文字・小文字は表示の選択にすぎず、デコーダーはどちらも受け付けます。16進数はプロトコル仕様・デバッガ出力・暗号鍵に生のバイトを記述する標準的な方法です。バイナリより2倍コンパクトで、テキスト中の生バイトが引き起こす非印字文字の問題を回避できます。
絵文字が16進数で4バイトになるのはなぜですか?
UTF-8は可変長エンコードです。ASCIIキャラクター(U+0000〜U+007F)は1バイト、Latin-1補完は2バイト、BMPの大部分のコードポイントは3バイト、U+FFFFを超える文字(ほとんどの絵文字を含む)は4バイトを使います。スマイリーフェイス😀はU+1F600で、F0 9F 98 80にエンコードされます。固定幅のバイトビューが必要な場合はLatin-1に切り替えてください。ただしLatin-1は最初の256コードポイントのみをカバーするため、その範囲外の文字はラウンドトリップできません。
Latin-1 / ISO-8859-1をサポートしていますか?
はい。テキストエンコードオプションでLatin-1 (ISO-8859-1)に切り替えてください。エンコード時は各JavaScriptコードユニットの下位8ビット(charCodeAt(0) & 0xFF)を取得します。これはレガシーな1バイトマッピングと一致します。デコード時は各バイトにString.fromCharCode(byte)を使います。各バイトがちょうど1文字に対応する古いWindows-1252またはUnicode以前のシステムからの出力を扱う場合にLatin-1を使用してください。
変換はブラウザ内で行われますか?
はい。変換ツールはTextEncoder、TextDecoder、小さなパーサーを1つの静的ページとして実行します。アップロードも、APIコールも、貼り付けた内容の解析もありません。サイト全体で共有される標準的なページロードメトリクスのみです。ここに表示される16進バイトは、同じ入力に対してNodeスクリプトやLambda関数が生成するものと同一です。
Hex ↔ ASCII 変換は、バイナリプロトコルや組み込みファームウェアを読む作業で1日に何度も発生する小さな作業です。NodeやV8がすでに搭載しているネイティブエンコーダーを使ってブラウザタブ内で実行することで、作業を素早く、バイトストリームを手元に保つことができます。