How do I create a strong name key file for a .NET assembly?
Visual Studio 2005 makes it easy to create a strong name key file:
- Select your assembly project in the Visual Studio Solution Explorer.
- Click the Properties button. The project properties will appear in the main window.
- Select the Signing tab.
- Check the Sign the assembly checkbox.
- In the Choose a strong name key file drop-down, select New. The "Create Strong Name Key" dialog appears.
- In the Key file name text box, type the desired key name. Typically this is the name of your assembly but can be anything. Visual Studio will automatically append the proper file extension.
- If desired, you can protect the strong name key file with a password. To do so, check the Protect my key file with a password checkbox, then enter and confirm the password.
- Click the OK button.
Now when you compile your project, Visual Studio will automatically sign your assembly with the new strong name key you have just created Or if you prefer to use the command-line, you can create a key pair file with the strong name utility sn.exe in the .NET SDK, for example:
sn -k MyKey.snk
Then you reference that key file to when compiling your code with the C# compiler csc.exe:
csc /keyfile:MyKey.snk MyCodeFile.cs
What does it mean to sign an assembly?
.NET uses digital signatures to verify the integrity of an assembly. The signatures are generated and verified using public key cryptography, specifically the RSA public key algorithm and SHA-1 hash algorithm. The developer uses a pair of cryptographic keys: a public key, which everyone can see, and a private key, which the developer must keep secret.
How do I sign an assembly?
When you compile your assembly with a strong name key file, the compiler digitally signs the assembly:
- The compiler calculates the cryptographic digest (a hash) of your assembly contents. This is known as the compile-time digest. Modifying just a single byte of your assembly will change this hash value.
- The compiler encrypts the digest using the 1024-bit private key from your public-private key pair file.
- The compiler then stores the encrypted digest and public key into the assembly.
How does the system verify a signed assembly?
Sometime later, when an application attempts to load your signed assembly:
- The .NET assembly loader calculates the cryptographic digest of the current assembly contents. This is known as the run-time digest.
- The loader extracts the stored compile-time digest and public key from the assembly.
- The loader uses the public key to decrypt the compile-time digest.
- The loader then compares the run-time digest with the decrypted compile-time digest to ensure they match. If not, then the assembly has been modified since you compiled it, and the assembly load fails.
What is delay signing?
Delay signing is signing an assembly with its strong name public key, which is freely distributable, instead of using the private key as usual. This allows developers to use and test a strong-named assembly without access to the private key. Then at a later stage (typically just before shipping the assembly), a manager or trusted keyholder must sign the assembly with the corresponding private key.
How do I protect my private keys?
Private keys must remain secret. A hacker with your private key could spoof your signed assemblies by replacing or injecting them with a virus or other malicious code. There are a few strategies you can use to protect your private keys:
- Password Protection - As shown above, Visual Studio will allow you to protect your strong name key file with a password.
- Delay Signing - As mentioned above, delay signing enables your development team to build and test your assembly without access to the private key.
- Cryptographic Container - One of the most secure ways to protect your strong name key is to store it in a secure cryptographic.
How many private keys should I have?
- One private key for all your applications and assemblies
- One private key for each application (an application may have multiple assemblies)
- One private key for each assembly
Which option to use depends on your security situation and risk tolerance. With option 1, it's easier to keep a single key secure, but if your one private key is compromised, then all of your assemblies are compromised. With option 3, there are more keys to manage and hence lose, but if one key is compromised, then only one of your many assemblies is compromised. I recommend option 2 or 3 to reduce your overall exposure.
Are there problems with using strong names?
Strong names are not perfect. There are some issues to consider when using strong names:
- Requires Exact Match - If you use strong names, your application or library must load the assembly with the exact strong name that you specify, including version and culture. Note that you can bypass this requirement with a publisher policy.
- Cannot Lose Private Key - If your private key is lost or stolen, the security of your assembly is compromised. You will be forced to re-issue a new assembly signed with a new public-private key pair.
- Cannot Stop Full Replacement - Strong names cannot prevent a hacker from removing the strong name signature, maliciously modifying your assembly, re-signing it with his own key, and then passing off his assembly as yours. The user must have some way to ensure the public key they have from your assembly is valid and truly came from you. Note that you can use more sophisticated signing to help with this issue.
Where are shared assemblies stored?
A shared assembly is used by multiple applications. You can store shared assemblies pretty much anywhere. However, the challenge is to ensure that all dependent applications can find the shared assembly. The recommended way to ensure this is to store shared assemblies in the Global Assembly Cache.
What is the Global Assembly Cache (GAC)?
The Global Assembly Cache is a system folder (typically C:\Windows\assembly) that contains .NET shared assemblies. Companies that wish to share assemblies with others or even just among their own applications typically store these shared assemblies in the GAC. All of the .NET framework libraries are stored in the GAC.