Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
2.33/5 (3 votes)
I've got an HTTPS client and a HTTPS server coded in java, i need to make a SSL connection to the HTTPS server to get a message based on the condition that the client should accept the connection if the certificate hash of the server's certificate during SSL handshake equals to the one I've declared already in my client.

Here is my code

C#
package testsimulation;

import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import javax.net.ssl.*;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.util.encoders.Hex;


public class HTTPclient extends akande {
    private static String urlString;

public String k = a9 09 50 2d d8 2a e4 14 33 e6 f8 38 86 b0 0d 42 77 a3 2a 7b;
    public static void main(String[] args) throws Exception

    {
          //set necessary truststore properties - using JKS
         System.setProperty("javax.net.ssl.trustStore", "FiddlerKeystore.jks");
            System.setProperty("javax.net.ssl.trustStorePassword", "codedfar");
           // System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");

           // System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");

    SSLContext sslContext = createSSLContext();
      //  sslContext.init(null, null, null);

      SSLSocketFactory fact = sslContext.getSocketFactory();
       //    SSLSocketFactory fact = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();

        URL url = new URL("https://localhost:9990");
        System.setProperty("proxySet","true");
       System.setProperty("https.proxyHost", "127.0.0.1");
System.setProperty("https.proxyPort", "8888");
//-Djavax.net.ssl.trustStore=<path\to\fiddlerkeystore>
//-Djavax.net.ssl.trustStorePassword= codedfar;
    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888));

        HttpsURLConnection connection = (HttpsURLConnection)url.openConnection(proxy);

        connection.setSSLSocketFactory(fact);
      connection.setHostnameVerifier(new Validator());
        connection.connect();
        InputStream in = connection.getInputStream();

        int ch=0;
        while((ch = in.read()) >= 0)
        {
            System.out.println((char)ch);
        }
        in.close();
  // int th =1;
  // th.force(0);

    }
}


I want to compare the server's certificate thumbprint collected from another server which is declared in my class against the server's thumbprint obtained in the SSL handshake to know if it is the same.
Posted
Updated 18-Sep-13 4:56am
v2

I've done this on client side only by specifying the list of accepted certificates. I've never tried to do this what certificate hash, I don't know whether the java api allows you to do this or not. If you have the certificates then you can specify them as trusted: http://stackoverflow.com/questions/859111/how-do-i-accept-a-self-signed-certificate-with-a-java-httpsurlconnection[^]. I think this is the clean solution.

If you want custom server certificate validator code then this example may help: http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https/6378872[^]
The important thing is the checkServerTrusted() method in the trustmanager, you should always throw an exception there except if your check find the server acceptable.
 
Share this answer
 
Comments
ooolaoolaola 18-Sep-13 13:38pm    
@pasztorpisti Thank you very much for the assistance. A certificate hash is the hexadecimal code that normally appears in this form 42:af:77:b6:25:1c:59:69:af:be:00:a1:f8:b0:1a:. Normally, if you go to your keytool you can see this as SHA1 42:af:77:b6:25:1c:59:69:af:be:00:a1:f8:b0:1a: that's the certificate's public key in digest form. I like your solution but the other server sends just this thumbprint is there anyway to do this in java?
pasztorpisti 18-Sep-13 17:21pm    
I have no time to put together a ready-made solution in java but I can give you very useful info from which you should be able to get the job done. The certificate is a public key packed together with some additional info (company, name of issuer, expiry date, ...). The certificate is a piece of binary data, this binary format is called DER format. A format I use more often is PEM, the pem format is textual, the contents of the pem file consists of a header, a footer and between the two the DER format of the certificate in base64 encoded format:
-----BEGIN CERTIFICATE-----
<base64 encoded DER certificate data>
-----END CERTIFICATE-----

To get the fingerprint you have to have the certificate in binary DER format and you simply have to hash it with a hash algorithm (that is usually sha1). That's it. In your trustmanager you have to get the binary DER format of the certificate and you have to hash the byte array with sha1. In your TrustManager implementation you receive a cert chain and use the getEncoded() method of the certificates to get the DER format in a byte array. Give it a try and come back if you fail.
ooolaoolaola 18-Sep-13 18:58pm    
Hey boss, please can you help me with some code guidelines to this problem?, becuase i've got very little experience with the trust manager API and these format thing.
pasztorpisti 19-Sep-13 1:01am    
Bosses don't write code. If you haven't yet realized all you have to do is throwing a CertificateException from the trustmanager methods (that are empty in the linked example). There is no special api knowledge or whatever is needed. Start reading the second linked example if you haven't done that and integerate it with the code of your client. From the checkServerTrusted() method you also throw CertificateException all the time except when the specified sha1 of the certificate matches your sha1. Calculating the sha1: I've posted a step-by-step guide about calculating the fingerprint and it doesn't require knowledge of cert formats, you have to know only about their existence and your already know about it. I don't know these formats, I just use them. If you are lazy to do this or if you are not a programmer then ask a programmer friend/workmate to do it.
ooolaoolaola 19-Sep-13 9:52am    
Hey boss, i've created a new an object of the trust manager but the problem is i can't call the checkServerTrusted(), even if i declared it within the SSL context class it brings an error. Here's the code



package testsimulation;

import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.*;
import static testsimulation.KeyStoreee.FPASSWORD;


public class akande extends KeyStoreee{




static SSLContext createSSLContext() throws Exception
{
KeyManagerFactory mgrfact = KeyManagerFactory.getInstance("SunX509");
KeyStore clientstore = KeyStore.getInstance("PKCS12");






clientstore.load(new FileInputStream("branndP.12"), CLIENTPASSWORD);
mgrfact.init(clientstore, CLIENTPASSWORD);
TrustManagerFactory trustFact = TrustManagerFactory.getInstance("SunX509");

KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("FiddlerKeystore"), FPASSWORD);
// trustStore.load(new FileInputStream("badac.jks"), TPASSWORD);

trustFact.init(trustStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(mgrfact.getKeyManagers(), trustFact.getTrustManagers(),null);
return sslContext;

}


public static void main(String[] args) throws Exception
{

SSLContext sslContext = createSSLContext();
SSLSocketFactory fact = sslContext.getSocketFactory();
SSLSocket cSock = (SSLSocket)fact.createSocket(HOST, PORT_NO);
}
}
The problem is i was told to implement this problem, i'm implementing it for my thesis and i'm submitting tomorrow i just need you to tell me where the code fits in. Thanks.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900