Monday, July 13, 2015

Signing ClickOnce WPF application

So let's say you have a WPF application that you want to distribute using ClickOnce. Like I am doing with my Visual Task Map.

If you want your users to download and run your application without going through multiple scary red dialog windows with warnings, you need to sing it.

A lot of information on this topic is scattered all over the web. Microsoft has a good set of articles about it. There are bunch of answered questions on Stack Overflow. But sometimes you just want the short version. So here it is.


  1. To sing any code you need to buy a code signing certificate
  2. Update project settings to sign and timestamp the ClickOnce manifest.
  3. Add a BeforePublish target into your project to sign the executable before it becomes part of the ClickOnce package.
I am using Comodo timestamping server - http://timestamp.comodoca.com/authenticode, but there are plenty of other servers to chose from. For example you can use this one: http://timestamp.verisign.com/scripts/timstamp.dll. It does not make any difference, any timestamping server will work.

Signing the manifest is simple as you just go o the project properties, Signing tab, and use your certificate (the one that you just bought, the one that has the private key) to sign the manifest. That is also where you can specify the timestamping server that will be used to timestamp the manifest.

You might also assume that signing the executable is as easy as signing the manifest because there is one more checkbox in the same dialog that says "Sign the assembly". You would be wrong. This is where you provide a certificate, used to create a Strong Name for your assembly, and your awesome new certificate won't work. Also, you don;t actually care about the strong-naming your executable. This is a good article about the difference between what VS does and what you need.

So how do you sing the executable ? There are no easy project options that will allow you to do that. And when you are dealing with ClickOnce, it all becomes a bit more complicated as ClickOnce sources binaries from the Obj folder, not the usual Bin folder, and the executable in the Obj folder has to be signed precisely at the right time: after it was actually built, but before the ClickOnce publishing mechanism has picked it up.

You can read more details about this here, and then here.
But the short version is that you need to add a call to singtool.exe into your project file. Something like this:
<Target Name="BeforePublish" Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
  <Exec Command=""C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" sign /n "My Name" /t http://timestamp.comodoca.com/authenticode $(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)" />
</Target>

One important thing to remember is that the BeforePublish action works incorrectly with WPF applications in VS2013 RTM (and AfterCompile option did not work for me either). But this problem has been resolved in VS2013 Update 4 - be sure to install it.

Where to get a code signing certificate

Recently I wanted to sign some code and I had to find and buy a certificate for that purpose.

Short version of the story: I got this one. It was frustrating and cheap. Had to notarize a personal statement, provide a photocopy of driver license, credit card and a utility bill. Also had to publish all my personal contact info on manta.com.

Now, the long version.

First of all, not all certificates are equal - it has to be a code signing certificate (or at least it has to include that capability).

But the majority of code signing certificates are the same. I found an interesting article on this topic.

I compared VeriSign, Thawte, Comodo, K-Software and StartSSL.

First two are crazy expensive and can/should only be used by enterprises that have extra money, so I decided to ignore them from the very beginning. Prices are above 300$

Comodo and K-Software are both selling same certificates (issues by Comodo), but K-Software offers them at lower price. This is the option that I ended up going with.

The last one is StartSSL. The price is very low (59$ for 2 years for the individual certificate). But they do not support time stamping, which means that once your certificate expires your code is no longer signed. (So all of sudden your users start getting errors and warnings and would be forced to contact support or just download the latest version).

About the actual process. K-Software side of the deal is very straightforward and it is very nice dealing with their support. Really nice and helpful.

But once you start to deal with the Comodo side of the deal, it feels like some parallel universe where nothing makes sense. From my conversations it looks like all of their staff is in India and their call center is in India. Those guys are trying their best to work with you, but they still fail.

To get a certificate you have to be authenticated as future owner of the certificate. This means that you will be asked to provide a government-issued photo ID (Driver License), a document that ties you to your home address (for example, a utility bill), and a document that ties you to a financial institution. (Credit card or bank statement). They ask you to fill in an notarize a personal statement about you being you and living where you said you are. This was easy, as any UPS store has a notary in it and it costs around 10$ to notarize that one statement.

The email from Comodo says that you must mail the papers overnight to them - that's extra 50-60$ right there. But a quick call to their support has revealed that it is not necessary - just scan the papers and submit online.

The most frustrating part about that process is that they must find your phone number online in one of the public databases, like www.whitepages.com or www.manta.com. If you own a company, then it's not a big deal - the phone number and the address of  your company are both public. But when you are an individual software engineer you do not want your contact information in the public directories.

Unfortunately there was no way to work around this requirement - I had to publish my info on manta.com, they took a phone number from there, a machine called me on that number and gave me some verification code.

After that you get your certificate. It will be installed straight into the certificate store on your machine, so don't be surprised when the final page just says "Success" and nothing else happens. Just export the certificate from the certificates store and you'll have your file.