24

I have to convert a certificate in PEM format into an Java key store.

To use this one with tomcat at a windows server

I've got those files:

  • cert_request.csr

      -----BEGIN CERTIFICATE REQUEST-----
      ...
      -----END CERTIFICATE REQUEST-----
    
  • cert_public_key.pem

      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    
  • cert_private_key.pem

      -----BEGIN ENCRYPTED PRIVATE KEY-----
      ...
      -----END ENCRYPTED PRIVATE KEY-----
    
  • cert.txt

      contains an 16 digit key
    

I tryed to combine the pem files (by combining the two files were chain together) and converted this with openssl into an

  • .der file and import that with keytool into an new keystore
  • same with .p12
  • directly imported to keystore

I also tryed to change the

    -----BEGIN ENCRYPTED PRIVATE KEY-----
    ...
    -----END ENCRYPTED PRIVATE KEY-----

into

    -----BEGIN RSA PRIVATE KEY-----
    ...
    -----END RSA PRIVATE KEY-----

and tryed the 3 ways above

what have I to do that I get an working certificate?

EDIT:

I combinied the cert_public_key.pem and the cert_private_key.pem to cert_comb.pem

    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    ...
    -----END ENCRYPTED PRIVATE KEY-----
Lii
  • 11,553
  • 8
  • 64
  • 88
Narf
  • 243
  • 1
  • 2
  • 7
  • This guide on jamielinux.com has a lot of answers on how to generate a keypair, how to generate a certificate, how to generate a CSR, how to sign a CSR using a certificate; afterwards you can either use keytool to merge them or you can use Portecle which has a GUI for it. https://jamielinux.com/docs/openssl-certificate-authority/introduction.html – EpicPandaForce Feb 03 '16 at 11:27

2 Answers2

47

You aren't clear which files you combined, but it should work to use openssl to combine the cert and private key to a PKCS#12:

cat cert_public_key.pem cert_private_key.pem >combined.pem
openssl pkcs12 -export -in combined.pem -out cert.p12

or on the fly but (update:) the privatekey must be first:

cat cert_private_key.pem cert_public_key.pem | openssl pkcs12 -export -out cert.p12 

If your cert needs any chain cert(s) -- the CA should have told you this when you submitted the CSR and they issued the cert -- it's easiest to also include it(them) now.

Then (1) some Java programs can actually use a pkcs12 directly as a keystore, but (2) if you need or prefer a JKS use keytool:

keytool -importkeystore -srckeystore cert.p12 -srcstoretype pkcs12 -destkeystore cert.jks 

If you care about the alias in the resulting JKS, easiest to fix it after converting.

Also: just changing the labels in an encrypted PEM doesn't unencrypt it, nor does changing the label from generic PKCS#8 to RSA actually change the data to match (and they are different, though only a little). If you do want a separate PEM file with the decrypted private key:

openssl pkey -in encryptedpk8 -out clearpk8.pem # 1.0.0 up
openssl pkcs8 -in encryptedpk8 -out clearpk8.pem # 1.0.0 up 
openssl pkcs8 -topk8 -nocrypt -in encryptedpk8 -out clearpk8.pem # below 1.0.0
openssl rsa -in encryptedpk8 -out clearrsa.pem
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • I combinied the cert_public_key.pem and the cert_private_key.pem to cert_comb.pem, i edited the post above – Narf Mar 10 '14 at 12:41
  • and i have to use windows, so i didn't copyed this with cat. I copyed it manually in an texteditor (notepad++) – Narf Mar 10 '14 at 12:44
  • i tryed to combine the two .pem files and do the command "pkcs12 -export -out C:/path/cert.p12 -in C:/path/cert_comb.pem" but I get the Error: "unable to write 'random state' " – Narf Mar 10 '14 at 15:19
  • Yes, openssl on Windows often gives that error after completing the requested operation, so in almost all cases you can ignore it. If you want to fix, see http://stackoverflow.com/questions/12507277/how-to-fix-unable-to-write-random-state-in-openssl http://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean – dave_thompson_085 Mar 10 '14 at 21:45
  • Hi, is there anyway to convert PEM to PKCS12(or JKS) without using openssl? – Zippon Nov 13 '17 at 08:23
  • @Zippon: StackOverflow (and StackExchange) policy is not to ask (or answer) questions in comments, which frequently get deleted. However: if you mean PEM containing privatekey and certificate(s) (which is nowhere near all PEM files) and you have Java (implied by JKS) and BouncyCastle (not implied) see https://stackoverflow.com/q/22963581/ https://stackoverflow.com/q/1580012 https://stackoverflow.com/q/6482484/ https://security.stackexchange.com/q/9600/ then store with JCA. Otherwise you can code the same algorithms yourself but that will require research and a proper question. – dave_thompson_085 Nov 14 '17 at 02:26
  • how I can convert my sslcertification.pem file that contains a certification and private key together to keystore? – Arash Jan 21 '19 at 07:55
  • 1
    @Arash: assuming you mean a certificate (certification is not a standard term) and privatekey in PEM format in one file, that's exactly the case already covered in the first part of my answer. (Note the OP on this Q used the name 'cert_public_key' for a certificate.) (Also note today unlike 2014 all supported versions of Java default to PKCS12 keystore.) – dave_thompson_085 Jan 22 '19 at 04:12
  • openssl pkcs12 -export -in combined.pem -out cert.p12 this command on windows hangs as if waiting for an input. tried all the mouse moving and key typing but to no avail – veritas Nov 12 '21 at 16:12
  • @veritas: assuming you answered the password prompts, it shouldn't 'hang'. Mouse is irrelevant to a program like OpenSSL; did you try control-C? Are you running directly on Windows, and built how (or by whom), or on something layered on Windows like mingw (or 'git-bash' which is really mingw64) or cygwin or wsl (and which guest)? Are you using console, WinTerm, whatever mingw and cygwin are using now, some kind of xterm, putty or similar, or what? Or a VM (and which kind, with what kind of terminal)? – dave_thompson_085 Nov 13 '21 at 00:34
  • @dave_thompson_085 thanks. it worked after I added winpty before openssl command on windows – veritas Nov 13 '21 at 11:47
1

First question: you only have a certificate request? Not an actual certificate? It needs to be signed, you can self-sign it or have it signed by an external party.

If you have the actual cert you can use this to parse the private key file and the cert file:

// parse the private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // might not be RSA
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(byteArray);
PrivateKey privateKey = keyFactory.generatePrivate(spec);

// parse cert
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate cert = factory.generateCertificate(certInputStream);

// add it to the keystore
store.setKeyEntry(alias, privateKey, password, new X509Certificate[] { cert });

UPDATE

As far as I know the command line keytool does not support any advanced options like signing a csr. Even standard java does not support this, you need an external library like bouncy castle. This is not easy. E.g:

JcaPKCS10CertificationRequest pkcs10 = new JcaPKCS10CertificationRequest(csrBytes);
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
        issuer,
        generateSerialId(),
        new Date(),
        until,
        subject,
        pkcs10.getPublicKey()
);

X509CertificateHolder holder = builder.build(getContentSigner(privateKey, type));
X509Certificate cert = getCertificate(holder);

...

ContentSigner getContentSigner(PrivateKey privateKey) {
    AsymmetricKeyParameter keyParameter = PrivateKeyFactory.createKey(privateKey.getEncoded());
    AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WITHRSA"); // or what you want
    AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
    return new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(keyParameter);
}
nablex
  • 4,635
  • 4
  • 36
  • 51
  • I have 4 files, an cert_request.csr, cert_public_key.pem, cert_private_key.pem, and cert.txt. – Narf Mar 10 '14 at 10:19
  • The cert.txt is only 16 digits, not sure what this contains, an id? The public key is not important here. The csr (certificate signing request) has to be signed by someone to generate a cert. The cert and the private key go together into the keystore. The csr can be ignored after it has been signed. – nablex Mar 10 '14 at 10:24
  • ok insofar understood, but how? i'm searching for an commandline expression – Narf Mar 10 '14 at 10:38
  • how should I run this code? please Help me. I have a sslcertification.pem file that contains a certification and private key together that i want to convert to java keystore format? – Arash Jan 21 '19 at 07:58
  • The data in the Q clearly showed that 'cert_public_key.pem' was actually a cert. Although not applicable here, `keytool -gencert` can create a cert from a CSR (which is NOT done by signing the CSR, although lots of people and sites wrongly claim that) since Java 7 in 2011. – dave_thompson_085 Mar 10 '21 at 08:24