Mensagem de erro
java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits: RSA 768 bit key used with certificate: CN=api.example.com
Também aparece como
- 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
O tipo da chave, o tamanho e o titular são preenchidos para cada certificado. A camada TLS informa o erro como “(unsupported_certificate) PKIX path validation failed: …”. Com um certificado de servidor assinado com MD5, nosso teste falhou antes, com handshake_failure vindo do servidor, porque a JVM nem sequer oferece assinaturas MD5.
Java (PKIX validator) — jdk.certpath.disabledAlgorithms rejects a weak key or signature algorithm in the chain
O que significa
O Java montou um caminho confiável, mas um dos certificados usa uma chave (ou um algoritmo de assinatura) que jdk.certpath.disabledAlgorithms proíbe, então a validação do caminho falha. A mensagem cita o algoritmo, o tamanho da chave e o titular do certificado. Os JDKs atuais rejeitam chaves RSA e DSA com menos de 1024 bits, chaves EC com menos de 224 bits e assinaturas MD2/MD5 em cadeias de certificados.
Por que acontece
Um certificado legado com uma chave pequena
comumAppliances antigos, servidores web embarcados e certificados de teste gerados com chaves RSA de 512 ou 768 bits.
Um certificado da cadeia assinado com MD5 (ou com SHA-1 sob uma raiz distribuída com o JDK)
ocasionalA propriedade jdk.certpath.disabledAlgorithms também lista MD2, MD5 e SHA-1 para cadeias de servidores TLS que terminam em uma CA distribuída com o JDK.
Uma atualização do JDK tornou as restrições mais rígidas
ocasionalAs restrições ficam mais rígidas de tempos em tempos nas atualizações de segurança; certificados que passavam em uma atualização anterior podem falhar depois que o JDK é atualizado.
Como corrigir
- 1.
Encontrar o certificado fraco
Imprima o tamanho da chave pública e o algoritmo de assinatura de cada certificado da cadeia servida.
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.
Reemitir com uma chave moderna
ECDSA P-256 ou RSA 2048+ com assinatura SHA-256 é aceito em todo lugar.
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.
Ler as restrições do JDK
A propriedade jdk.certpath.disabledAlgorithms do arquivo java.security lista o que é rejeitado; é possível afrouxá-la sobrescrevendo as propriedades de segurança, mas isso volta a admitir chaves que podem ser quebradas.
bash # What this JDK rejects in certificate chains sed -n '/^jdk.certpath.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security"