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.
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.
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.
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
Anonymous
April 25, 2006
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,
ChrisAnonymous
May 01, 2006
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?Anonymous
May 01, 2006
Nope -- that should be fine.Anonymous
May 02, 2006
The comment has been removedAnonymous
May 02, 2006
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?Anonymous
May 03, 2006
Is this possible in vs 2003?Anonymous
May 03, 2006
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.kumarAnonymous
May 04, 2006
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.Anonymous
May 04, 2006
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.
-ShawnAnonymous
May 04, 2006
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.
-ShawnAnonymous
May 04, 2006
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 ...
-ShawnAnonymous
May 05, 2006
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.Anonymous
May 05, 2006
The following links to .NET resources have been collated over time with the assistance of colleagues.&nbsp;...Anonymous
May 08, 2006
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>
JohnAnonymous
May 08, 2006
Is there a good reference to how to use this approach with a key file stored on a smart card?Anonymous
May 08, 2006
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.
-ShawnAnonymous
May 08, 2006
Check out Ivan's blog http://dotnetthis.com/Articles/SNandSmartCards.htm for information on signing with a smart card.
-ShawnAnonymous
May 13, 2006
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.Anonymous
May 15, 2006
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.
-ShawnAnonymous
May 15, 2006
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. ThenAnonymous
May 15, 2006
That's a great tip Mitch!
-ShawnAnonymous
May 20, 2006
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 thisAnonymous
May 23, 2006
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.
-ShawnAnonymous
May 24, 2006
How key file sharing will affect application publishing (click-once)?Anonymous
May 24, 2006
It shouldn't have any affect on ClickOnce at all.Anonymous
June 21, 2006
The comment has been removedAnonymous
October 20, 2006
The comment has been removedAnonymous
December 17, 2006
PingBack from http://www.sral.org/2006/12/18/links-for-2006-12-18/Anonymous
January 08, 2007
Strong Named Key File Per SolutionAnonymous
December 08, 2009
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?Anonymous
February 14, 2010
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??Anonymous
February 24, 2010
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. -ShawnAnonymous
August 24, 2014
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>