ChaCha20-Poly1305 Nonce 重複検証ツール | AEAD の nonce 再利用を一括チェック
ChaCha20-Poly1305 (12 バイト nonce) と XChaCha20-Poly1305 (24 バイト nonce) の使用済み nonce 一覧を貼り付けると、重複・長さ不正・誕生日衝突確率を 1 画面で表示。同じ鍵での nonce 再利用という AEAD の致命傷を、ログから抽出した実データで監査するための専用ツール。
💡 このツールについて
ChaCha20-Poly1305 や XChaCha20-Poly1305 のような AEAD 暗号では、nonce (number used once) の名前が示すとおり、同じ鍵で同じ nonce を二度使ってはいけない。これを破ると ChaCha20 のキーストリームが両メッセージの XOR として漏れ、さらに Poly1305 の一回限り認証鍵が露出して、攻撃者が任意のメッセージを偽造できるようになる。理論ではなく、実装ミスで繰り返し起きてきた事故。
問題は、nonce 再利用がコードレビューでは見えにくい点にある。乱数生成・カウンタ・タイムスタンプ由来など実装ごとに生成方法が違い、複数インスタンスやコンテナ再起動をまたぐと「同じ鍵 × 同じ nonce」が紛れ込む。本ツールはログや監査データから抽出した nonce 一覧を貼るだけで、重複している値を具体的に列挙し、12 バイト / 24 バイトという期待長から外れたエントリも別カウントで報告する。
加えて、乱数 nonce 運用を前提とした誕生日境界を計算する。P(衝突) ≈ q² / 2ⁿ⁺¹ という近似で、現在の入力件数に対する衝突確率と、衝突確率が 2⁻³² / 2⁻⁶⁴ を下回る安全件数の上限を示す。96 ビット nonce では乱数生成でも 2³² メッセージ付近で無視できない衝突確率に達するため、ステートレスな送信側では 192 ビットの XChaCha20 が推奨される — その差が件数として一目で分かる。
🧐 よくある質問
Q. nonce は秘密情報ですか? 貼り付けても大丈夫? nonce は AEAD の設計上、暗号文と一緒に平文で送られる公開値で、鍵そのものではない。とはいえ運用ログ由来のデータなので、本ツールは入力をブラウザ内だけで処理し、外部に送信しない。タブを閉じれば貼り付けたデータは残らない。
Q. ChaCha20-Poly1305 と XChaCha20-Poly1305 の違いは? nonce のサイズが違う。RFC 8439 の ChaCha20-Poly1305 は 96 ビット (12 バイト)、XChaCha20-Poly1305 は HChaCha20 で導出した拡張版で 192 ビット (24 バイト)。192 ビットあれば乱数生成でも実質的に衝突しないため、カウンタを持てないステートレスな送信側に向く。
Q. 「長さ不正」と判定されるのはどんなとき? 選択した方式の期待長 (ChaCha20 なら 24 桁 hex、XChaCha20 なら 48 桁 hex) と桁数が一致しない、または 16 進以外の文字が含まれる場合。AEAD 実装はこうした nonce をそもそも受け付けないため、抽出やパースのバグを示している可能性が高い。
Q. 0x プレフィックスやコロン区切りのままでも貼れますか?
貼れる。先頭の 0x、コロン、空白、ハイフンは自動で除去し、大文字小文字も区別せず比較する。ログのフォーマットをそのまま貼って構わない。
Q. 誕生日境界の安全件数は何を意味しますか? 乱数で nonce を生成した場合に、衝突確率を指定値以下に抑えられる最大メッセージ数。例えば 96 ビットで 2⁻³² 安全件数は約 2³² 件。これを超えて同じ鍵を使い続けると、乱数でも nonce 衝突のリスクが看過できなくなる、という鍵ローテーションの目安。
Q. カウンタ運用 (シーケンシャル nonce) でも使えますか? 重複検出と長さ検証はそのまま使える。ただし誕生日境界は乱数生成を前提とした近似なので、厳密なカウンタ運用では衝突確率の欄は参考値として扱う。重複が 0 であることの確認が主目的になる。
📚 豆知識
nonce 再利用の事故で広く知られるのは、複数の TLS 実装や独自プロトコルで報告された GCM の nonce 衝突問題で、ChaCha20-Poly1305 も同じ AEAD の枠組みである以上、同じ落とし穴を共有する。だからこそ Google は QUIC で ChaCha20-Poly1305 を採用する際、nonce を厳密にカウンタ管理する設計にした。
XChaCha20 の「X」は extended の頭文字で、内部で HChaCha20 という鍵導出を一段かませて 192 ビット nonce を扱えるようにしている。libsodium が早くから採用したことで、乱数 nonce で安全に使える AEAD として実務に広まった。96 ビットでカウンタ管理に悩むより、192 ビットで乱数を投げる方が運用がシンプル、というのが普及の背景。