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?
openssl s_client -showcerts -connect server:port | grep -i md2
– jdiverdepth=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