Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Giving an Assembly a Strong Name

If multiple applications are going to access an assembly, the assembly must be placed in a well-known directory, and the CLR must know to look in this directory automatically when a reference to the as- sembly is detected. However, we have a problem: Two (or more) companies could produce assemblies that have the same file name. Then, if both of these assemblies get copied into the same well-known directory, the last one installed wins, and all of the applications that were using the old assembly no longer function as desired. (This is exactly why DLL hell exists today in Windows, in which shared DLLs are all just copied into the System32 directory.)

Obviously, differentiating assemblies simply by using a file name isn’t good enough. The CLR needs to support some mechanism that allows assemblies to be uniquely identified. This is what the term strongly named assembly refers to. A strongly named assembly consists of four attributes that uniquely identify the assembly: a file name (without an extension), a version number, a culture identity, and a public key. Because public keys are very large numbers, we frequently use a small hash value derived from a public key. This hash value is called a public key token. The following assembly identity strings (sometimes called an assembly display name) identify four completely different assembly files.

 

"MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture="en­US", PublicKeyToken=b77a5c561934e089" "MyTypes, Version=2.0.1234.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

The first string identifies an assembly file called MyTypes.exe or MyTypes.dll (you can’t actually

determine the file extension from an assembly identity string). The company producing the assembly is creating version 1.0.8123.0 of this assembly, and nothing in the assembly is sensitive to any one culture because Culture is set to neutral. Of course, any company could produce a MyTypes.dll (or MyTypes.exe) assembly file that is marked with a version number of 1.0.8123.0 and a neutral culture.


There must be a way to distinguish this company’s assembly from another company’s assembly that happens to have the same attributes. For several reasons, Microsoft chose to use standard public/ private key cryptographic technologies instead of any other unique identification technique such as GUIDs, URLs, or URNs. Specifically, cryptographic techniques provide a way to check the integrity of the assembly’s bits as they are installed on a machine, and they also allow permissions to be granted on a per-publisher basis. I’ll discuss these techniques later in this chapter. So a company that wants

to uniquely mark its assemblies must create a public/private key pair. Then the public key can be as- sociated with the assembly. No two companies should have the same public/private key pair, and this distinction is what allows two companies to create assemblies that have the same name, version, and culture without causing any conflict.



       
   
 
 

 

In Chapter 2, I showed you how to name an assembly file and how to apply an assembly version number and a culture. A weakly named assembly can have assembly version and culture attributes embedded in the manifest metadata; however, the CLR always ignores the version number and uses only the culture information when it’s probing subdirectories looking for the satellite assembly. Be- cause weakly named assemblies are always privately deployed, the CLR simply uses the name of the assembly (tacking on a .dll or an .exe extension) when searching for the assembly’s file in the applica- tion’s base directory or in any of the application’s subdirectories specified in the Extensible Markup Language (XML) configuration file’s probing element’s privatePath XML attribute.

A strongly named assembly has a file name, an assembly version, and a culture. In addition, a

strongly named assembly is signed with the publisher’s private key.

 

The first step in creating a strongly named assembly is to obtain a key by using the Strong Name utility, SN.exe, that ships with the .NET Framework SDK and Microsoft Visual Studio. This utility offers a whole slew of features depending on the command-line switch you specify. Note that all SN.exe’s command-line switches are case-sensitive. To generate a public/private key pair, you run SN.exe as follows.

 

SN –k MyCompany.snk

 

This line tells SN.exe to create a file called MyCompany.snk. This file will contain the public and

private key numbers persisted in a binary format.


Public key numbers are very big. If you want to, after creating the file that contains the public and private key, you can use the SN.exe utility again to see the actual public key. To do this, you must ex- ecute the SN.exe utility twice. First, you invoke SN.exe with the –p switch to create a file that contains only the public key (MyCompany.PublicKey).1

 

SN –p MyCompany.snk MyCompany.PublicKey sha256

 

Then, you invoke SN.exe, passing it the –tp switch and the file that contains just the public key.

 

SN –tp MyCompany.PublicKey

 

When I execute this line, I get the following output.

 

Microsoft (R) .NET Framework Strong Name Utility Version 4.0.30319.17929 Copyright (c) Microsoft Corporation. All rights reserved.

 

Public key (hash algorithm: sha256): 00240000048000009400000006020000002400005253413100040000010001003f9d621b702111

850be453b92bd6a58c020eb7b804f75d67ab302047fc786ffa3797b669215afb4d814a6f294010 b233bac0b8c8098ba809855da256d964c0d07f16463d918d651a4846a62317328cac893626a550

69f21a125bc03193261176dd629eace6c90d36858de3fcb781bfc8b817936a567cad608ae672b6 1fb80eb0

 

Public key token is 3db32f38c8b42c9a

 

The SN.exe utility doesn’t offer any way for you to display the private key.

 

The size of public keys makes them difficult to work with. To make things easier for the developer (and for end users too), public key tokens were created. A public key token is a 64-bit hash of the pub- lic key. SN.exe’s –tp switch shows the public key token that corresponds to the complete public key at the end of its output.

Now that you know how to create a public/private key pair, creating a strongly named assembly is simple. When you compile your assembly, you use the /keyfile:<file> compiler switch.

 

csc /keyfile:MyCompany.snk Program.cs

 

When the C# compiler sees this switch, the compiler opens the specified file (MyCompany.snk), signs the assembly with the private key, and embeds the public key in the manifest. Note that you sign only the assembly file that contains the manifest; the assembly’s other files can’t be signed explicitly.

If you are using Visual Studio, you can create a new public/private key file by displaying the prop- erties for your project, clicking the Signing tab, selecting the Sign The Assembly check box, and then choosing the <New…> option from the Choose A Strong Name Key File combo box.

 

 
 

1 In this example, I am using Enhanced Strong Naming, which was introduced in .NET Framework 4.5. If you need to produce an assembly that is compatible with previous versions of the .NET Framework, then you will also have to create a counter-signature by using the AssemblySignatureKeyAttribute. For details about this, see http://msdn.microsoft.com/ en-us/library/hh415055(v=vs.110).aspx.


Here’s what it means to sign a file: When you build a strongly named assembly, the assembly’s FileDef manifest metadata table includes the list of all the files that make up the assembly. As each file’s name is added to the manifest, the file’s contents are hashed, and this hash value is stored along with the file’s name in the FileDef table. You can override the default hash algorithm used with AL.exe’s /algid switch or apply the assembly-level System.Reflection.AssemblyAlgorithm­ IdAttribute custom attribute in one of the assembly’s source code files. By default, a SHA-1 algo- rithm is used.

After the PE file containing the manifest is built, the PE file’s entire contents (except for any Au- thenticode Signature, the assembly’s strong name data, and the PE header checksum) are hashed, as shown in Figure 3-1. This hash value is signed with the publisher’s private key, and the resulting RSA digital signature is stored in a reserved section (not included in the hash) within the PE file. The CLR header of the PE file is updated to reflect where the digital signature is embedded within the file.

 

 
 

Calculus.dll

FIGURE 3-1Signing an assembly.

 

The publisher’s public key is also embedded into the AssemblyDef manifest metadata table in this PE file. The combination of the file name, the assembly version, the culture, and the public key gives this assembly a strong name, which is guaranteed to be unique. There is no way that two companies could each produce an assembly named OurLibrary with the same public/private keys unless the companies share this key pair with each other.

At this point, the assembly and all of its files are ready to be packaged and distributed.

 

As described in Chapter 2, when you compile your source code, the compiler detects the types and members that your code references. You must specify the referenced assemblies to the compiler. For the C# compiler, you use the /reference compiler switch. Part of the compiler’s job is to emit an AssemblyRef metadata table inside the resulting managed module. Each entry in the AssemblyRef metadata table indicates the referenced assembly’s name (without path and extension), version num- ber, culture, and public key information.


 

The AssemblyRef metadata information (obtained by using ILDasm.exe) for a simple class library

DLL file is shown here.

 

AssemblyRef #1 (23000001)

­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

Token: 0x23000001

Public Key or Token: b7 7a 5c 56 19 34 e0 89 Name: mscorlib

Version: 4.0.0.0

Major Version: 0x00000004 Minor Version: 0x00000000 Build Number: 0x00000000 Revision Number: 0x00000000 Locale: <null>

HashValue Blob:

Flags: [none] (00000000)

 

From this, you can see that the DLL assembly references a type that is contained in an assembly matching the following attributes.

 

"MSCorLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

 

Unfortunately, ILDasm.exe uses the term Locale when it really should be using Culture. If you look at the DLL assembly’s AssemblyDef metadata table, you see the following.

Assembly

­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

Token: 0x20000001

Name : SomeClassLibrary Public Key :

Hash Algorithm : 0x00008004 Version: 3.0.0.0

Major Version: 0x00000003 Minor Version: 0x00000000 Build Number: 0x00000000 Revision Number: 0x00000000 Locale: <null>

Flags : [none] (00000000)


This is equivalent to the following.

 

"SomeClassLibrary, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null"

 

In this line, no public key token is specified because the DLL assembly wasn’t signed with a public/ private key pair, making it a weakly named assembly. If I had used SN.exe to create a key file com- piled with the /keyfile compiler switch, the resulting assembly would have been signed. If I had then used ILDasm.exe to explore the new assembly’s metadata, the AssemblyDef entry would have bytes appearing after the Public Key field, and the assembly would be strongly named. By the way, the AssemblyDef entry always stores the full public key, not the public key token. The full public key is necessary to ensure that the file hasn’t been tampered with. I’ll explain the tamper resistance of strongly named assemblies later in this chapter.

 

 


Date: 2016-03-03; view: 695


<== previous page | next page ==>
Building an Assembly That References a Strongly | Nbsp;   The Global Assembly Cache
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.01 sec.)