Code Signing: two worlds defined
I’ve always been a fan of code signing. There’s “signing” to give the assembly a strong assembly name, and there’s “signing” to verify the application hasn’t been tampered with. (It irks me that they’re named the same.) It finally gelled in my head the difference between the two. For my own reference, and for the benefit of others, here is a description of each:
Strong Name
Reason: This is necessary to install assemblies into the GAC and to include a library in a signed project. It is specific to managed code.
Benefits: This insures the library doesn’t conflict with other dlls. It says nothing about the origin of the file.
Technique (Visual Studio 2005):
– In the project’s properties, click on the Signing tab
– Check “Sign the assembly”
– In “Choose a strong name key file” choose New to generate a .snk file
– For other projects using the same .snk file, choose Browse in this dialog, and find the .snk file created previously
I like to use the same .snk file for all projects in a solution. When choosing Browse, it copies the .snk file. I additionally do this:
– Close the solution
– Move the .snk file to a central location, and delete the copies
– Open the project files in my text editor of choice
– Locate the .snk file reference, and modify the path accordingly
– Open the solution and rebuild
Technique (Visual Studio 2003):
– Use sn.exe from a Visual Studio Command Prompt to generate a .snk file ( or use VS 2005 :) )
– In the Assembly Info file in each project, add the path to the .snk file
Gotchas:
– This .snk file should be kept in secret. You can create a public key file using sn.exe worthy of distribution.
– If this is an absolute path into C:Documents and SettingsUserMy DocumentsVisual Studio 2005Projects… and you check this file into source control, your team won’t like you. Please use relative paths.
– VS 2003 only: the compiled code is signed from inside the build directory (e.g. /bin/Debug), so relative references need to start there. I often found I’d have a bunch of “……….” in my key paths.
– VS 2005 only: the snk file is referenced from the project directory, so relative paths need to start there.
References:
– Demanding a strong name in a library
Verify Origin
Reason: This is necessary for Windows Mobile 5, and good practice. It is not part of managed code, but rather a part of Win32.
Benefits: This documents the binary file hasn’t been changed since it was built, and the builder can be trusted. It uses a chain of trust to a central trusted root certificate to insure the author is indeed who they say they are.
For production use, you should buy a certificate from Verisign or another trusted provider. Ramon has suggested a free provider: http://www.cacert.org/. I haven’t reached the same level of trust he has, and can’t comment on using it though. For testing, you can create a “self certificate”. It doesn’t tie to a trusted root certificate, but can be installed on a client machine as a trusted source.
Technique:
– From a Visual Studio Command Prompt, do this once:
makecert -r -sv app.self.pvk -n “CN=AppCert” -b 01/01/2000 -e 12/31/2050 app.self.cer
pvk2pfx.exe -pvk app.self.pvk -spc app.self.cer -pfx app.self.pfx
Substitute “app.self” and “AppCert” in both commands for what ever descriptive info you’d like.
Modify the beginning (-b) and ending (-e) dates as necessary.
Use MSDN or makecert -!
for other parameters.
– After building the project each time (and signing for strong naming), run this command:
```
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\signtool.exe sign /f ../../../path/to/app.self.pfx /d "Descriptive App" /du http://www.tempuri.org/ app.exe
```
Substitute "app.self" for the actual .pfx file, and other info with info relative to your app and your organization.
I like including this as a post-build event on the solution.
An NAnt task would also be a great place to put this command.
Gotchas
– These .pvk, .cer, and .pfx files should be kept in secret. Handing them out defeats the purpose.
– Post-build events are run from the build directory (e.g. /bin/Debug), so relative paths have to start from here
References:
– Sign your redistributables quick and easy
– Signing assemblies for Windows Mobile 5
Conclusion
With both of these in place, you can look at an exe or dll and know that:
– It is uniquely named
– It is unaltered since it was built and the builder can be trusted
The other point of note: .snk sign first, .cer sign second. .snk is .net specific, .cer is bigger than that.
Rob