2
votes

Sorry for the uninformative title, but the question is too large to express in a few words. So, I have a Java program that connects to an SSL webserver using HttpsURLConnection. With the following line in (JDK path)/jre/lib/security/java.security:

jdk.certpath.disabledAlgorithms=MD2

It gives the following error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints

And when I replace it with this line:

jdk.certpath.disabledAlgorithms=

It connects. Now, common logic tells that this is caused by the server using MD2 to sign its certificate. But it doesn't use MD2, it uses SHA1! I have confirmed this by 1) checking the certificate info from Chrome (the lock button in the address bar -> Connection -> Certificate information) and 2) running the following code from http://sanjaal.com/java/tag/get-ssl-certificate-info-in-java/ :

SSLSocketFactory factory = HttpsURLConnection
.getDefaultSSLSocketFactory();

System.out.println("Creating a SSL Socket For "+hostname+" on port "+port);

SSLSocket socket = (SSLSocket) factory.createSocket(hostname, port);

/**
* Starts an SSL handshake on this connection. Common reasons include a
* need to use new encryption keys, to change cipher suites, or to
* initiate a new session. To force complete reauthentication, the
* current session could be invalidated before starting this handshake.
* If data has already been sent on the connection, it continues to flow
* during this handshake. When the handshake completes, this will be
* signaled with an event. This method is synchronous for the initial
* handshake on a connection and returns when the negotiated handshake
* is complete. Some protocols may not support multiple handshakes on an
* existing socket and may throw an IOException.
*/

socket.startHandshake();
System.out.println("Handshaking Complete");

/**
* Retrieve the server's certificate chain
*
* Returns the identity of the peer which was established as part of
* defining the session. Note: This method can be used only when using
* certificate-based cipher suites; using it with non-certificate-based
* cipher suites, such as Kerberos, will throw an
* SSLPeerUnverifiedException.
*
*
* Returns: an ordered array of peer certificates, with the peer's own
* certificate first followed by any certificate authorities.
*/
Certificate[] serverCerts = socket.getSession().getPeerCertificates();
System.out.println("Retreived Server's Certificate Chain");

System.out.println(serverCerts.length + " Certifcates Found\n\n\n");
for (int i = 0; i < serverCerts.length; i++) {
    Certificate myCert = serverCerts[i];
    System.out.println("====Certificate:" + (i+1) + "====");
    System.out.println("-Public Key-\n" + myCert.getPublicKey());
    System.out.println("-Certificate Type-\n " + myCert.getType());

    System.out.println();
}

socket.close();

This output the following:

    run:
Creating a SSL Socket For 127.0.0.1 on port 5001
Handshaking Complete
Retreived Server's Certificate Chain
4 Certifcates Found



====Certificate:1====
-Public Key-
Sun RSA public key, 2048 bits
  modulus: <first RSA public key>
  public exponent: 65537
-Certificate Type-
 X.509

====Certificate:2====
-Public Key-
Sun RSA public key, 2048 bits
  modulus: <second RSA public key>
  public exponent: 65537
-Certificate Type-
 X.509

====Certificate:3====
-Public Key-
Sun RSA public key, 2048 bits
  modulus: <third RSA public key>
  public exponent: 65537
-Certificate Type-
 X.509

====Certificate:4====
-Public Key-
Sun RSA public key, 1024 bits
  modulus: <fourth RSA public key>
  public exponent: 65537
-Certificate Type-
 X.509

I've omitted the actual keys, but the output clearly states that the public keys are in perfect order and are definetely NOT MD2, but (I think) RSA-encrypted SHA1.

Now, my question is... how is that even possible? Why does disabling MD2 make Java refuse to access a site with an SHA-1 signed certificate? And how in the world can I make my program access the site WITHOUT having to edit the java.security file?

Run the following comment to check for md2 openssl s_client -showcerts -connect server:port | grep -i md2jdiver
When the server sends its certificate it has to provide a new digital signature over the certificate plus a few other things, to prove it owns the certificate. This is different from the signature in the certificate itself.user207421
@jdiver: this command returned the following: depth=3 C = US, O = "VeriSign, Inc.", OU = Class 3 Public Primary Certification Authority verify error:num=19:self signed certificate in certificate chain verify return:0 user3079266
The output shows nothing at all about the hash function used to sign the certificates themselves.President James K. Polk
@Mints97: No. RSA plus a hash function is used in the signing algorithm. Evidently one of the certificates is signed with RSA-MD2, probably one of the self-signed root certificates.President James K. Polk