こんにちは。セキュリティの最前線で泥臭いインシデントと戦い続けているエンジニアです。
今日は、暗号化の現場で「やってはいけない禁忌」の中でも、特にやってしまうと「一瞬でセキュリティが崩壊する」と言われる、AES-GCMのNonce(ノンス)再利用についてお話しします。
「暗号化してるから大丈夫でしょ?」と思っているそこのあなた。その油断が一番危ないんです。一緒に紐解いていきましょう。
—
1. AES-GCMと「使い捨ての鍵」の物語
AES-GCMは、現代のWeb通信(TLSなど)で最も信頼されている暗号化方式の一つです。「データを隠す(暗号化)」ことと、「データが改ざんされていないか確認する(認証)」という2つの役割を同時にこなす、非常に優秀なやつです。
ここで登場するのが「Nonce(ノンス)」です。
これを「家の鍵」に例えてみましょう。
鍵の管理、どうしていますか?
あなたは、毎日同じ鍵を使い回していますよね。でも、もしその鍵が「一度きりしか使えない特殊な鍵」だったらどうでしょう?
- Nonce(Number used onceの略): その名の通り「一度だけ使われる数字」です。
- AES-GCMのルール: 「同じ鍵(共通鍵)と、同じNonceの組み合わせで、二度とデータを暗号化してはいけない」という絶対的な掟があります。
もし、同じNonceで二つの異なるメッセージを暗号化してしまうと、泥棒(攻撃者)に「暗号の仕組みそのもの」を解読されてしまうのです。
—
2. なぜNonceを再利用すると「即死」するのか?
少しだけ裏側の話をしますね。AES-GCMの仕組みは、実は「暗号化したデータ」と「ハッシュ値のような認証タグ」を組み合わせて作られています。
同じNonceを使って二つのデータを暗号化すると、数学的な演算(XORという処理)を通じて、「認証タグを偽造するための鍵(GHASH鍵)」が丸裸になってしまいます。
これを家に例えると、こんな状態です。
1. Nonce再利用: 玄関の鍵を閉める際、いつも同じ「封印のシール」を貼っていた。
2. 泥棒の侵入: 泥棒は、そのシールの「剥がし方」を学習してしまう。
3. 結末: 泥棒は、他の家(通信)でも同じシールを使っているのを見れば、簡単に封印を破って中身をすり替え、持ち主には「何も異常はない」と偽装する。
つまり、攻撃者は通信の中身を盗み見るだけでなく、データを改ざんして送信元になりすますことさえ可能になります。これがNonce再利用の恐ろしさです。
—
3. 実装でやってはいけないこと、やるべきこと
開発現場でよくあるミスは、「毎回適当な値をNonceにしている」あるいは「Nonceをカウンタとして管理せず、乱数で重複させてしまう」ことです。
悪い例:Nonceを固定してしまっている
// !!絶対にやってはいけない例!!
// 固定値や、予測可能な値を使うと、攻撃者は即座に暗号を解読します
$key = '秘密の鍵';
$nonce = '12345'; // 毎回同じ固定値!
$data = '秘密のメッセージ';
$encrypted = openssl_encrypt($data, 'aes-256-gcm', $key, 0, $nonce, $tag);
良い例:Nonceを適切に管理する
実務では、random_bytesを使って毎回異なる値を生成するか、カウンタを適切にインクリメントする必要があります。
// 推奨される実装例
$key = random_bytes(32); // 256bitの鍵を生成
$nonce = random_bytes(12); // GCMで推奨される12バイト(96ビット)のNonce
$data = '大切なデータ';
// 暗号化を実行
$encrypted = openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $tag);
// $nonce と $tag は、復号する側にも必要なので一緒に保存・送付します
// 復号時には必ず「保存したその時のNonce」を使うこと!
—
4. エンジニアとして心がけたい「防御の心得」
現場でインシデントハンドリングをしていて感じるのは、多くの事故が「ライブラリの仕様を深く理解せずに、コピペで実装したこと」から生まれているということです。
- Nonceは使い捨て: プログラム内でカウンタを回すか、暗号論的に安全な乱数生成器(
random_bytesなど)を使用してください。 - Nonceを再利用しない設計: もしNonceが重複する可能性が少しでもあるなら、その設計自体を見直すべきです。
- ライブラリを信じすぎない:
opensslなどの標準ライブラリを使う際も、パラメータの役割を公式ドキュメントで確認する癖をつけましょう。
最後に
セキュリティは「完璧な門」を作ることではなく、「泥棒が嫌がる仕組み」を地道に積み上げることです。
Nonceの再利用は、その門の鍵を自分から泥棒に渡すようなものです。「面倒くさいな」と感じるその一手間が、あなたのユーザーのデータと、あなた自身のエンジニアとしてのキャリアを守ります。
一歩ずつ、セキュアな実装を身につけていきましょう。応援しています!
コメント