Candid’s brain

If you don’t want to read all this, jump down to the solution.

When you create a client certificate with CAcert, the workflow is as follows (if I understand it correctly):

  1. On the CAcert website, you click the button to generate a client certificate
  2. The browser (usually Firefox) generates a private key and sends a Certificate Signing Request for that key to the CAcert website
  3. CAcert signs the key and stores the signed public key on its website
  4. By clicking the link to the signed certificate, the browser imports the signature and associates it with the private key

As CAcert does not have access to your private key – only your browser has –, you cannot just download your private key from the CAcert website and import it into your e-mail client. Instead, you have to export it from your browser and import it to your e-mail program then.

In my case, I used Firefox to generate the client certificate, and I want to use it in KMail. KMail uses Kleopatra as an encryption back-end, which then uses gpgsm, a tool to manage X.509 (SSL) certificates that is part of GnuPG. Exporting the certificate in Firefox is easy, but that generates a PKCS #12 file, which in my case was not that comfortable to import into gpgsm.

My attempts

The solution linked in the CAcert Wiki suggests to import the PKCS #12 file somewhere in the settings dialogue of Konqueror. In my case (KDE 4.8.3), that menu entry does not seem to exist in Konqueror anymore, so this solution does not work.

I then tried to import the certificate using the “Import” function of Kleopatra. That presented me the following error message:

An error occurred while trying to import the certificate /tmp/cert.p12:

Decryption failed

So I tried to import the certificate directly using gpgsm --import cert.p12. Apparently, something does not work there with asking the password that the PKCS #12 file is encrypted with, this is the output:

gpgsm: gpgsm: GPG_TTY has not been set - using maybe bogus default
gpgsm: gpg-protect-tool: error while asking for the passphrase: End of file
gpgsm: error running `/usr/libexec/gpg-protect-tool': exit status 2
gpgsm: total number processed: 0

I then found out how to convert a PKCS #12 file to a X.509 private key file on this page: openssl pkcs12 -in cert.p12 -out cert.pem -nodes. That generates an X.509 file that contains the private and public key, and the public key of the CA (by adding the -nocerts options, only the private key is exported, but that doesn’t fix the following problem). On trying to import that file (gpgsm --import cert.pem), I received the following output:

gpgsm: no issuer found in certificate
gpgsm: basic certificate checks failed - not imported
gpgsm: no issuer found in certificate
gpgsm: basic certificate checks failed - not imported
gpgsm: ksba_cert_hash failed: No value
gpgsm: total number processed: 2
gpgsm:           not imported: 2

Then I came across an ancient mailing-list post that suggests to execute the following command: gpgsm --call-protect-tool --p12-import --store cert.p12. That seems to be some pretty low-level stuff that somehow calls the backend of gpgsm. A familiar error messages was produced:

gpg-protect-tool: error while asking for the passphrase: End of file

I finally found a working solution then by passing the password of the PKCS #12 file manually using the -P option, as described in the mailing-list post: gpgsm --call-protect-tool --p12-import --store -P password cert.p12. That finally did the trick. Note that this only imports the private key. In order to use the certificate for signing and encrypting e-mails, you also need the public key with the signature by the CA in your keyring. In my case that was imported when I tried to import the X.509 file above.

The solution

Execute the following two commands, where cert.p12 is the certificate file you exported in Firefox and password is the password it is encrypted with.

openssl pkcs12 -in cert.p12 | gpgsm --import
gpgsm --call-protect-tool --p12-import --store -P password cert.p12