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).
- 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).
- Under “Object Code Signing” in the second tab on the StartSSL control panel you paste the CSR and then submit it.
- 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.crtfor subsequent steps.
- Now use the tool
cert2spc.exefrom the Windows SDK to convert the certificate to SPC format:
cert2spc.exe cert.crt cert.spc
- 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
gcccommand 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
- 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.exefrom 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.
- 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
- User’s certificate store:
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
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:
/vmeans 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).
/aautomatically 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.
/phcomputes hashes over each section of the binary file (more secure but not strictly necessary).
/dadds a description.
/duadds a URL.
/tris 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.
(turns out this is no longer the case, see in the comment section below)
/achas to be used for kernel mode drivers to include issuer intermediate and root certificates in the signature.
The choice of
/trdepends on the timestamp service running at the URL you are using (were given)
/rcan 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
- http://timestamp.globalsign.com/scripts/timestamp.dll works with
- http://www.startssl.com/timestamp works with
Hope it’s helpful for someone else.
- StartCom claims their extended validation certificates don’t have that issue, though. [↩]