When you get beyond simple forms based applications and you're ready to tackle something a little more powerful, you might discover that you need programming tools that are more powerful too. This article is about SN - the Strong Name Utility.
About Visual Basic offers a series of articles about the Framework tools. Links to all of them, and an introduction to the .NET Framework tools, can be found at: Framework Tools - About the Tools. (Note ... The series is still incomplete as of this writing, however.)
SN.EXE is a "helper" utility because it's really only required as part of another process. That process is usually installing assemblies in the GAC - Global Assembly Cache. If you need background information on that, I recommend that you start with one of the other articles in this series, either the article introducing assemblies - The .NET Framework - Assemblies - or the article about GACUTIL - Framework Tools - GACUTIL.
A "strong name" is an assembly name that includes:
-> the name of the assembly
-> the version
-> a 64 bit hash of a public key (called a 'token')
-> the culture
Because the name includes the public key hash, it's guaranteed unique, and that's the main reason that it's required by GACUTIL. The GAC is a place to store assemblies that can be referenced from anywhere. To make sure that Windows never confuses one program with another one with the same name, a guaranteed unique strong name is used. If you try using GACUTIL without generating a strong name first, you simply generate an error:
Failure adding assembly to the cache: Attempt to install an assembly without a strong name
To create a strong name for an assembly, you use a utility called sn.exe.
You can think of a strong name as the .NET Framework equivalent of something that you might have seen before: the GUID. The name GUID means "globally unique identifier". A GUID is a 128-bit number that is created by a mathematical process that makes it unique. But strong names are created using two cryptographically related keys called a public key and a private key. This gives strong names a whole new dimension of capability over the GUIDs. In fact, the SN utility is as much a cryptographic tool as anything else because it provides options for key management, signature generation, and signature verification.
Being more exact, a strong name consists of a set of related data as follows:
- The friendly name of the assembly - which is just the name of the assembly minus the file extension.
- The version number of the assembly.
- The public key value-created using sn.exe.
- An optional culture identity value used for localization.
And perhaps most significant:
- An embedded digital signature that is created from a hash of the assembly's contents and the private key value. More on this later.
So, step one is to generate public/private key data using the .NET Framework utility: sn.exe. The sn.exe utility will create a file ending with the *.snk (strong name key) file extension. This file contains the values of two mathematically related keys. These are the public key and the private key. The VB.NET compiler can record the full public key value as part of the assembly manifest.
The compiler will also generate a hash code based on the contents of the entire assembly including the IL (intermediate language) code and the metadata. A hash code is a numerical value that can guarantee that the content of the assembly hasn't been changed. The hash code can be regenerated from the assembly at any time. If the assembly isn't bit for bit identical, the hash value won't be the same. That means that the hash code can detect any change. To make the hash code secure, it's encoded by the private key data in the *.snk file to create a digital signature in the assembly's CLR header data.
The use of strong names goes way beyond the simple function of COM GUIDs and also provides protection against someone tampering with your assemblies. So it's a good idea to give an assembly a strong name, even if it isn't added to the GAC.
Note that the private key is not in the manifest. It's used to digitally sign the contents of the assembly (that's the process described above) but it isn't part of the manifest to maintain security. Public/private key cryptography can guarantee that no two organizations or individuals will have the same identity with .NET. But the most immediate effect goes back to where we started. Once a strong name is complete, the assembly can be installed into the GAC as a shared assembly.
Here's a quick demo of the process of generating and using a strong name.
To create a public/private key file, you need to execute SN.exe in a Command Prompt window. If you need some help with that, the introduction article provides some tips. Remember to use the 64 bit version of the Command Prompt window if you're using a 64-bit computers. We're working close to the hardware here.
Change to a convenient directory in the Command Prompt window. You might want to create a new directory for your new strong name file just to make things easier to see. You can then generate a file named MySNFile.snk file using the command:
sn -k MySNFile.snk
The computer should echo back a message telling you that the file has been created. You can now use the public/private key pair that is contained in this file in any number of assemblies. Your whole company could use the same strong name file, or you can create one just for a single assembly as we will do here.
Create and compile a program using Visual Studio. Switching back to the Command Prompt, use the ILDASM utility to view the manifest for the new assembly file for your program. Scroll down to the section of the manifest that describes your program. I'm using a standard Windows program named GACUTIL_Test, so the section will start with the line:
Because you're going to be looking for a change in the manifest, you might even want to copy this section into Notepad for easy comparison.
Close down ILDASM and go back to Visual Studio. Open the project properties window. In previous versions of Visual Studio, you had to manually update the AssemblyInfo.vb file. Visual Studio 2010 lets you select the public/private key file using the properties for the project.
Click Here to display the illustration
After updating the project properties to tell Visual Studio to include a strong name, build the solution again. Switch back to ILDASM one more time and you will now see a new .publickey tag shows the full public key information.
Click Here to display the illustration
I've suggested that you check things out using ILDASM just to make sure that what is happening is completely clear. In a real world situation, you don't have to do that.
You could use a .snk file for a whole organization. In that case, it would be a very sensitive and protected file. If your organization worked this way, you would probably also use a technique called delayed signing which requires a altered .snk file containing only the public key. Since anyone who had the private key could sign a project and install it, only a few trusted individuals would normally have access to it. for this reason, someone else with a higher security level than you will have executed sn.exe with the -p parameter after the original key pair was generated to create a key file with just the sensitive private key in SecretCorporatePrivateKey.snk.
sn -p SecretCorporatePrivateKey.snk PublicKeyForAnyone.snk
Just to be clear, the SecretCorporatePrivateKey.snk file starts out with both the public and private key using a command:
sn -k SecretCorporatePrivateKey.snk
The -p option removes the public key and places it in a file by itself leaving only the private key in the file SecretCorporatePrivateKey.snk.
Then you would check the Delay sign only box in the project properties (see the illustration above) and build the assembly using only the public key. The person authorized to use the complete public/private .snk key file then has to resign the the assembly with the complete digital signature. SN.exe has a parameter for that too: the -R flag:
sn.exe -R GACUTIL_Test C:\SecretCorporateKeyPair.snk
You're there, champ! May your names always be strong names!