views:

1570

answers:

4

I have a java client that is calling a web service operation which takes a certificate "thumbprint" as a parameter. I believe the thumbprint is some kind of SHA1 hash, in hexadecimal string format, of the cert's public key, but I'm not sure.

The .NET framework seems to include a simple way to get this value (X509Certificate2.Thumbprint property). Viewing a .cer file's properties in Windows also displays the thumbprint, which looks like:

a6 9c fd b0 58 0d a4 ee ae 9a 47 75 24 c3 0b 9f 5d b6 1c 77

My question is therefore: Does anybody know how to retrieve or compute this thumbprint string within Java, if I have an instance of a java.security.cert.X509Certificate?

+3  A: 

Thumbprint is a .NET thing. Why do you need it in Java?

It's not part of certificate. It's simply SHA1 hash of the DER encoding of the certificate. You can calculate it easily like this,

public class X509 {

    public static void main(String[] args) {
     FileInputStream is;
     try {
      is = new FileInputStream("/tmp/certificate_x509.pem");
      CertificateFactory x509CertFact = CertificateFactory.getInstance("X.509");
      X509Certificate cert = (X509Certificate)x509CertFact.generateCertificate(is);
      String thumbprint = getThumbPrint(cert);
      System.out.println(thumbprint);

     } catch (FileNotFoundException e) {
      e.printStackTrace();
     } catch (CertificateException e) {
      e.printStackTrace();
     } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
     }

    }

    public static String getThumbPrint(X509Certificate cert) 
     throws NoSuchAlgorithmException, CertificateEncodingException {
     MessageDigest md = MessageDigest.getInstance("SHA-1");
     byte[] der = cert.getEncoded();
     md.update(der);
     byte[] digest = md.digest();
     return hexify(digest);

    }

    public static String hexify (byte bytes[]) {

     char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', 
       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

     StringBuffer buf = new StringBuffer(bytes.length * 2);

        for (int i = 0; i < bytes.length; ++i) {
         buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]);
            buf.append(hexDigits[bytes[i] & 0x0f]);
        }

        return buf.toString();
    }

}
ZZ Coder
Thanks for the answer! Googling around I found that the thumbprint is commonly used as a unique identifier for a certificate, so it doesn't seem to be .NET specific. The web service I'm calling is using it to find the certificate in their store.
Matt Z
The web service must be a .NET server. I haven't seen any other servers using thumbprint to store client cert. .NET made so much security-related extensions, you might encounter other issues also. Unless your client needs to be cross-platform, it would be a lot easier to write client in .NET too.
ZZ Coder
A: 

Hey MattZ,

I have the same problem. In java I need to get the Thumbprint as well. What was the solution to your orignal problem?

CharlesC
A: 

You can generate the thumbprint by using the openssl command, so example if you have the pem format of the certificate in a file (file.txt)

then:

cat file.txt | openssl x509 -sha1 -fingerprint - this would generate the same thumbprint

Clarence
A: 

Here's a simpler way:

using System.Security.Cryptography.X509Certificates;    

X509Certificate2 xcert = new X509Certificate2("C:\some_cert.cerpub");
string certSubject = xcert.Subject;
string certThumbprint =  xcert.Thumbprint;   
tech66
That's not Java :-) I know it's easy to get in .NET
Matt Z