2.4 Strong Names

Shared assemblies must have a strong name. A strong name consists of the assembly's name, version and culture metadata, plus a cryptographic public key and a digital signature. Because it is sufficiently unlikely that two different assemblies will have the same strong name, Microsoft considers a strong name to be a unique identifier of an assembly. Two properties of digital signatures support this position:

  1. Digital signatures are associated with a hash code generated from the contents of the assembly; this hash code acts as a "fingerprint" for the assembly contents, and it is very difficult to find two assemblies with the same fingerprint.

  2. Cryptographic key pairs, used to create the digital signature, are created randomly.

The randomness of key pairs, and the uniqueness of the fingerprint provided by the digital hash code and signature, means that a strong name, for all practical purposes, provides a unique identification for an assembly. See Chapter 13 for details of digital hash codes and Chapter 16 for details of digital signatures.

The chapters in the Cryptography section of this book provide information about assessing the cryptographic meaning of words and phrases such as "unique" and "very difficult."

The uniqueness of a strong name allows the .NET Framework to verify the contents of an assembly to protect against tampering; the hash code generated from the assembly contents means that changing even a single MSIL statement will invalidate the digital signature, leading the .NET Framework to reject the assembly. This protection against tampering is a fundamental security feature of strongly named assemblies and is a key function in the life cycle of a .NET application, which we discuss in Chapter 4. Strong names are a key feature of code access security, which we discuss in Chapter 6 through Chapter 9.

Library assemblies with strong names can be used only by fully trusted code, unless the AllowPartiallyTrustedCallers attribute has been applied to the assembly. See Chapter 7 for information about trusted code and the implications for your development projects.

2.4.1 Creating a Key Pair

The first step towards creating a strong name is to generate a public and private key. The private key is used to create the digital signature and must be kept secret; the public key is included in the assembly as part of the strong name and is used by the .NET Framework to validate the digital signature and to determine if the contents of an assembly have been tampered with. See Chapter 15 for information about public/private key pairs and Chapter 16 for details of digital signatures.

Create a new pair of keys using the Strong Name tool (sn.exe), supplied as part of the .NET Framework SDK. The following command illustrates how to create a new pair of keys, stored in a file named MyKeyPair.snk:

sn -k MyKeyPair.snk

The contents of the MyKeyPair.snk file are not human-readable, but you can view the public key with the following command:

sn -tp MyKeyPair.snk

The output is below; the public key is a sequence of hexadecimal characters. This command also displays the public key token (marked in bold), which is a hash code of the public key, used by other assemblies as a compact way of referencing your public key.

Microsoft (R) .NET Framework Strong Name Utility Version 1.1.4322.510
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Public key is
00240000048000009400000006020000002400005253413100040000010001004b251886d12dfd0501c03
2d9b1d36888f3ee68ecc047a56d457ac21d64a54467d7d223c5be2e99bf2ed499c16db4cee567c16d94d2
94aece0348a00025eb7d415005d887c4cee3ee26b83d9cb4b29ed7b21b0c5097f4277d260938f5e00a4cf
f90cf20befd491782b1f3a34675c3ce6c2224bdcc2e329057031937f7d4e032b7

Public key token is 060fc0167cf4a028

You can install the newly created key pair into the Windows Cryptographic Service Provider (CSP) container, which provides a centralized store of key pairs. Installing key pairs in the CSP offers easier administration than storing the keys in a disk file; see the Windows documentation for full details. The following command demonstrates how to install keys into a CSP container called MyCSPContainer; you will see how to use this container in the following sections.

sn -i MyKeyPair.snk MyCSPContainer

It is very important that your private key remains a secretif not, then assemblies can be assigned strong names, which will appear to have originated from you. And why be granted an unwarranted level of trust by system administrators?

2.4.2 Creating an Assembly Strong Name

Before you can generate a strong name, you need to specify the assembly's version and culture metadata; remember that a strong name consists of the assembly name, the version and culture information, plus a public key and a digital signature.

2.4.2.1 Specifying the version and culture metadata

The simplest way to specify the version and culture metadata is to use the System.Reflection.AssemblyVersion and System.Reflection.AssemblyCulture attributes, applied at the assembly level. Visual Studio .NET creates a file called AssemblyInfo.cs (C#) or AssemblyInfo.vb (Visual Basic .NET) as part of a project; this file contains attributes for all of the configurable assembly metadata. We shall follow this convention to specify the metadata for our example assembly (from Section 2.2) as follows; we have specified that this is Version 2.1.0 of our assembly and that the assembly is suitable for any culture setting (see the .NET documentation for details of version and culture configuration):

# C#

using System.Reflection;
using System.Runtime.CompilerServices;

// Specify the culture and version metadata
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.1.0")]

# Visual Basic .NET

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

' Specify the culture and version metadata
<Assembly: AssemblyCulture("")>
<Assembly: AssemblyVersion("2.1.0")>
2.4.2.2 Specifying the key pair

We specify the key pair to use when creating the strong name by adding an attribute that refers to either the file or CSP container that contains our key pair; we do this with the AssemblyKeyFile and AssemblyKeyName attributes. You should specify a file or a CSP containerdo not specify both. To specify a key pair file, add the following attribute to the AssemblyInfo.cs or AssemblyInfo.vb file:

# C#

[assembly: AssemblyKeyFile("MyKeyPair.snk")]

# Visual Basic .NET 

<Assembly: AssemblyKeyFile("MyKeyPair.snk")>

To specify that the key pair should be obtained from the MyCSPContainer CSP container, add the following attribute to the AssemblyInfo.cs or AssemblyInfo.vb file:

# C#

[assembly: AssemblyKeyName("MyCSPContainer")]

# Visual Basic .NET 

<Assembly: AssemblyKeyName("MyCSPContainer")>
2.4.2.3 Creating the strong name

The .NET language compilers will automatically create the strong name if you specify AssemblyInfo.cs or AssemblyInfo.vb in the list of files to compile. The following command demonstrates how to apply the strong name to the example single-file assembly that you created previously:

# C#

csc /out:SingleFileAssembly.dll /target:library SumNumbers.cs SumArray.cs 
AssemblyInfo.cs

# Visual Basic .NET

vbc /out:SingleFileAssembly.dll /target:library SumNumbers.vb SumArray.vb 
AssemblyInfo.vb
2.4.2.4 Creating a strong name for a multifile assembly

For a single-file assembly, the compiler uses the assembly attributes to locate the key pair and generates the strong name. When working with a multifile assembly, you must specify the information required for the strong name as arguments to the Assembly Linker tool (al.exe); the following command demonstrates how to create a strong-named assembly using the modules you created previously:

al /out:MultiFileAssembly.dll /target:library /culture:"" /version:2.1.0 /keyfile:
MyKeyPair.snk SumNumbers.netmodule SumArray.netmodule

We specify the culture and version metadata with the /culture and /version arguments, and the file containing the key pair with the /keyfile argument. The Assembly Linker supports the /keyname argument to specify a CSP container for the keys.

2.4.3 Delayed Signing

The examples in the previous sections assume that you are able to either create or access the key pair used to create strong names. In large organizations, a signing authority may manage the key pair, and you are required to submit your assemblies for signing; this is especially likely if a single key pair is used to create strong names for the assemblies produced by more then one project.

The .NET Framework supports delayed signing, where the public key is included in the assembly, but the signature is not created; this allows you to compile and test your assemblies without requiring access to the secret private key. The first step is to obtain the public key from the key pair, a task usually performed by the signing authority; the following command demonstrates how to extract the public key from the key file and place it in a file called MyPublicKey.snk:

sn -p MyKeyPair.snk MyPublicKey.snk

You can also extract the public key from a key pair stored in a CSP container:

sn -pc MyCSPContainer MyPublicKey.snk

For a single-file assembly, enable delayed signing with the AssemblyDelaySign attribute, which you add to the AssemblyInfo.cs or AssemblyInfo.vb file as follows, specifying the name of the file containing the public key with the AssemblyKeyFile attribute:

# C#

using System.Reflection;
using System.Runtime.CompilerServices;

// Specify the culture and version metadata
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.1.0")]

// Enable delayed signing
[assembly: AssemblyDelaySign(true)]
// specify the file containing the public key
[assembly: AssemblyKeyFile("MyPublicKey.snk")]

# Visual Basic .NET

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

' Specify the culture and version metadata
<Assembly: AssemblyCulture("")>
<Assembly: AssemblyVersion("2.1.0")> 

' Enable delayed signing
<Assembly: AssemblyDelaySign(true)>
' specify the file containing the public key
<Assembly: AssemblyKeyFile("MyPublicKey.snk")>

Compile the assembly as before:

# C#

csc /out:SingleFileAssembly.dll /target:library SumNumbers.cs SumArray.cs 
AssemblyInfo.cs

# Visual Basic .NET

vbc /out:SingleFileAssembly.dll /target:library SumNumbers.vb SumArray.vb 
AssemblyInfo.vb

For a multifile assembly, use the /delaysign+ argument to enable delayed signing and specify the key file with the /keyfile argument, as shown below:

al /out:MultiFileAssembly.dll /target:library /culture:"" /version:2.1.0 /delaysign+ 
/keyfile:MyPublicKey.snk SumNumbers.netmodule SumArray.netmodule

The assemblies that these commands create do not have strong names, because they are not digitally signed. The signing authority can subsequently complete the strong name by using the -R argument of the Strong Name tool, as follows:

sn -R MultiFileAssembly.dll MyKeyPair.snk

This technique applies to single- and multifile assemblies. As well as specifying the name of the assembly to sign, you must provide the name of the key file that contains the public and private keysthe public key file cannot be used to create a digital signature. You can specify a CSP container from which to obtain the key pair with the -Rc argument, as follows:

sn -Rc SingleFileAssembly.dll MyCSPContainer

2.4.4 Verifying a Strong Name

You can verify an assembly strong name with the Strong Name tool (sn.exe); verification checks that the contents of the assembly have not been changed since the digital signature was created. The following command verifies our example single-file assembly:

sn -v SingleFileAssembly.dll

For a valid assembly, the output from this command is as follows:

Microsoft (R) .NET Framework Strong Name Utility  Version 1.1.4322.510
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Assembly 'SingleFileAssembly.dll' is valid

You can also determine the public key from the key pair used to create the digital signature using the following command:

sn -Tp SingleFileAssembly.dll

The result of this command is shown below, and you can see that this matches the public key we created in Section 2.4.1:

Microsoft (R) .NET Framework Strong Name Utility  Version 1.1.4322.510
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Public key is
00240000048000009400000006020000002400005253413100040000010001004b251886d12dfd0501c03
2d9b1d36888f3ee68ecc047a56d457ac21d64a54467d7d223c5be2e99bf2ed499c16db4cee567c16d94d2
94aece0348a00025eb7d415005d887c4cee3ee26b83d9cb4b29ed7b21b0c5097f4277d260938f5e00a4cf
f90cf20befd491782b1f3a34675c3ce6c2224bdcc2e329057031937f7d4e032b7

Public key token is 060fc0167cf4a028


    Part V: API Quick Reference