2006-08-02

Signing Assemblies in Visual Studio 2005 with Key Containers

When signing an assembly, I prefer to use key containers rather than key files. Just specify a key name in AssemblyKeyName and the assembly is signed with that key provided that it has been installed on the machine. Installing the key into a key container is easy. Take the keyfile (keyfile.snk) obtained by running sn -k keyfile.snk from a Visual Studio / SDK Command Prompt and run it with sn -i keyfile.snk keycontainer. Set AssemblyKeyName in AssemblyInfo.cs to "keycontainer" ([assembly: AssemblyKeyName("keycontainer")]) and the assembly will be signed with the key in keycontainer.

At least, that's how it worked in Visual Studio .NET 2002 and Visual Studio .NET 2003. In Visual Studio 2005, if one uses the AssemblyKeyName attribute in AssemblyInfo.cs, one gets the following warning:

Properties\AssemblyInfo.cs(16,12): warning CS1699: Use command line option '/keycontainer' or appropriate project settings instead of 'AssemblyKeyName'

This is fine, except a reason we'll get into later. If one looks up C# compiler warning CS1699 in the VC# Reference, one will note that "Prior to Microsoft Visual C# 2005, you specified the key file using CLR attributes in source code. These attributes are now deprecated". The warning description goes on to list security, usability, and decreased compiler efficiency as reasons for the deprecation.

Now, the reference page for CS1699 also states "Beginning in Microsoft Visual C# 2005, you should use the Signing Page of the Project Designer or the Assembly Linker to specify the key". The problem here is that the "Signing Page" has no place to specify a key container!



CS1699's documentation points one to a page titled "/keycontainer (Specify Strong Name Key Container) (C# Compiler Options)". On that page one finds the following tasty morsel:

To set this compiler option in the Visual Studio development environment

  • This compiler option is not available in the Visual Studio development environment


  • Well, that would explain how this can lead to an increase in compiler efficiency!

    You can't specify any additional options to the C# compiler via the IDE, and there's no way to specify a keycontainer on the "Signing Page".

    Luckily, there is a way to specify a keycontainer without using the AssemblyKeyName attribute. One needs to close the C# project and open up the .csproj file for the particular project in an XML editor ("Notepad"). In the first <PropertyGroup> element one can add the following line, replaing [containername] with the name of the key container one wishes to use:

    <KeyContainerName>[containername]</KeyContainerName>

    Note that as tempting as it may be, you need to leave the value of the "SignAssembly" element as false. Apparently, "SignAssembly" really means "use an assembly key file".

    Open up the project again and build the assembly, and it should be signed with the key that was installed into the container specified in the KeyContainerName.

    »

    4 comments:

    Jay B said...

    I'm curious how you found this out. Also, in my .csproj I show something different:

    <AssemblyKeyContainerName>
    </AssemblyKeyContainerName>

    Is this the correct section, or is it the same thing as:

    <KeyContainerName>
    </KeyContainerName>

    Thanks

    «/\/\Ø|ö±ò\/»®© said...

    Mainly, inference and trial and error. KeyContainerName != AssemblyKeyContainerName. For the instructions I provided, KeyContainerName is the correct tag to use.

    Anonymous said...

    Excellent.

    Rasik Bihari said...

    Superb Finding!!