java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

james picture james · Jan 4, 2013 · Viewed 100.4k times · Source

I have a mapping application that can add ArcGIS 9.3+ base maps given a URL. One of the URLs that I would like to add is from a customer's URL and is secured. My mapping application was using Java 6 before and was able to add the secure URL with no issues. I now upgraded to Java 7 and am getting a

"java.security.cert.CertificateException: Certificates does not conform to algorithm constraints"

exception. At first, I believe this to be the case because in Java 7, by default, the MD2 algorithm to sign SSL certificates is disabled. You can see this in the java.security file:

"jdk.certpath.disabledAlgorithms=MD2"

But when I check the Certification Signature Algorithm of that URL, it says SHA-1. What is even more strange is if I comment out the "jdk.certpath.disabledAlgorithms=MD2" line in the java.security file, the URL will work with no issues. Is MD2 used somewhere else during the SSL process? Am I missing something here?

Answer

Raman picture Raman · Jan 5, 2014

Background

MD2 was widely recognized as insecure and thus disabled in Java in version JDK 6u17 (see release notes http://www.oracle.com/technetwork/java/javase/6u17-141447.html, "Disable MD2 in certificate chain validation"), as well as JDK 7, as per the configuration you pointed out in java.security.

Verisign was using a Class 3 root certificate with the md2WithRSAEncryption signature algorithm (serial 70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf), but deprecated it and replaced it with another certificate with the same key and name, but signed with algorithm sha1WithRSAEncryption. However, some servers are still sending the old MD2 signed certificate during the SSL handshake (ironically, I ran into this problem with a server run by Verisign!).

You can verify that this is the case by getting the certificate chain from the server and examining it:

openssl s_client -showcerts -connect <server>:<port>

Recent versions of the JDK (e.g. 6u21 and all released versions of 7) should resolve this issue by automatically removing certs with the same issuer and public key as a trusted anchor (in cacerts by default).

If you still have this issue with newer JDKs

Check if you have a custom trust manager implementing the older X509TrustManager interface. JDK 7+ is supposed to be compatible with this interface, however based on my investigation when the trust manager implements X509TrustManager rather than the newer X509ExtendedTrustManager (docs), the JDK uses its own wrapper (AbstractTrustManagerWrapper) and somehow bypasses the internal fix for this issue.

The solution is to:

  1. use the default trust manager, or

  2. modify your custom trust manager to extend X509ExtendedTrustManager directly (a simple change).