P-256 と P-384 のどちらを使うかは、同じファミリーに属する 2 つの NIST 曲線から選ぶ問題です。アルゴリズム(ECDSA と ECDH)も、エンコーディングも、ツールも共通です。P-384 は古典的セキュリティを約 128 ビットから約 192 ビットに引き上げ、P-256 は数倍高速で、対応するハードウェアも多くあります。ほとんどのシステムでは、リスクよりもポリシーによって判断が決まります。
比較表
| P-256(secp256r1) | P-384(secp384r1) | |
|---|---|---|
| 有限体のサイズ、群の位数 | 256 ビット | 384 ビット |
| 古典的セキュリティ | 約 128 ビット(AES-128 相当) | 約 192 ビット(AES-192 相当) |
| 通常組み合わせるハッシュ関数 | SHA-256 | SHA-384 |
| 秘密鍵 | 32 バイト | 48 バイト |
| 公開鍵 | 非圧縮形式で 65 バイト、SPKI DER で 91 バイト | 非圧縮形式で 97 バイト、SPKI DER で 120 バイト |
| 署名 | 生形式で 64 バイト、DER で 70〜72 バイト | 生形式で 96 バイト、DER で約 102〜104 バイト |
| 1 秒あたりの署名数・検証数(OpenSSL 3.6.5) | 約 87,000 / 29,000 | 約 9,700 / 4,500 |
| JOSE / COSE | ES256 / −7 | ES384 / −35 |
| TLS 1.3 | ecdsa_secp256r1_sha256(0x0403)、グループ 23 | ecdsa_secp384r1_sha384(0x0503)、グループ 24 |
| ハイブリッド TLS グループ | SecP256r1MLKEM768 | SecP384r1MLKEM1024 |
| Secure Enclave、Android Keystore、TPM 2.0 | 対応 | 製品による(Secure Enclave は非対応) |
| NIST IR 8547(ドラフト) | 2035年より後は禁止 | 2035年より後は禁止 |
速度は Apple M4 Max の 1 コアで openssl speed を使って測定しました。後述のサイズを調べるスクリプトは OpenSSL 3.6.5 で実行しました。
必要なセキュリティの水準
NIST SP 800-57 Part 1 は、256〜383 ビットの曲線を 128 ビットセキュリティに、384〜511 ビットの曲線を 192 ビットセキュリティに位置付けています。128 ビットは、予見できるどのような古典的攻撃もはるかに及ばない水準です。P-256 に対する既知の最良の攻撃でも、2¹²⁸ のオーダーの群演算が必要です。P-384 の追加のマージンは、総当たり攻撃ではなく、楕円曲線の暗号解読が予想外に進歩した場合への備えです。また、2 つの曲線をほぼ同じ労力で破る Shor のアルゴリズムに対しては、何の効果もありません。そのため NIST IR 8547(初期公開ドラフト)は両者を同じように扱っています。どちらも 2030年に非推奨になることはなく(非推奨の対象は RSA-2048 や P-224 のような 112 ビットのアルゴリズムだけです)、どちらも 2035年より後は禁止されます。
実際に判断を左右するのはポリシーです。NSA が当初定めた Commercial National Security Algorithm Suite(CNSA 1.0)は ECDH と ECDSA に P-384 を要求していたため、米国の国家安全保障システム向けの製品とそのサプライチェーンでは P-384 がデフォルトになっています。CNSA 2.0 では、これが ML-KEM-1024 と ML-DSA-87 に置き換えられます。認証局は、10 年以上にわたって信頼に足る状態を保たなければならないルート CA と中間 CA の鍵に、P-384 を選ぶことがよくあります。Let's Encrypt の ISRG Root X2 と ECDSA の中間証明書は P-384 ですが、サブスクライバー証明書にはどちらの曲線も使えます。
性能とサイズのコスト
OpenSSL には P-256 向けに手作業で最適化されたアセンブリコードが含まれているため、差が大きくなります。Apple M4 Max の 1 コアで、署名は P-256 が毎秒約 87,000 回、P-384 が約 9,700 回、検証は約 29,000 回と 4,500 回です。TLS サーバーでは、証明書の鍵による署名はフルハンドシェイクごとに 1 回なので、P-384 にするとハンドシェイクのその部分のコストが約 9 倍になります。毎秒数枚の証明書に署名する程度の認証局にとっては、この差は問題になりません。
サイズの増加はわずかです。署名は生形式で 32 バイト、公開鍵は 32 バイト、証明書は約 60 バイト大きくなります。
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
printf 'hello' > msg
for curve in P-256 P-384; do
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$curve -out key.pem 2>/dev/null
openssl req -new -x509 -key key.pem -subj "/CN=example.com" -days 90 -outform DER -out cert.der 2>/dev/null
openssl dgst -sha256 -sign key.pem -out sig.der msg
printf '%s: SPKI %s bytes, DER signature %s bytes, self-signed certificate %s bytes\n' "$curve" \
"$(openssl pkey -in key.pem -pubout -outform DER | wc -c | tr -d ' ')" \
"$(wc -c < sig.der | tr -d ' ')" \
"$(wc -c < cert.der | tr -d ' ')"
done
cd / && rm -rf "$dir"
P-256: SPKI 91 bytes, DER signature 71 bytes, self-signed certificate 388 bytes
P-384: SPKI 120 bytes, DER signature 102 bytes, self-signed certificate 451 bytes
対応状況
どちらの曲線も、FIPS 186-5 と SP 800-186、すべての TLS ライブラリ、WebCrypto、JOSE と COSE、PIV スマートカード、そして CA/Browser Forum が証明書に認める鍵のリスト(P-256、P-384、P-521)に含まれています。差があるのはセキュアハードウェアと認証器です。Apple の Secure Enclave が古典的な鍵として提供するのは P-256 だけで、パスキーはほぼ例外なく ES256 を使い、IoT 向けのセキュアエレメントには P-256 しか実装していないものもあります。サーバー側では、HSM とクラウドの KMS サービスが両方に対応しています。
それぞれの用途
- 公開 TLS 証明書:P-256 を使います。ハンドシェイクが高速で、どこでも受け入れられます。P-384 のリーフ証明書にしても、クライアントが検証できる利点は何も得られません。
- CA のルート鍵と中間鍵:長期間使う鍵には P-384 が一般的で妥当な選択です。その鍵で P-256 のリーフ証明書に署名してもかまいません。
- JWT と API トークン:
ES256を使います。ただし、一部の政府機関や金融業界の仕様のようなプロファイルがES384を要求する場合は別です。 - パスキーとデバイスの鍵:P-256 を使います。ハードウェアが提供しているのが P-256 だからです。
- CNSA 1.0 のシステムとそのベンダー:P-384 と SHA-384、そして AES-256 を使います。CNSA 2.0 に基づく ML-KEM-1024 と ML-DSA-87 への移行を計画してください。
- ハイブリッドのポスト量子 TLS:一般的な用途には
X25519MLKEM768を使います。CNSA のようなポリシーが NIST 曲線とカテゴリ 5 のパラメーターを求める場合はSecP384r1MLKEM1024を使います。
移行時の注意点
曲線を変更すると鍵は新しくなりますが、ツールはそのまま使えます。
- 新しい鍵を生成する:鍵を保管する HSM または KMS の内部で、
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384(または P-256)を使って生成します。 - ハッシュ関数を正しく組み合わせる:P-384 は通常 SHA-384 と組み合わせて使います(
ES384、ecdsa-with-SHA384)。ECDSA は長いハッシュ値を位数の長さに切り詰めますが、組み合わせが一致していないと、ポリシーのチェックや一部の検証者が混乱します。 - 識別子を更新する:JOSE の
algとcrv、COSE のアルゴリズム、TLS の署名方式、証明書プロファイルを更新します。鍵のローテーション中は、別々のkid値を付けた両方の鍵を JWKS で公開してください。 - 固定長バッファーのサイズを変更する:生形式の署名は 64 バイトから 96 バイトに、座標は 32 バイトから 48 バイトに大きくなります。
- ハンドシェイクのベンチマークを取る:負荷の高い TLS エンドポイントを P-384 の証明書に切り替える前に計測してください。ポリシー上の理由で P-384 に移行する環境の多くは、ポリシーが適用されない部分では P-256 を使い続けています。