Sharing a Strong Name Key File Across Projects


v2.0 of the .NET Framework deprecated the use of the AssemblyKeyFileAttribute and AssemblyKeyContainerAttribute.  Often times, these attributes were used to share a common key file across several projects.


If you try to share key files using the Visual Studio 2005 <Browse …> function on the signing property page, you’ll find that the key file is copied into your project directory.  In a lot of cases this is exactly the desired behavior since it helps to group all of the artifacts that go into building your project into one location.  However, it is a common requirement that the key file not be copied into every project directory and instead referenced from a single common location.  You can still pull this off using Visual Studio 2005:


Step 1: Add the key file to your project using the Add Existing Item menu.


Add an existing item to the project


Step 2: In the add dialog, instead of choosing to add the key directly (which will make a copy into your project directory), hit the arrow next to the Add button and choose to add the key as a link.


Add a link to the key


Step 3: Go to the signing page of the project properties.  Your key file should now be on the drop down list of available keys.


Select the key on the signing page


Since the key is already a part of the project, Visual Studio will not  make a new copy of it.  One thing to notice, Visual Studio will reference your key as a relative path from the project file.  This may be exactly what you want — but if you’d rather have a hard coded path, you can open up the project file and change the AssemblyOriginatorKeyFile (and the Include path of the Link to your key).


You’ll also want to make sure that on the property sheet of the key file, the Build Action is set to None and Copy to Output Directory is set to “Do not copy” — You don’t want to accidentally start distributing your key file as an embedded resource!


Finally, there are a couple of tweaks you can make for asthetics. After setting up signing, some people like to add the key as a solution item, then edit the project files and add a <Visible>False</Visible> tag to the None tag including the key.  This presents the key in the Solution Explorer at the solution level rather than in each individual project.


Personally, I like to see the key file that each assembly will be signed with, but I don’t want it cluttering the root level of the project’s files.  The tweak I make is to edit the project files and change the Link tag to have a Properties prefix.  For instance, I might have:



<ItemGroup>
  <None Include=”..\App.snk”>
    <Link>Properties\App.snk</Link>
  </None>
</ItemGroup>


This puts the key in the properties node of the project, which I think is a more appropriate location for it than the project root.

Comments (34)

  1. Chris says:

    I went through defining the same process for my company a few weeks ago. An interesting behavior is that once you perform the above steps and get the key file into your projects property pages, you can then go and delete the linked file. The signing page will remain as it was.

    Regards,

    Chris

  2. Matt says:

    Quick question…Is there a problem with security using one SNK for all your projects/assemblies?  or would it be better to create one SNK for each project/assembly?

  3. Nope — that should be fine.

  4. JohnnieK says:

    Can someone tell me if developers can realistically develop their code using delayed signing?  VS 2005 even tells me that I will not be able to run or debug my assemblies when I check the "Delay Sign Only" checkbox in my project properties page.  I went ahead and used the delayed signing option and sure enough my project would not run.  I used the "sn.exe -Vr *,<publicKeyToken>" command, which allowed my assemblies to run outside of VS, which is something, but I could not debug/run within VS.  I’m thinking that developers should not use keys at all and following our nightly build I’ll make a copy of our assemblies and sign them using "sn" for use by QA.  Is that crazy?

  5. JohnnieK says:

    Oops, I’m wrong.  After signing I was able to run the VS project.  Any tips to make the developer’s life easier when using delayed signing?

  6. syed says:

    Is this possible in vs 2003?

  7. v.v..s.kumar says:

    hi,

    ur information is very very good . but same public key generating to assemblies.Is it possible to generate different public key to assembly using same SNK file.

     

    thanks

    v.v.s.kumar

  8. Brad says:

    I think the bigger problem with signing .NET assemblies via the Properties page is that you end up with multiple copies of your SNK file floating around.  Also, you usually end up checking in the SNK file along side the source code.  All that just feels unsecure to me…maybe I’m being too paranoid.

    I sign my .NET assemblies in 1 of 2 ways:

    1. the old fashioned way, with the AssemblyKeyFile attribute in the AssemblyInfo.cs (making sure I can still compile despite the deprecation warning)

    2. creating a key container (/i) and adding a KeyContainerName in each of my CSPROJ files.

  9. Hi Johnnie —

    Well I know for sure it’s possible to use delay signing in a production environment, since that’s how we build the .NET Framework 🙂  You’re right that VS doesn’t have great support for it though, since you’ll have to manually do the skip verification step.

    On the CLR team, we have a setup script to install builds of the runtime.  As part of that script, we register our keys for skip verification so that our delay signing system works.

    -Shawn

  10. V.V.S. Kumar — it’s not possible to do that since public and private keys are mathematically related and tied together. If you want two different public key tokens then you’ll need to use two different private keys to generate their signatures.

    -Shawn

  11. Brad,

    We actually deprectaed those attributes due to information leakage — they end up in your final assembly and people can use that to deduce information about your build environment.  (For instance, you can tell that the Microsoft key for v1.1 of the framework was stored on E:com99binEcmaPublicKey.snk on the build machine.  If it’s on a share you might be able to deduce some machine names in the build network).  This may or may not be a concern for you.

    This post itself was about solving the multiple copies of the SNK file problem though …

    -Shawn

  12. Walter Mitty says:

    Why did this change?  It wasn’t broken in VS 2003 and now VS 2005 just makes it harder to achieve.  The feature could have been added without to 2005 without removing the old functionality.

  13. The following links to .NET resources have been collated over time with the assistance of colleagues.&amp;nbsp;…

  14. John Vottero says:

    Isn’t using a key container the best way to manage private keys?  It’s easy to steal a private key when it’s in a .snk file.  I *think* it’s hard to steal a key that’s stored in a key container.  It’s also easier to manage, even across different solutions.

    VS 2005 broke key containers because it depricated AssemblyKeyName without providing a replacement.  We still manage to use them by editing the .csproj file and adding <KeyContainerName>TheName</KeyContainerName>

    John

  15. Dave Comer says:

    Is there a good reference to how to use this approach with a key file stored on a smart card?

  16. Key containers require being setup on the client machine, and can be ACLed.  However SNK files can also be ACLed.  Since key containers require machine setup, there’s no way to check a project out of source control and just build it.

    On the CLR, we keep the public key files checked into source control, and then pass them over to a carefully guarded machine on Microsoft to do the final signing.

    If you want to protect your keys, I recommend using a self signed certificate instead.

    -Shawn

  17. Check out Ivan’s blog http://dotnetthis.com/Articles/SNandSmartCards.htm for information on signing with a smart card.

    -Shawn

  18. For everyone wondering about previous versions of VS (and this is possible in 2005 as well), you can store the key pair that you create in VS in a store. It’s one of the options when you create the key (and can be done using sn.exe as well). Instead of using a file, get it from the container. For those using older versions of VS, use the AssemblyKeyNameAttribute instead of the AssemblyKeyFileAttribute. The name is whatever the name of the key pair you put into the store.

  19. Right.  However, be aware that using a key container instead of a key file does require that development and build machines run some setup before they can produce a build of your product.

    -Shawn

  20. Mitch says:

    We ran into the same issues on our project (wanting to use a common keyfile) and came up with a similar, but different solution.

    Instead of using the linking option in VS2005, we make use of an environment variable.  We simply update the ".csproj" file to set the "SignAssembly" property to "true" and the "AssemblyOriginatorKeyFile" to the environment variable to use (e.g. $(MY_KEY_FILE) ).

    This is nice because the developers can build with their own keyfile, and the CM can build on their machine with the real keyfile.  This is all done by just simply setting the environment variable.  If the environment variable is not set, then it will create assemblies that are not signed.

    Once the project file is updated initially, you can run any of these permutations without needing to update the project file again.  Very flexible.

    (Additionally, you can override the value in the projects by invoking msbuild with the "/p:AssemblyOriginatorKeyFile=" option if you don’t want to mess with environment variables in your scripts.

    -Mitch

    We decided to use an environment variable to point to the keyfile.  Then

  21. That’s a great tip Mitch!

    -Shawn

  22. hema says:

    I am working in VS.Net 2000.

    can you please tell me the sharing a strong name in that version.

    Also I wish to develop a webservice in .net and to call it in Visual Basic.kindly help me to do this

  23. Hi Hema,

    There was no Visual Studio 2000, so I assume you mean either 2002 or 2003.  In those versions, you can just have the AssemblyKeyFileAttribute point at the same location.

    -Shawn

  24. Slava Brosgol says:

    How key file sharing will affect application publishing (click-once)?

  25. It shouldn’t have any affect on ClickOnce at all.

  26. RoBlog says:

    Strong Named Key File Per Solution

  27. Helena says:

    I tried and I don’t have option to select "Add as a link" when I click the arrow. Do I need to install or changing setting in order to get this option?

  28. Sri.net says:

    hey..

    i am developing a VSTO add-in and intend to install the dll to GAC

    i created a .snk file and added it to the add-in.

    now that i have made the dll a strong-named assembly..it is asking all my other dlls which i am using with this add-in to be strong named..

    is this always like this?? do we have to set all the dlls, even those which i am not going install in GAC, be given a snk file??

  29. Hi Sri,

    Any dependency of a strongly named assembly must also be strongly named.  The reason is, the strong name is giving a specific identity and version to your code so we want to make sure that your code is pulling in exactly the identity and verison of the dependencies it has.  That can only be achieved by strongly naming them as well.

    -Shawn

  30. Jingfei says:

    Now in Visual Studio 2012, you can use following code only.

    <PropertyGroup>

       <SignAssembly>true</SignAssembly>

     </PropertyGroup>

     <PropertyGroup>

       <AssemblyOriginatorKeyFile>relative_path_to_snk/pfx_file</AssemblyOriginatorKeyFile>

     </PropertyGroup>