2
votes

I want to generate an X509 certificate for a private key stored in the Google Cloud HSM.

Using Java Key tool and a local Java "keystore" i would do something like this:

keytool -exportcert -alias sign1 -keystore signkeystore -storetype jks -storepass password -file sign1.certificate

See http://tutorials.jenkov.com/java-cryptography/keytool.html

Using OpenSSL i would do something like this:

openssl genrsa -out private.key 1024

openssl req -new -x509 -key private.key -out publickey.cer -days 365

openssl pkcs12 -export -out public_privatekey.pfx -inkey private.key -in publickey.cer

See X.509: Private / Public Key

It would seem, generating a certificate needs access to the "private key", in some fashion, either directly like OpenSSL or indirectly like keytool using the private keystore.

Gcloud documentation seems to use OpenSSL for generating the private key. https://cloud.google.com/load-balancing/docs/ssl-certificates

How do i get a X509 certificate for a private key in Google Cloud HSM. Has anyone done this before ?

Regards Suchak

1

1 Answers

1
votes

I had a look at this thread Creating an X509 Certificate in Java without BouncyCastle?.

Then I did the following two create a GCloud X509 Certificate

  1. Create a key in the GCloud HSM (see https://cloud.google.com/kms/docs/hsm)
  2. Download the public key from GCloud.
  3. Use the code below to create a X509 certificate.
  4. Run some unit tests on the same.
    /**
     * Create a self-signed X.509 based on a public key
     * @param googlePublicKey the Public key downloaded from Google Cloud HSM
     * @param dn        the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param days      how many days from now the Example is valid for
     * @param algorithm the signing algorithm, eg "SHA1withRSA"
     */
    public static X509Certificate generateRSACertificate(String googlePublicKey, String dn, int days, String algorithm)
            throws GeneralSecurityException, IOException {
        byte[] derKey = Base64.decodeBase64(googlePublicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
        PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privkey = keyPair.getPrivate();
        X509CertInfo info = new X509CertInfo();
        Date from = new Date();
        Date to = new Date(from.getTime() + days * 86400000l);
        CertificateValidity interval = new CertificateValidity(from, to);
        BigInteger sn = new BigInteger(64, new SecureRandom());
        X500Name owner = new X500Name(dn);

        info.set(X509CertInfo.VALIDITY, interval);
        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
        info.set(X509CertInfo.SUBJECT, owner);
        info.set(X509CertInfo.ISSUER, owner);
        info.set(X509CertInfo.KEY, new CertificateX509Key(rsaKey));
        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
        AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

        // Sign the cert to identify the algorithm that's used.
        X509CertImpl cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);

        // Update the algorith, and resign.
        algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
        cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);
        return cert;
    }

Imports used were

import org.apache.commons.codec.binary.Base64;
import sun.security.x509.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Collection;
import java.util.Date;