One of my recent tasks involves applying for a "Compatible with Windows 7" logo from Microsoft for one of our software products via The Windows 7 Software Logo program. One of the requirements of the program is that we need to code sign all executable files (exe, dll, ocx, sys, drv, src, msi) in an application with an authenticode or code signing certificate. The reason for this is that a user of our application can then be sure that the executables are indeed published by us and they are not altered in any way after publication. In addition, if we code sign a Windows installer package (.msi), Windows User Account Control (UAC) will be able to show our signature to the user before it gets installed. This gives him certain level of confidence in our product. This blog post by Jeff Wilcox shows detailed information about how to purchase a code signing certificate from a CA (certificate authority) and how to sign an executable with the certificate using the utility program signtool.exe. Now let's say we will develop our Windows application with Visual Studio, our application will consist of more than one executable, e.g. typically an exe and one or more dlls, and we would like to distribute our application via a Windows installer package. It is under this context that I will discuss how to digitally sign all executables in a Visual Studio solution that includes a Setup project.
Before I go over the details, here are some related notes:
If your intent is to get "Compatible with Windows 7" logo for your application like I do, you must get a code signing certificate from VeriSign because that's the only brand recognized when you submit your self-test result to Microsoft. Unfortunately, this means you are likely to pay more than getting it from other vendors, such as K Software or Comodo mentioned in Jeff's post.
The Signing tab under a Visual Studio project's Properties page allows you to sign ClickOnce manifests, as well as to perform strong-name signing on assemblies. However, it has nothing to do with signing the executables of an application.
When you purchase a code signing certificate from a CA, the certificate will be delivered directly to the certificate store on your machine. You can view or manage all certificates in the certificate store by clicking the Start button and typing certmgr.msc. The following screenshot shows the certificates I have on my Vista machine.
You can view a certificate's details by double clicking a certificate in the right pane (above). The Certificate dialog box will be shown (such as below).
You can check if an executable is digitally signed or not by right clicking it and selecting Properties. If it is digitally signed, you should see a Digital Signatures tab, as shown below.
Sample VS Solution
The discussion in the rest of the post is based on the following Visual Studio sample solution:
The sample solution consists of three projects, a main Windows application TestCodeSign, a class library TestCodeSignDll and a Setup project TestCodeSignSetup. The Setup project consists of the primary output from the main application, which references the class library. Note that we have set proper values for the following properties of the Setup project: Author, Manufacturer, ProductName and Title. When we build the sample solution, we get TestCodeSign.exe and TestCodeSignDll.dll. When we build the Setup project, we get setup.exe (bootstrapper) and TestCodeSignSetup.msi. These four executables are what we are interested in signing digitally with a code signing certificate.
Signing the Executables
Here are the steps:
- Build the solution in either Debug or Release mode (assume Debug mode in this example).
- Open a Visual Studio Command Prompt.
- Launch Digital Signature Wizard by typing this command: signtool.exe signwizard
- Select an executable to sign, e.g. TestCodeSign.exe from the TestCodeSign project's obj folder instead of the bin folder (see the folder structure below). This is because when you build the Setup project later on, the executable in the obj folder is copied to the bin folder and grabbed from the bin folder to the installer package.
- Select the code signing certificate to use from the certificate store.
- Provide a description for the executable.
- Specify timestamp service URL. For VeriSign certificate the URL is http://timestamp.verisign.com/scripts/timstamp.dll
- Complete the Digital Signature Wizard.
- Repeat steps 3 - 8 for TestCodeSignDll.dll.
- Now Build the Setup project to generate setup.exe and TestCodeSignSetup.msi (see the screenshot below for their location). Note: DO NOT Rebuild, or the exe and dll you have just signed will be overwritten.
- Repeat steps 3 - 8 to sign setup.exe.
- Repeat steps 3 - 8 to sign TestCodeSignSetup.msi.
Test It Out
Now that we have signed all the executables in our application, it's time to test it out. Double click setup.exe or TestCodeSignSetup.msi to launch the Installation Wizard. The wizard will go through these steps: Select Installation Folder -> Confirm Installation -> Installing TestCodeSign -> Installation Complete. Between Confirm Installtion and Installing TestCodeSign UAC will show the following message with our signature:
This proves that the signing of the installer package is working.
Now with Windows Explorer browse to the application's installation folder C:\Program Files\Manufacturer\ProductName or C:\Program Files\Pharos\TestCodeSign in our case, and we will find the two executables installed, TestCodeSign.exe and TestCodeSignDll.dll (see below).
Check the Properties page of any of the two files and we will see the Digital Signatures tab.
Finally, if we try to uninstall the TestCodeSign application from the Control Panel -> Programs, we should see a UAC message with our signature asking us if it's ok to run the uninstaller. This works fine for Windows 7. However, it is not the case for Windows Vista and Windows Server 2008; we will get a message showing "unidentified publisher". This issue/bug has been confirmed by Microsoft and documented widely on the web such as in Aaron Stebner's WebLog.