2 つのアルゴリズム、1 つの役割
RSA 署名は、大きな合成数をモジュラスとするべき乗剰余演算に基づいています。秘密鍵は 2 つの秘密の素数から導出され、その積の素因数分解が難しいことが、鍵の秘密を守っています。一方、ECDSA(楕円曲線デジタル署名アルゴリズム。FIPS 186-5 で標準化)は楕円曲線上の点がなす群で演算を行い、困難な問題は楕円曲線離散対数問題です。
困難な問題が異なることの実際的な帰結は次のとおりです。素因数分解に対する攻撃は、楕円曲線離散対数に対する攻撃よりも効率よくスケールするため、同じ安全マージンを保つには、RSA 鍵を EC 鍵よりもはるかに速いペースで大きくしなければなりません。以下で説明するサイズと性能の違いのほとんどは、この 1 つの事実に起因します。
サイズ:同じ強度での鍵と署名
NIST によるセキュリティ強度の比較(SP 800-57 Part 1 を参照)では、256 ビットの楕円曲線鍵は、3072 ビットの RSA モジュラスと同じ 128 ビットのセキュリティ区分に位置付けられています。
| セキュリティレベル | ECDSA の曲線 | EC 公開鍵 | EC 署名 | RSA モジュラス | RSA 署名 |
|---|---|---|---|---|---|
| 112 ビット | P-224 | 57 B / 29 B* | 56 B(生形式) | 2048 ビット | 256 B |
| 128 ビット | P-256 | 65 B / 33 B* | 64 B(生形式、DER では約 70〜72 B) | 3072 ビット | 384 B |
| 192 ビット | P-384 | 97 B / 49 B* | 96 B(生形式) | 7680 ビット | 960 B |
| 256 ビット | P-521 | 133 B / 67 B* | 132 B(生形式) | 15360 ビット | 1920 B |
(*非圧縮形式・圧縮形式の点のエンコーディング。)現在、新しいシステムの最低ラインである 128 ビットのレベルでは、ECDSA P-256 の署名が 64 バイトなのに対して RSA-3072 は 384 バイトで、公開鍵のサイズもおよそ 10 分の 1 です。広く使われている(そして安全マージンが小さい)RSA-2048 でさえ、署名は 256 バイトになります。TLS ハンドシェイクの証明書、HTTP ヘッダーのトークン、ブロックチェーンのトランザクションなど、1 バイト単位でサイズが問われる場面では、サイズの点で常に楕円曲線が勝ります。
ECDSA の署名サイズが 2 つあることに注意してください。「生形式」の 64 バイトと、DER エンコードした場合の約 70〜72 バイトです。数学的には同じ署名に、よく使われる伝送用のエンコーディングが 2 種類あり、両者の取り違えは「invalid signature」エラーの最も多い原因の 1 つです。このテーマは別の記事で詳しく取り上げています。
速度:署名と検証の非対称性
2 つのアルゴリズムの性能特性は正反対です。この非対称性は実際のアーキテクチャを左右するので、しっかり理解しておく価値があります。
- RSA の検証は非常に高速です。検証は公開指数による 1 回のべき乗剰余演算で済み、公開指数はほぼ常に小さな値 65537 です。RSA が証明書チェーンでこれほど長く使われ続けてきたのはこのためです。証明書は 1 回署名され、何十億回も検証されます。
- RSA の署名は低速です。2048〜4096 ビットのモジュラスに対して、フルサイズの秘密指数でべき乗を計算するからです。RSA の鍵生成はさらに遅くなります。大きなランダムな素数を探索しなければならず、数分の 1 秒という体感できるほどの時間がかかることもあり、その長さは予測できない形でばらつきます。
- ECDSA の署名は高速です。256 ビットの有限体上での 1 回のスカラー倍算で済み、一般に RSA-2048 の署名より数倍から 1 桁速く、RSA-3072 と比べればその差はさらに大きくなります。EC の鍵生成には実質的にコストがかかりません(1 回のスカラー倍算)。これは一時鍵やデバイスごとの鍵で重要になります。
- ECDSA の検証は RSA の検証より低速です(おおよそスカラー倍算 2 回分)。ただし、現代のハードウェアでは、絶対的な速度としては十分に高速です。
サイズの違いは、数行の Node.js コードで直接確認できます。
import { generateKeyPairSync, sign } from "node:crypto";
const message = Buffer.from("measure me");
const ec = generateKeyPairSync("ec", { namedCurve: "P-256" });
const rsa = generateKeyPairSync("rsa", { modulusLength: 3072 }); // slow: prime search
const ecSig = sign("sha256", message, ec.privateKey); // DER-encoded by default
const rsaSig = sign("sha256", message, rsa.privateKey);
console.log("ECDSA P-256:", ecSig.length, "bytes"); // ~70-72 (64 raw)
console.log("RSA-3072: ", rsaSig.length, "bytes"); // 384
それぞれの現在の用途
- TLS / X.509:どちらも広く使われています。導入済みの証明書では今も RSA が主流ですが、ECDSA 証明書(P-256、P-384)は大手 CA が標準で発行しており、ハンドシェイクを大幅に小さくします。多くの大規模サイトは、RSA をフォールバックとして用意したうえで ECDSA を提供しています。TLS 1.3 は両方の署名方式をネイティブにサポートしています。
- SSH:エコシステムは楕円曲線に移行しました。新しい鍵では Ed25519(関連する EC 署名方式で、ECDSA ではありません)が通常のデフォルトで、ECDSA P-256 も一般的です。RSA 鍵も引き続き使えますが、従来の
ssh-rsa署名方式(SHA-1 ベース)は最近の OpenSSH のリリースでデフォルトで無効化されているため、RSA 鍵では SHA-2 のバリアントを使わなければなりません。 - JWT:RS256(RSA)は ID 基盤のエコシステムにおける従来のデフォルトで、ES256(ECDSA P-256)はコンパクトで現代的な選択肢であり、複数のプラットフォームで必須とされています(Apple のトークン API、DPoP、ほとんどの WebAuthn / パスキーの認証情報)。トレードオフはかなり具体的なので、専用のガイドを用意しています:JWT における ES256 と RS256。実際のトークンは JWT デバッガーで確認できます。
- ブロックチェーン:実質的に ECDSA の独壇場です。Bitcoin と Ethereum はどちらも secp256k1 曲線上の ECDSA で署名します(Bitcoin は Taproot で Schnorr 署名も追加で採用しました)。トランザクションの 1 バイトごとに手数料がかかる環境では、RSA は署名サイズのせいで最初から選択肢になりません。
- コード署名とファームウェア:従来は RSA が中心でしたが、混在が進んでいます。リソースの限られたデバイスでは、鍵が小さく、署名が高速でメモリ消費も少ない ECDSA が好まれます。
ECDSA の落とし穴:nonce は完璧でなければならない
ECDSA には、RSA にはまったくない運用上の要件が 1 つあります。署名のたびに新しい秘密の数 k(nonce)を消費し、方式の安全性は、その数がすべての署名で一意かつ一様ランダムであることに依存します。失敗したときの結果は致命的です。
- 1 つの鍵で 2 つの異なるメッセージに同じ
kが一度でも使われると、2 つの署名から初歩的な代数計算で秘密鍵を求められてしまいます。2010年の有名な PlayStation 3 の事件で起きたのがまさにこれで、固定の nonce によってゲーム機の署名鍵が露呈しました。 - 部分的に予測可能な nonce や、わずかに偏った nonce でも、多数の署名にわたって観測されれば、格子を使った手法で鍵を復元するのに十分な場合があります。したがって、署名時にシステムの乱数生成器が弱いことは、単なる品質の問題ではなく、鍵の危殆化につながるリスクです。
標準的な解決策は、RFC 6979 で規定された決定的 ECDSA です。HMAC を使って秘密鍵とメッセージダイジェストから k を導出するため、同じ入力からは常に同じ、偏りなく分布した nonce が得られ、署名時の乱数は不要になります。FIPS 186-5 は現在、決定的 ECDSA を認めており、最近のライブラリのほとんどは RFC 6979 か、そのヘッジ付き(hedged)のバリアント(決定的な導出に追加のエントロピーを混ぜる方式)を実装しています。ライブラリを選ぶときに、最初に確認すべき点の 1 つです。これに対して RSA は、PKCS#1 v1.5 では署名ごとの乱数を必要とせず、RSA-PSS のランダムなソルトは、重複しても鍵の危殆化にはつながりません。
どちらにも迫るポスト量子への移行期限
どちらを選ぶにしても、その廃止に備えた計画が必要です。ショアのアルゴリズムを実行できる十分に大きな量子コンピューターは、素因数分解も楕円曲線離散対数も同じように解いてしまいます。RSA も ECDSA も一緒に破られるということです。NIST は NIST IR 8547(まだ初期公開ドラフトの段階)で移行スケジュールの概要を示しています。古典的な署名アルゴリズム(ECDSA、EdDSA、RSA)は、連邦政府での利用において、どのパラメーターセットでも 2035年より後は使用禁止(disallowed)となります。それより早いマイルストーンが 1 つありますが、これは 112 ビットのセキュリティレベルにのみ適用され、署名では RSA-2048 と P-224 が該当します。これらは 2030年より後は非推奨(deprecated)、つまり引き続き使用できるものの、リスクが公式に認められた扱いになります。P-256、P-384、RSA-3072 は 2030年の期限の影響を受けません。どの鍵に最初に対処すべきかが変わるので、この違いは正確に押さえておく価値があります。
後継として指定されているのは ML-DSA(格子ベース、FIPS 204 で標準化)と SLH-DSA(ハッシュベース、FIPS 205)で、Falcon から派生した FN-DSA がこれに続く予定です。サイズの大きさには覚悟が必要です。ML-DSA-65 の署名は約 3.3 KB で、P-256 の署名の 50 倍にもなります。ハイブリッド証明書や複合証明書に関するプロトコルの策定作業が今も続いているのは、このためです。現時点での実践的な結論は「今すぐあらゆる場所で PQC を導入する」ことではなく、クリプトアジリティを確立することです。システムが署名を行う箇所をすべて把握し、アルゴリズムの選択を設定で変更できるようにしておき、鍵長や署名サイズをハードコードしないようにします。
結局、今どちらを使うべきか
実際のバイト列で違いを確かめてみませんか。ECDSA 署名検証ツールで署名を生成するか貼り付けてください。曲線とエンコーディングを自動検出し、何を検証したのかを正確に表示します。