【入門編】 RSA暗号におけるパディング方式(PKCS#1 v1.5 vs OAEP)の選択基準 – 暗号理論・認証基盤 & エンドポイントセキュリティ防御ガイド

RSA暗号の「落とし穴」:なぜ古い鍵の閉め方(PKCS#1 v1.5)を使ってはいけないのか?

エンジニアの皆さん、こんにちは。セキュリティの世界へようこそ。

今日は、皆さんが普段何気なく使っている「暗号」の、ちょっとだけ深い話をしましょう。特に、世界中の通信を影で支えている「RSA暗号」の、パディング(Padding)という仕組みについてです。

「パディング? なんだか難しそう…」と思うかもしれません。でも、これを知っているかどうかで、あなたの作ったサービスのセキュリティレベルは天と地ほど変わります。一緒に紐解いていきましょう。

—

1. そもそも「パディング」って何?:家の鍵に例えてみよう

まず、イメージしてください。あなたはとても大事な手紙を、頑丈な金庫に入れて送ろうとしています。

RSA暗号という金庫は、実は少し「気難しい」性質を持っています。中に入れるデータが短すぎたり、規則性が強すぎたりすると、数学的な法則性が見抜かれて、鍵を壊さなくても中身を推測されてしまう弱点があるんです。

そこで登場するのがパディングです。
これは、金庫に入れる前にデータの周りに「意味のないゴミデータ(乱数)」を詰め込んで、データをカサ増しする作業のことです。

  • パディングなし: 鍵をかけるだけ。泥棒は「中身が何となくこれくらいかな?」と推測できてしまう。
  • パディングあり: データをランダムな装飾で包み込む。泥棒は「金庫の中身が何なのか、形すらさっぱりわからない!」と頭を抱える。

この「どうやって包むか」のルールが、昔から使われているPKCS#1 v1.5と、現代の推奨であるOAEPというわけです。

—

2. なぜ「PKCS#1 v1.5」は危ないのか?(Bleichenbacher攻撃)

PKCS#1 v1.5は、いわば「昔の規格」です。
この方式は、暗号を解読しようとする泥棒に、非常に親切な「ヒント」を与えてしまうという致命的な欠陥があります。

泥棒は、適当に作った暗号文をあなたのサーバーに送りつけます。するとサーバーは、「あ、これパディングの形式が間違ってるよ!」というエラーを返します。
泥棒はこの反応を見て、「なるほど、今のデータは不正解だったのか。じゃあ次はこうしてみよう」と、試行錯誤を繰り返すのです。

これをBleichenbacher攻撃(ブライヘンバッハー攻撃)と呼びます。何度もエラーの反応を見聞きすることで、ついには金庫の鍵そのものを暴いてしまう。まるで、玄関の鍵をガチャガチャ回して、扉の隙間から漏れる「カチッ」という音を頼りに、中の構造を読み解くような泥棒ですね。

—

3. 現代の正解「RSA-OAEP」へ移行しよう

この攻撃を防ぐために生まれたのがOAEP(Optimal Asymmetric Encryption Padding)です。
OAEPは、中身を包むプロセスで最新のハッシュ関数を使い、データの整合性を厳密にチェックします。万が一、泥棒が細工をした暗号文を送っても、サーバーは「エラーです」というヒントを極力出さず、淡々と処理を終了させるため、泥棒は何も学べないのです。

実装のヒント:OpenSSLでの設定例

もし皆さんがサーバーサイドで暗号化処理を書くなら、設定は必ずOAEPを選んでください。例えば、PHPのopenssl_public_encrypt関数を使う場合は、以下のように指定します。

<?php
// 公開鍵の読み込み
$publicKey = openssl_pkey_get_public(file_get_contents('public.pem'));
$data = "秘密のメッセージ";

// 第4引数にパディング方式を指定する
// PKCS1_PADDING は古いので絶対に使わない!
// OPENSSL_PKCS1_OAEP_PADDING を使うのが現代の標準
$encryptedData = '';
$result = openssl_public_encrypt(
    $data, 
    $encryptedData, 
    $publicKey, 
    OPENSSL_PKCS1_OAEP_PADDING // ここが重要!
);

if ($result) {
    echo "安全に暗号化されました。";
} else {
    echo "エラーが発生しました。";
}
?>

—

4. 今日からできること:一歩ずつ学んでいこう

開発現場で、古いライブラリの設定がPKCS1_PADDINGのままになっていないか、一度確認してみてください。

1. 設定を見直す: 暗号化ライブラリのドキュメントを開き、パディングの項目を探す。
2. OAEPを選択する: 可能であれば、デフォルトでOAEPが有効になるものを使う。
3. エラーメッセージを慎重に: ログインや復号のエラーで、「パディングが不正です」なんて親切な情報をユーザーに返していないか?(これは攻撃者にヒントを与えます。ログにだけ残して、ユーザーには一律で「エラーです」と返すのが鉄則です!)

セキュリティは「完璧」を目指すのではなく、「泥棒の手間を最大限に増やす」作業の積み重ねです。今日から、皆さんの書くコードが少しだけ強固になることを願っています。

また次の記事でお会いしましょう! 安全なコーディングを!

コメント

タイトルとURLをコピーしました