1

When I use the openssl command to create a certificate, it has the option to secure the private key with a password. However, when I programmatically create a certificate and public/private key pair in Java, the Java API only has a way to set a password on the keystone but not on the private key (unlike the openssl command). So is there no way to encrypt the private key with a password like in the openssl command?

If it helps, here's how I'm creating the private key and certificate in Java:

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    X509CertInfo info = new X509CertInfo();
    CertificateValidity validityInterval = generateValidityInterval();
    BigInteger serialNumber = new BigInteger(SERIAL_NUMBER_SIZE, new SecureRandom());
    X500Name owner = new X500Name(DN);

    info.set(X509CertInfo.VALIDITY, validityInterval);
    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber));
    info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
    info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
    info.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic()));
    info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
    AlgorithmId certificateAlgorithm = new AlgorithmId(CERTIFICATE_ALGORITHM);
    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(certificateAlgorithm));

    X509CertImpl certificate = new X509CertImpl(info);
    certificate.sign(keyPair.getPrivate(), new AlgorithmId(SIGNATURE_ALGORITHM).getName());

    AlgorithmId x509Algorithm = (AlgorithmId) certificate.get(X509CertImpl.SIG_ALG);
    info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, x509Algorithm);
    certificate = new X509CertImpl(info);
    certificate.sign(keyPair.getPrivate(), new AlgorithmId(SIGNATURE_ALGORITHM).getName());
Glide
  • 20,235
  • 26
  • 86
  • 135
  • 2
    See [KeyStore.setEntry()](http://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html#setEntry(java.lang.String,%20java.security.KeyStore.Entry,%20java.security.KeyStore.ProtectionParameter)) – user207421 Jul 30 '14 at 00:11
  • *"So is there no way to encrypt the private key with a password like in the openssl command..."* - you need to be careful here. OpenSSL can encrypt the key using PEM Message Encryption of RFC 1421. Its an old format, and OpenSSL uses it by default. Unfortunately, OpenSSL uses a non standard derivation function when the key size is larger than 16 bytes. So Java *may* not be able to decrypt the key. With the `pkcs8` utility, you can strip the old format encryption and apply PKCS8 encryption to the key. Java should be able to decrypt the PKCS8 encrypted key. – jww Jul 30 '14 at 00:23
  • 2
    `X509CertInfo`? `X509CertImpl`? This code uses unsupported internal classes that nobody should *ever* use. – President James K. Polk Jul 30 '14 at 01:36
  • @GregS Thanks for the feedback. Could you elaborate a bit on why those internal classes shouldn't be used? This may not be most reliable source, but the classes are used in this [tutorial](http://www.java2s.com/Tutorial/Java/0490__Security/CreatingaCertificateinJava.htm) – Glide Jul 30 '14 at 05:13
  • 1
    Anything that begins with `sun.*` or `com.sun.*` is a no-no. See this question: http://stackoverflow.com/questions/1834826/it-is-a-bad-practice-to-use-suns-proprietary-java-classes – ntoskrnl Jul 30 '14 at 10:49

0 Answers0