Pham Anh Tuan
Pham Anh Tuan

Reputation: 11

CloudHSM generating a certificate signing request (CSR)

I generate a certificate signing request (CSR) by getting keypair from CloudHsmProvider's Keystore and use bouncycastle to generate csr, but I getting error java.lang.UnsupportedOperationException: getPrivateExponent is not supported by CloudHsmRsaPrivateCrtKey. On the other hand if I create the keypair (not save to the keystore) and then create the csr too, there is no such error and I still get the desired csr file. So is my problem caused by error when saving keypair to keystore?

enter image description here

Create CSR

public static void main(String[] args) {
    try {

        try {
            if (Security.getProvider(CloudHsmProvider.PROVIDER_NAME) == null) {
                Security.addProvider(new CloudHsmProvider());
            }
        } catch (IOException ex) {
            System.out.println(ex);
            return;
        }
        String keystoreFile = "abc.p12";
        String password = "123456";
        String label = "tuan14";

        final String privateLabel = label + ":Private";

        final KeyStore keyStore = KeyStore.getInstance(CloudHsmProvider.CLOUDHSM_KEYSTORE_TYPE);
        try {
            final FileInputStream instream = new FileInputStream(keystoreFile);
            keyStore.load(instream, password.toCharArray());
        } catch (final FileNotFoundException ex) {
            System.err.println("Keystore not found, loading an empty store");
            keyStore.load(null, null);
        }

        final PasswordProtection passwordProtection = new PasswordProtection(password.toCharArray());
        System.out.println("Searching for example key pair and certificate...");

        final PrivateKeyEntry keyEntry =
            (PrivateKeyEntry) keyStore.getEntry(privateLabel, passwordProtection);
        final String name = keyEntry.getCertificate().toString();
        System.out.printf("Found private key %s with certificate %s%n", label, name);


        PublicKey publicKey = keyEntry.getCertificate().getPublicKey();
        PrivateKey privateKey = keyEntry.getPrivateKey();

        X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE);

        x500NameBld.addRDN(BCStyle.CN, "ABC");
        x500NameBld.addRDN(BCStyle.C, "Viet Nam");
        x500NameBld.addRDN(BCStyle.ST, "Hà nội");
        x500NameBld.addRDN(BCStyle.L, "Cầu Giấy");
        x500NameBld.addRDN(BCStyle.O, "ABC");
        x500NameBld.addRDN(BCStyle.OU, "ABC");
        x500NameBld.addRDN(BCStyle.UID, "1427732196");
        x500NameBld.addRDN(BCStyle.UID, "1427732189");
        x500NameBld.addRDN(BCStyle.TELEPHONE_NUMBER, "0339028712");
        x500NameBld.addRDN(BCStyle.EmailAddress, "[email protected]");
        x500NameBld.addRDN(BCStyle.STREET, "abc");
        X500Name subject = x500NameBld.build();

        PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
                subject, publicKey);
        JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");

        ContentSigner signer = csBuilder.build((PrivateKey) privateKey);
        PKCS10CertificationRequest csr = p10Builder.build(signer);
        PemObject pemObject = new PemObject("CERTIFICATE REQUEST", csr.getEncoded());

        StringWriter strWriter;
        try (JcaPEMWriter pemWriter = new JcaPEMWriter(strWriter = new StringWriter())) {
            pemWriter.writeObject(pemObject);
        }
        writeToFile(strWriter.toString().getBytes(), "demo.pem");

    } catch (Throwable thr) {
        thr.printStackTrace();
        System.out.println("HSM Exception printStackTrace():");
    }
}

Store Keypair

 private static X509Certificate generateCertificate(String dn, String issuer, KeyPair pair, int days,
        String algorithm) throws GeneralSecurityException, IOException {
    PrivateKey privkey = pair.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);
    X500Name issuerName = new X500Name(issuer);
    AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
    if ("1.8".equals(System.getProperty("java.specification.version"))) {
        info.set(X509CertInfo.VALIDITY, interval);
        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
        info.set(X509CertInfo.SUBJECT, owner); 
        info.set(X509CertInfo.ISSUER, issuerName);
        info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
    }
    X509CertImpl cert = new X509CertImpl(info);
    cert.sign(privkey, algorithm);
    algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
    info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
    cert = new X509CertImpl(info);
    cert.sign(privkey, algorithm);
    return cert;
}

public static void main(String[] args) {

    try {
        try {
            if (Security.getProvider(CloudHsmProvider.PROVIDER_NAME) == null) {
                Security.addProvider(new CloudHsmProvider());
            }
        } catch (IOException ex) {
            System.out.println(ex);
            return;
        }

        String password = "123456";
        String label = "tuan14";
        String keystoreFile = "./abc.p12";

        String privateLabel = label+":Private";
        final PasswordProtection passwordProtection =
        new PasswordProtection(password.toCharArray());

        KeyStore keyStore = KeyStore.getInstance(CloudHsmProvider.CLOUDHSM_KEYSTORE_TYPE);
        keyStore.load(null, password.toCharArray());
        final KeyAttributesMap requiredPublicKeyAttributes =
            new KeyAttributesMapBuilder().put(KeyAttribute.VERIFY, true).build();
        final KeyAttributesMap requiredPrivateKeyAttributes =
            new KeyAttributesMapBuilder().put(KeyAttribute.SIGN, true).build();
        final KeyPair keyPair =
            AsymmetricKeys.generateRSAKeyPair(
                2048, label, requiredPublicKeyAttributes, requiredPrivateKeyAttributes);
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        System.out.println("Keypair info: ");
        System.out.println("Private key: " + privateKey.toString());
        System.out.println("Public key: " + publicKey);
        System.out.println("Algo PrivateKey: " + privateKey.getAlgorithm());
        X509Certificate rootCertificate = generateCertificate(
        "CN="+label,
        "CN="+label,
        keyPair, 
        30, 
        "SHA256WithRSA");

        //Create Chain
        X509Certificate[] chain = new X509Certificate[1];
        chain[0] = rootCertificate;
        final PrivateKeyEntry entry = new PrivateKeyEntry(keyPair.getPrivate(), chain);
        keyStore.setEntry(privateLabel, entry, passwordProtection);

        final FileOutputStream outstream = new FileOutputStream(keystoreFile);
        keyStore.store(outstream, password.toCharArray());
        outstream.close();
    } catch (Throwable thr) {
        thr.printStackTrace();
        System.out.println("HSM Exception printStackTrace():");
    }
}

public static KeyPair generateRSAKeyPair(
        int keySizeInBits,
        String label,
        KeyAttributesMap additionalPublicKeyAttributes,
        KeyAttributesMap additionalPrivateKeyAttributes)
        throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
                NoSuchProviderException, AddAttributeException {
    KeyPairGenerator keyPairGen =
            KeyPairGenerator.getInstance("RSA", CloudHsmProvider.PROVIDER_NAME);
    final KeyAttributesMap publicKeyAttrsMap = new KeyAttributesMap();
    publicKeyAttrsMap.putAll(additionalPublicKeyAttributes);
    publicKeyAttrsMap.put(KeyAttribute.LABEL, label + ":Public");
    publicKeyAttrsMap.put(KeyAttribute.MODULUS_BITS, keySizeInBits);
    publicKeyAttrsMap.put(KeyAttribute.PUBLIC_EXPONENT, new BigInteger("65537").toByteArray());

    final KeyAttributesMap privateKeyAttrsMap = new KeyAttributesMap();
    privateKeyAttrsMap.putAll(additionalPrivateKeyAttributes);
    privateKeyAttrsMap.put(KeyAttribute.LABEL, label + ":Private");

    KeyPairAttributesMap keyPairSpec =
            new KeyPairAttributesMapBuilder()
                    .withPublic(publicKeyAttrsMap)
                    .withPrivate(privateKeyAttrsMap)
                    .build();

    keyPairGen.initialize(keyPairSpec);
    return keyPairGen.generateKeyPair();
}

Upvotes: 1

Views: 1178

Answers (0)

Related Questions