エラーメッセージ
java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits: RSA 768 bit key used with certificate: CN=api.example.com
別の表記
- Algorithm constraints check failed on keysize limits
- javax.net.ssl.SSLHandshakeException: (unsupported_certificate) PKIX path validation failed: java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits
鍵の種類、鍵長、サブジェクトは証明書ごとに埋め込まれます。TLS 層では「(unsupported_certificate) PKIX path validation failed: …」として報告されます。MD5 で署名されたサーバー証明書でテストしたところ、JVM がそもそも MD5 署名を提示しないため、それより前の段階で、サーバーから返された handshake_failure によって失敗しました。
Java (PKIX validator) — jdk.certpath.disabledAlgorithms rejects a weak key or signature algorithm in the chain
このエラーの意味
Java は信頼できるパスを構築しましたが、パス内の証明書が jdk.certpath.disabledAlgorithms で禁止されている鍵(または署名アルゴリズム)を使っているため、パス検証に失敗します。メッセージには、アルゴリズム、鍵長、証明書のサブジェクトが示されます。現在の JDK は、証明書チェーン内の 1024 ビット未満の RSA 鍵と DSA 鍵、224 ビット未満の EC 鍵、MD2/MD5 署名を拒否します。
発生する理由
鍵長の短い古い証明書
よくある古いアプライアンス、組み込みのウェブサーバー、テスト用の証明書で、512 ビットまたは 768 ビットの RSA 鍵で生成されたものです。
MD5 で署名されたチェーン内の証明書(または JDK 同梱のルート配下での SHA-1)
ときどきjdk.certpath.disabledAlgorithms には MD2 と MD5 も含まれており、JDK に同梱された CA で終わる TLS サーバーのチェーンについては SHA-1 も含まれています。
JDK のアップデートで制約が厳しくなった
ときどき制約はセキュリティアップデートで随時引き上げられます。古いアップデートでは通っていた証明書が、アップグレード後に失敗することがあります。
修正方法
- 1.
弱い証明書を見つける
サーバーが送信するチェーン内の各証明書について、公開鍵の鍵長と署名アルゴリズムを出力してください。
bash # Key size and signature algorithm of every certificate the server sends openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | awk '/BEGIN CERT/{n++; f="c" n ".pem"} /BEGIN CERT/,/END CERT/{print > f}' for f in c*.pem; do openssl x509 -in "$f" -noout -subject -text | grep -E 'subject=|Public-Key|Signature Algorithm' | sort -u; done - 2.
現在の標準的な鍵で再発行する
ECDSA P-256 または 2048 ビット以上の RSA に SHA-256 署名を組み合わせれば、どこでも受け入れられます。
bash # Replace the weak key: ECDSA P-256 (or RSA 2048+) with a SHA-256 signature openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout server.key \ -subj "/CN=api.example.com" -addext "subjectAltName=DNS:api.example.com" -out server.csr - 3.
JDK の制約を確認する
java.security の jdk.certpath.disabledAlgorithms に、拒否される対象が列挙されています。セキュリティプロパティを上書きして制約を緩めることもできますが、そうすると破られる可能性のある鍵を再び受け入れることになります。
bash # What this JDK rejects in certificate chains sed -n '/^jdk.certpath.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security"