StartSSL code signing certificate

Today I want to explain how to get the StartSSL code-signing certificates into a state that is usable for signtool. It is an affordable solution for individuals that would rather sign the code they publish. I bought one this week and will probably rebuild some of my code and then sign it and leave other really old code completely alone, though.

The current price is 59 USD, but it is being charged for the validation of your identity, not the certificate itself as far as I understand. There are plenty of explanations on how to do everything within the StartSSL control panel, but I’d like to explain how to do it “correctly”.

Because even though you trust them – otherwise you wouldn’t have them sign your certificate – you shouldn’t ever give them the means to decrypt your private key. But this is exactly what’s being asked of you if you choose the “easy” route.

It’s assumed that you did a class 2 or 3 validation with them before following these steps. Note that these steps are generally also valid for other issuers, not just StartSSL. For other issuers you would just use a different time stamp service in the signtool command line (or rather you might want to use a different one, it’s not mandatory).

  1. Create a certificate signing request (CSR) and a key with OpenSSL. You can also use an existing key, such as your PGP key, as long as you convert it into the proper format.
    openssl req -new -newkey rsa:4096 -keyout key.pem -out csr.pem
    It is absolutely fine if you accept the defaults OpenSSL gives you. The reason for this is that StartSSL will only use the public key from your CSR along with the identity information from the validation step. They include: E (email), CN (common name, would be your name), L (location), S (state) und C (country).
  2. Under “Object Code Signing” in the second tab on the StartSSL control panel you paste the CSR and then submit it.
  3. At the end of the previous step you receive the certificate in a text field, which you save into a text file under some name. We will assume the file name cert.crt for subsequent steps.
  4. Now use the tool cert2spc.exe from the Windows SDK to convert the certificate to SPC format:
    cert2spc.exe cert.crt cert.spc
  5. Now one uses pvktool to convert the private key generated in step one (or pre-existing) into PVK format. Newer versions of OpenSSL supposedly include the functionality to achieve exactly the same, but I was too lazy to sift through the complete docs. To build pvktool I had to append -ldl to the gcc command line in the make file. Otherwise I got a linker error with OpenSSL 1.0.0d.
    pvk -in key.pem -topvk -strong -out key.pvk
  6. It’s now time to merge the private key and the certificate into a PFX file. This file contains thus both, the key and the certificate. It’s what can be used to sign your binaries. We use pvk2pfx.exe from the Windows SDK to do the conversion step:
    pvk2pfx.exe -spc cert.spc -pvk key.pvk -pfx cert.pfx
    NB: many consider this sufficient, but it is way more convenient and arguably more secure to store the certificate in the machine’s or the user’s certificate store. Follow the next step.
  7. To import the certificate in PFX format into the certificate store of either the user account or the machine, use either of these methods:
    • User’s certificate store:
      certutil -user -importPFX cert.pfx
    • Machine’s certificate store:
      certutil -importPFX cert.pfx

From this point on you can conveniently use the certificate. Note that the last step is mandatory for the case where you have to sign kernel mode code for Vista or newer (i.e. according to the kernel mode signing policy).

If it was installed in the machine’s certificate store one uses the /sm switch:
signtool.exe sign /v /a /sm /ph /d "..." /du "http://..." /tr http://... my.exe

If it was installed in the user’s certificate store simply leave the /sm switch off:
signtool.exe sign /v /a /ph /d "..." /du "http://..." /tr http://... my.exe

Now the short explanation for the used command line switches:

  • /v means verbose and is not strictly needed. It’s useful for the first invocation when you want to see which certificate was ultimately chosen (see next bullet point).
  • /a automatically selects the certificate that is valid the longest and that can be used for code signing. In most cases only one certificate will be installed on the machine anyway.
  • /ph computes hashes over each section of the binary file (more secure but not strictly necessary).
  • /d adds a description.
  • /du adds a URL.
  • /t or /tr is the URL of a time stamp service. This part is very very important. The reason being that without this the signature of a file will expire unless the signature is time stamped. Once time stamped, the signature will remain valid even beyond the expiry date of the certificate.
  • /ac has to be used for kernel mode drivers to include issuer intermediate and root certificates in the signature.
    The choice of /t versus /tr depends on the timestamp service running at the URL you are using (were given)
  • /i, /n and /r can be used to select the right certificate in case more than one is installed.

Timestamp URLs which can be used:

  • http://timestamp.verisign.com/scripts/timstamp.dll works with /t (Note: no ‘e’ in timstamp.dll)
  • http://timestamp.globalsign.com/scripts/timestamp.dll works with /t
  • http://www.startssl.com/timestamp works with /tr

Hope it’s helpful for someone else.

// Oliver

This entry was posted in EN, IT Security, Programming, Software and tagged , , , , , , . Bookmark the permalink.

6 Responses to StartSSL code signing certificate

  1. airmax says:

    Useful article, but i prefer to not import certificate in local store. Just using *.pfx files (important if need to sign different binaries with different certificates).
    Regarding kernel mode signing:
    1. Certificate issuer must have cross-certificate from Microsoft.
    2. To verify kernel-mode embedded signature:
    signtool.exe verify /kp /v DriverPath

  2. Oliver says:

    Yep, point 1 I mentioned (see the /ac switch), but point 2 is a very good point. I haven’t bought a certificate suitable for signing kernel mode code for myself, but I am using this, including the verification, in the build process at work. Tell me, how did you even get it to work with PFX files for signing kernel mode code? This worked fine for XP, I know. But with /ac I never was able to use a PFX file, only a locally stored cert. Besides, I consider it slightly more secure than having the PFX file sitting somewhere in the file system.

  3. Oliver says:

    Спасибо ;)

    Had tried that, but it didn’t work for me even with that switch. I’ll try again on Monday, though. Just to see.

  4. Alexey says:

    no need in other than OpenSSL tools. You can convert CRT into PFX using this command line:

    openssl pkcs12 -export -out “cert.pfx” -inkey cert.key -in cert.crt

    I found it in this topic: https://forum.startcom.org/viewtopic.php?p=7091&sid=7b97b298c28a1f4353e8f9e78cc182ae

  5. Oliver says:

    Alexey, I know you are right. However, to my knowledge this was only introduced fairly recently into OpenSSL. So for people who don’t want to (or can’t) compile OpenSSL from source themselves, this is a rather bumpy road to take.

    Nevertheless, you’re of course right.

    Thanks for your comment :)

Comments are closed.