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);
}