2009-06-21-0209Z


I was playing around with openssl today, trying to connect to my server without success, and had to re-learn stuff I'd forgotten. Posting this as a reminder for myself and anyone else who tends to forget things after a few weeks, months, or years of not using them. Please forgive the switch between first and second person in the following steps; I couldn't make up my mind how to present it.

First, from Firefox's Edit | Preferences option, I selected Advanced tab, then the Encryption tag, View Certificates, Your Certificates, and selecting my own, Backup. Just entered the base name of the file, and it added a .pk7 extension.

Then you need to convert the certificate that you backed up from Firefox to the PEM format. It will prompt you for the password with which you saved it, and another password (that you choose now) for the encryption of the private key. While Firefox accepts an empty password, and openssl also does for the decryption, it requires the use of at least a 4-letter passphrase for the encryption of the private key.

openssl pkcs12 -in jcomeau_expires_20091106.p12 \
 -out jcomeau_expires_20091106.pem
openssl s_server -key unternet.key -cert unternet.crt \
 -state -Verify 2 -port 4433 >/dev/null 2>&1 &
openssl s_client -connect localhost:4433 -cert \
 jcomeau_expires_20091106.pem -pass pass:test

I got the error:

error setting private key
4246:error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch:x509_cmp.c:399:

Not very informative. Did some searching on the net, and found a number of reasons for the error, but none that could be deduced from just this one error line. So now, I copied my cert file into 3 different files: a key file, a cert file, and a "chain" file, which has the upstream certs needed to verify the client certificate. Then I edited the 3 files. The private key is first in the file, followed by the two (or more) certs in the chain, and the last cert was my own. After editing yours, make sure each file contains only what should be there.

Now I tried again:

openssl s_server -key unternet.key -cert unternet.crt \
 -state -Verify 2 -port 4433 >/dev/null 2>&1 &
openssl s_client -connect localhost:4433 \
 -cert jcomeau_expires_20091106_cert.pem \
 -key jcomeau_expires_20091106_key.pem \
 -CAfile jcomeau_expires_20091106_chain.pem \
 -pass pass:test 2>&1 | grep 'verify error'

shows the errors: verify error:num=20:unable to get local issuer certificate
verify error:num=27:certificate not trusted
verify error:num=21:unable to verify the first certificate

So I figured you have to, as with the Apache configuration directives SSLCertificateChainFile and SSLCACertificatePath respectively, specify the file containing the server certificate's upstream chain, as -CAfile; and the directory containing the upstream certs of the client certs you're willing to accept, as -CApath:

openssl s_server -key unternet.key -cert unternet.crt \
 -state -Verify 2 -port 4433 \
 -CApath www/www/client_certs_verification \
 -CAfile ipscabundle.pem >/dev/null 2>&1 &
openssl s_client -connect localhost:4433 \
 -cert jcomeau_expires_20091106_cert.pem \
 -key jcomeau_expires_20091106_key.pem \
 -CAfile jcomeau_expires_20091106_chain.pem \
 -pass pass:test

Now it works: Verify return code: 0 (ok)

After each try above, kill the server: killall -KILL openssl

Hope I didn't leave anything out.

Back to blog or home page

last updated 2009-06-20 22:21:37. served from tektonic.jcomeau.com