Error message
java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits: RSA 768 bit key used with certificate: CN=api.example.com
Also printed as
- 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
The key type, size and subject are filled in per certificate. The TLS layer reports it as "(unsupported_certificate) PKIX path validation failed: …". With an MD5-signed server certificate our test failed earlier, with handshake_failure from the server, because the JVM does not offer MD5 signatures at all.
Java (PKIX validator) — jdk.certpath.disabledAlgorithms rejects a weak key or signature algorithm in the chain
What it means
Java built a trusted path, but a certificate in it uses a key (or signature algorithm) that jdk.certpath.disabledAlgorithms forbids, so path validation fails. The message names the algorithm, the key size and the certificate's subject. Current JDKs reject RSA and DSA keys under 1024 bits, EC keys under 224 bits and MD2/MD5 signatures in certificate chains.
Why it happens
A legacy certificate with a small key
commonOld appliances, embedded web servers and test certificates generated with 512- or 768-bit RSA keys.
A chain certificate signed with MD5 (or SHA-1 under a JDK-shipped root)
occasionaljdk.certpath.disabledAlgorithms also lists MD2, MD5, and SHA-1 for TLS server chains that end in a CA shipped with the JDK.
A JDK update tightened the constraints
occasionalThe constraints are raised from time to time in security updates; certificates that passed on an older update can fail after upgrading.
How to fix it
- 1.
Find the weak certificate
Print the public key size and signature algorithm of each certificate in the served chain.
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.
Reissue with a modern key
ECDSA P-256 or RSA 2048+ with a SHA-256 signature is accepted everywhere.
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.
Read the JDK's constraints
jdk.certpath.disabledAlgorithms in java.security lists what is rejected; relaxing it is possible with a security properties override but re-admits keys that can be broken.
bash # What this JDK rejects in certificate chains sed -n '/^jdk.certpath.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security"