Java/OpenSSL CA generation

2008-10-14

I was trying to find a Java equivalent to openssl x509 -hash -in certificate.pem

It turns out it’s an OpenSSL invention; while there’s no pre-written solution, here’s one I wrote earlier:

    public static String opensslHash(X509Certificate cert) {
        try {
            return openssl_X509_NAME_hash(cert.getSubjectX500Principal());
        }
        catch (NoSuchAlgorithmException e) {
            throw new Error("MD5 isn't available!", e);
        }
    }



    /**
    * Generates a hex X509_NAME hash (like openssl x509 -hash -in cert.pem)
    * Based on openssl's crypto/x509/x509_cmp.c line 321
    */
    public static String openssl_X509_NAME_hash(X500Principal p) throws NoSuchAlgorithmException {
        // This code replicates OpenSSL's hashing function
        // DER-encode the Principal, MD5 hash it, then extract the first 4 bytes and reverse their positions
        byte[] derEncodedSubject = p.getEncoded();
        byte[] md5 = MessageDigest.getInstance("MD5").digest(derEncodedSubject);


        // Reduce the MD5 hash to a single unsigned long
        byte[] result = new byte[] { md5[3], md5[2], md5[1], md5[0] };
        return toHex(result);

    }


    // encode binary to hex

    private static String toHex(final byte[] bin) {

        if (bin == null || bin.length == 0)
            return "";

        char[] buffer = new char[bin.length * 2];


        final char[] hex = "0123456789abcdef".toCharArray();

        // i tracks input position, j tracks output position
        for (int i = 0, j = 0; i < bin.length ;i++) {
            final byte b = bin[i];

            buffer[j++] = hex[(b >> 4) & 0x0F];
            buffer[j++] = hex[b & 0x0F];
        }

        return new String(buffer);
    }