Certificate signing isn’t a perfect answer for untrusted code, but it does give the user another indication that your Add-In will do what it says on the tin. More importantly, not signing your code when the installer framework expects a certificate isn’t a great way to make a first impression.
Previously, we talked about automating builds of our Add-In’s installers and the parent *.wssx add-in package file, and my strategy for automatically building packages that support in-place upgrades.
Now we’re going to talk about signing our *.wssx package with a certificate, specifically a self-signed certificate for testing purposes.
Code signing certificates are usually more expensive than standard SSL certificates. While an SSL certificate authenticates a single web server (probably), a code signing certificate states that a specific piece of software was built by your company and hasn’t (probably) changed since it was built.
The difference in cost is that (theoretically) your company must be authenticated by the certificate issuer before they give you a certificate (by checking company registration records etc.).
Code signing certificates are valuable to malware authors – if they can get hold of a code signing certificate and private key for your company, they can write software that pretends it was written by you. Not great for your business' image if that happens (and it has, to some high-profile companies).
So, code signing certificates are more expensive than SSL certificates and should have their private keys protected against theft. What’s a self-signed certificate, then?
You can generate your own certificates and private keys using a variety of tools, and use them however you want. These are “self-signed” certificates, because they’re not signed by a trusted 3rd-party issuer (like VeriSign et al.).
Self-signed certificates are great for testing certificate signing processes, signing development code, and allowing automated builds that aren’t dependent on one person entering the secret private key for your expensive code signing certificate.
The only down side is that no one trusts your self-signed certificate, so you tend to generate the same sorts of errors as unsigned code because the issuer of the certificate (your development machine) isn’t trusted by anyone else.
That’s not a major issue for internal testing as you can make other computers trust your certificate (which we’ll talk about later). External testers can also trust your self-signed development certificate, or ignore the certificate error.
Creating a self-signed certificate
Visual Studio has all the tools you need to create and use a self-signed certificate.
I’m going to describe the command line method here, using Visual Studio tools. This method creates a self-signed Certificate Authority (CA) certificate that you can import into the certificate store on other computers so that they trust your self-signed certificate.
Using this method is a good idea if you need/want to create multiple code signing certificates; you won’t have to manually import each certificate because your target machines just need to trust your root CA certificate.
Credit goes to Roger Lipscombe on StackOverflow for these steps.
Start by opening Visual Studio Command Prompt (which opens in the right directory, and gives us the path variables that make things easier) or open Command Prompt and navigate to C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC (or wherever you’ve installed Visual Studio).
In the instructions below, substitute “Tentacle Software” for your own company or name.
Create your self-signed CA
Run the following command (it’s all one line, so watch out for line breaks) to create your CA certificate and private key file. Your self-signed code signing certificates will use this CA certificate as their root.
makecert -r -pe -n "CN=Tentacle Software CA" -ss CA -sr CurrentUser -a sha1 -sky signature -sv TentacleSoftwareCA.pvk TentacleSoftwareCA.cer
Note the *.pvk and *.cer file names; you probably want to give them a path (otherwise they’ll get created in the current working directory).
You’ll be prompted twice for a password for the private key. Use the same password for both prompts, and make sure it’s one you can remember.
Now we can import our CA certificate into our own certificate store so that we trust it.
certutil -user -addstore Root TentacleSoftwareCA.cer
Note the *.cer file name; make sure you’re using your own file name and not mine!
You’ll be prompted to accept the certificate, and you’ll receive a detailed warning about why accepting a CA that can’t be verified is a bad idea. They’re right, it is a bad idea! Unless you’ve created the CA yourself, of course.
Each time you create a code signing certificate, you’ll be using the CA *.cer and *.pvk files. So keep them safe.
Create your first self-signed code signing certificate
Using our new CA, we’ll create a code signing certificate we can actually use. We pass in the CA certificate and private key file as variables, and we output a *.cer and *.pvk for our code signing certificate.
A code signing certificate is referred to as a Software Publisher Certificate (SPC), which you’ll see in my example file names below.
makecert -pe -n "CN=Tentacle Software SPC" -a sha1 -sky signature -ic TentacleSoftwareCA.cer -iv TentacleSoftwareCA.pvk -sv TentacleSoftwareSPC.pvk TentacleSoftwareSPC.cer
Again, note the file names for our CA certificate and private key file. Make sure to use your own file names.
You’ll be prompted twice for the private key password for our new private key file, just as we were when we created the CA. If you’re feeling particularly security conscious, use a different password from the CA *.pvk.
You’ll also be prompted for the password to the CA *.pvk file, so our CA can officially sign our new certificate.
Now we want to convert our *.cer and *.pvk combo into a *.pfx file, which Visual Studio can use to sign our code.
pvk2pfx -pvk TentacleSoftwareSPC.pvk -spc TentacleSoftwareSPC.cer -pfx Key.pfx -po P@ssw0rd
We’ve got another password here, specified by the -po switch; you’ll enter this in Visual Studio when signing. Use something slightly more secure than I have here.
You’ll be prompted to enter the private key password of your SPC private key file, and Key.pfx is the final output file that we’ll add to our Visual Studio project.
Signing a *.wssx file
Our Windows Server Solutions Add-In Package Project Type (*.wssx) for Visual Studio 2010 supports post-build package signing, so we’ll make use of that functionality.
If you’re not using our *.wssx project type, you’ll need to play around with some post-build steps in MS Build, which I won’t cover here; we’re just running signtool with the appropriate switches.
Add Key.pfx to the package project
The first step is to add our final Key.pfx file to our project.
You can copy and paste Key.pfx from Windows Explorer into the project in Visual Studio, or right-click the package project and choose Add –> Existing Item.
Configuring signing in Debug builds
Our *.wssx project type supports different code signing properties per build configuration. This is great because it means you can use your self-signed certificate for Debug builds and your real SPC for Release builds.
To configure signing options, right-click the package project, choose Properties, and change to the Signing tab.
Make sure you’re in Debug configuration, set “Sign the package” to true and choose your certificate file from the drop-down list.
Because we set a password on our *.pfx earlier, we need to enter an additional signing option (“/p P@ssw0rd”) to tell signtool to use our password.
Now whenever we build our package in Debug mode, it will be automatically signed with our self-signed *.pfx Software Publisher Certificate.
Our *wssx project type also verifies the signature after signing, so that you can be sure the certificate signing process completed successfully.
Trusting a self-signed certificate
So, what does our self-signed package look like now when we install it?
Pretty much the same.
In order for the Windows Server Solutions package framework to trust our self-signed certificate, it needs to trust our imaginary Certificate Authority.
Installing the CA certificate
Copy your CA certificate from your development machine to the server you’re deploying your Add-In packages to (using our example file names, that’s TentacleSoftwareCA.cer).
Double-click the certificate and you’ll be presented with the certificate’s details.
Click “Install Certificate” and step through the import wizard. You want to place the certificate into the Trusted Root Certification Authorities store.
You’ll be prompted about how much of a bad idea it is to trust random root CA certificates. We know where this one came from, so click “Yes” to install it. You’ll receive a success confirmation dialog at the end.
This server now trusts all certificates issued by our fake CA, including our new code signing certificate.
If you Add-In package deploys client binaries, those client machines will need to trust our CA too. You’ll need to repeat the above process on each client machine.
Installing a trusted *.wssx package
What happens when we install a *.wssx package that’s been signed with a certificate issued by a CA we trust?
Not much! The nasty untrusted code error isn’t shown, and we go directly to the EULA screen.
This is a much better experience for your customers; remember that your installer is the first impression you get to make regarding the quality of your software, and big red error messages about untrusted code tend to make users slightly uncomfortable.
Release mode signing
Once you’ve built your Add-In, tested it, and you’re ready for release, you’ll need to purchase a production code signing certificate from a Certificate Authority that Windows trusts by default. Costs vary wildly here, so do some research.
When you have your *.pfx file ready, you can edit the Release mode configuration for your *.wssx package project and enter the relevant details.
Depending on your company’s certificate policies, this may mean delay signing or not signing automatically at all – final package signing can be performed manually using signtool by the person who has access to the private key of your production certificate.
Now, go forth and certify!