8
votes

I have followed the steps listed here to create a new private key and certificate. Now I am trying to combine them into a .pfx file.

OpenSSL should be able to read in both the private key and the certificate from a single file, and according the man man docs, should also be able to read from stdin. However, this doesn't seem to be working for me.

On Mac OS X 10.14.3 and openssl version gives "LibreSSL 2.6.5".

I combined my certificate and key into one file (called 'combined.pem'). I did this with the following commands:

$ openssl genrsa -out private.key 2048
$ openssl req -new -x509 -key private.key -out public.cer -days 365
$ cat public.cer >> combined.pem
$ cat private.key >> combined.pem

For reference, combined.pem looks something like this:

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

When I run the following command, everything works fine:

$ openssl pkcs12 -export -out x509.pfx -in combined.pem

When I run this command, I get an error:

$ openssl pkcs12 -export -out x509.pfx < combined.pem
unable to load certificates

I have also tried:

$ cat combined.pem | openssl pkcs12 -export -out x509.pfx
unable to load certificates

What am I missing? Is OpenSSL not really able to read from stdin for this?

Also, from the man docs:

     -in file
           The input file to read from, or standard input if not specified.  The order doesn't matter but one private key and its corresponding certificate should
           be present.  If additional certificates are present, they will also be included in the PKCS#12 file.

     -inkey file
           File to read a private key from.  If not present, a private key must be present in the input file.
5

5 Answers

17
votes

Contrary to what most answers here say, OpenSSL does work with stdin out of the box, including on macOS. The trick is to leave the -in parameter out completely.

cat combined.pem | openssl pkcs12 -export -out x509.pfx
5
votes

From what I gather from this question OpenSSL indeed doesn't work with stdin out of the box. One thing you can try though is using a bit of trickery:

openssl pkcs12 -export -out x509.pfx -in /dev/stdin < combined.pem

I haven't tested your specific certificate combination case, but the /dev/stdin redirect piece should work to allow you to have "stdin-like" capabilities in OpenSSL

4
votes

I had a similar problem and, with some help from contributors over at the OpenSSL Github, managed to determine that feeding a PEM file in via stdin can work, but you must have a PEM file which contains the key before the certificate.

According to this comment, the pkcs12 command processes by opening the input, scanning for keys and reading them; then reopening the input (or seeking back to the beginning), scanning for certificates and reading those. When input is a file (e.g. via -in somefile) this reopen/seek resets the reading position to the start of the file, but when input is the stdin stream (e.g. via in -, cat |, < file or just omitting -in), reopen/seek is ignored and it carries on from where it left off (because the stdin stream is forward-only).

As such, if the input stream contains the certificate before the key, the key scan (starting at the beginning of the stream) consumes all of the stream up to the end of the key data, ignoring the certificate data; then the certificate scan (starting at the end of the key data) reaches the end of the stream before it finds any certificates, so you get the unable to load certificates result.

If the input stream contains the key before the certificate, the key scan (starting at the beginning of the stream) finds the key first, then the certificate scan (starting at the end of the key data) finds the certificate second, and everything works as it should.

This is made more irritating by the fact that OpenSSL (currently) emits its certificates before its keys in its normal output, so you can't readily pipe pkcs12 calls together.

TL;DR: Do cat private.key public.cer > combined.pem, not cat public.cer private.key > combined.pem.

3
votes

Several command-line utilities expect a dash when using standard input; openssl x509 appears to follow this (tested on Ubuntu 18.04, so I would reasonably expect this to be portable syntax).

cat combined.pem | openssl pkcs12 -export -out x509.pfx -in -
0
votes

The truth is - it depends on the exact openssl command.

For the openssl crl it was enough to omit -in param:

curl -s ${VAULT_ADDR}/v1/pki/crl 2>&1 | openssl crl -inform der -noout -text

For the openssl x509 you must supply -in - param:

curl -s ${VAULT_ADDR}/v1/pki/ca 2>&1 | openssl x509 -text -noout -nameopt multiline,show_type -in -

I guess my suggestion is to test one of these two in your particular case.