Two Kinds of Assemblies, Two Kinds of Deployment
The real difference between weakly named and strongly named assemblies is that a strongly named assembly is signed with a publisher’s public/private key pair that uniquely identifies the assembly’s publisher. This key pair allows the assembly to be uniquely identified, secured, and versioned, and it allows the assembly to be deployed anywhere on the user’s machine or even on the Internet.
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.
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.
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.
First, you invoke SN.exe with the –pswitch to create a file that contains only the public key (MyCompany.PublicKey)
SN –p MyCompany.snk MyCompany.PublicKey sha256
Then, you invoke SN.exe, passing it the –tpswitch and the file that contains just the public key.
SN –tp MyCompany.PublicKey
A public key token is a 64-bit hash of the public key.
When you compile your assembly, you use the /keyfile:<file>compiler switch.
csc /keyfile:MyCompany.snk Program.cs
These reduced public key values—known as public key tokens—are what are actually stored in an AssemblyRef table.
By the way, the Assembly Def entry always stores the full public key, not the public key token.
The Global Assembly Cache
As you can see, you can invoke GACUtil.exe, specifying the /iswitch to install an assembly into the GAC, and you can use GACUtil.exe’s /uswitch to uninstall an assembly from the GAC.
By default, the GAC can be manipulated only by a user belonging to the Windows Administrators group.
First, you invoke SN.exe with the –pswitch to create a file that contains only the public key (MyCompany.PublicKey)
SN –p MyCompany.snk MyCompany.PublicKey sha256
Then, you invoke SN.exe, passing it the –tpswitch and the file that contains just the public key.
SN –tp MyCompany.PublicKey
Using GACUtil.exe’s /iswitch is very convenient for developer testing. However, if you use GACUtil.exe to deploy an assembly in a production environment, it’s recommended that you use GACUtil.exe’s /rswitch in addition to specifying the /ior /uswitch to install or uninstall the assembly. The /rswitch integrates the assembly with the Windows install and uninstall engine. Basically, it tells the system which application requires the assembly and then ties the application and the assembly together.
MSI is the only tool that is guaranteed to be on end-user machines and capable of installing assemblies into the GAC.
Building an Assembly That References a Strongly Named Assembly
Yousee, when you install the .NET Framework, two copies of Microsoft’s assembly files are actually installed. One set is installed into the compiler/CLR directory, and another set is installed into a GAC subdirectory. The files in the compiler/CLR directory exist so that you can easily build your assembly, whereas the copies in the GAC exist so that they can be loaded at run time.
In addition, the assemblies in the compiler/CLR directory are machine agnostic. That is, these assemblies contain only metadata in them. Because the IL code is not required at build time, this directory does not have to contain x86, x64, and ARM versions of an assembly. The assemblies in the GAC contain metadata and IL code because the code is needed only at run time.
Strongly Named Assemblies Are Tamper-Resistant
When an assembly is installed into the GAC, the system hashes the contents of the file containing the manifest and compares the hash value with the RSA digital signature value embedded within the PE file (after unsigning it with the public key). If the values are identical, the file’s contents haven’t been tampered with. In addition, the system hashes the contents of the assembly’s other files and compares the hash values with the hash values stored in the manifest file’s FileDef table.
Delayed Signing
The .NET Framework supports delayed signing, sometimes referred to as partial signing.
When an assembly is installed into the GAC, the system hashes the contents of the file containing the manifest and compares the hash value with the RSA digital signature value embedded within the PE file (after unsigning it with the public key). If the values are identical, the file’s contents haven’t been tampered with. In addition, the system hashes the contents of the assembly’s other files and compares the hash values with the hash values stored in the manifest file’s FileDef tableaYou must also tell the tool that you want the assembly to be delay signed, meaning that you’re not supplying a private key. For the C# compiler, you do this by specifying the /delaysigncompiler switch. In Visual Studio, you display the properties for your project, click the Signing tab, and then select the Delay Sign Only check box. If you’re using AL.exe, you can specify the /delay[sign]commandline switch.
When creating the resulting assembly, space is left in the resulting PE file for the RSA digital signature. (The utility can determine how much space is necessary from he size of the public key.) Note that the file’s contents won’t be hashed at this time either.
On every machine on which the assembly needs to be installed into the GAC, you must prevent the system from verifying the integrity of the assembly’s files. To do this, you use the SN.exe utility, specifying the –Vrcommand-line switch.
After this step, you can deploy the fully signed assembly. On the developing and testing machines, don’t forget to turn verification of this assembly back on by using SN.exe’s –Vuor –Vxcommand-line switch.
the steps to develop your assembly by using the delayed signing technique
1. csc /keyfile:MyCompany.PublicKey /delaysign MyAssembly.cs
2. SN.exe –Vr MyAssembly.dll
3. SN.exe Ra MyAssembly.dll MyCompany.PrivateKey
4. SN.exe –Vu MyAssembly.dll
So, if you want to obfuscate an assembly file or perform any other type of post-build operation, you should use delayed signing, perform the post-build operation, and then run SN.exe with the –R or –Rc switch to complete the signing process of the assembly with all of its hashing.
Delayed signing is also useful whenever you want to perform some other operation to an assembly before you package it. For example, you may want to run an obfuscator over your assembly.
Privately Deploying Strongly Named Assemblies
codeBase
How the Runtime Resolves Type References
However, the .NET Framework assemblies (including MSCorLib.dll) are closely tied to the version of the CLR that’s running. Any assembly that references .NET Framework assemblies always binds to the version that matches the CLR’s version.
However, the GAC identifies assemblies by using name, version, culture, public key, and CPU architecture.
When searching the GAC for an assembly, the CLR first searches for a CPU architecture–specific version of the assembly. If it does not find a matching assembly, it then searches for a CPU-agnostic version of the assembly.
Advanced Administrative Control (Configuration)
<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemasmicrosoftcom:asm.v1">
<probing privatePath="AuxFiles;bin\subdir" />
<dependentAssembly>
<assemblyIdentity name="SomeClassLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="neutral"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
<codeBase version="2.0.0.0" href="http://www.Wintellect.com/SomeClassLibrary.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="TypeLib" publicKeyToken="1f2e74e897abbcfe" culture="neutral"/>
<bindingRedirect oldVersion="3.0.0.03.5.0.0" newVersion="4.0.0.0" />
<publisherPolicy apply="no" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Publisher Policy Control
AL.exe /out:Policy.1.0.SomeClassLibrary.dll
/version:1.0.0.0
/keyfile:MyCompany.snk
/linkresource:SomeClassLibrary.config
<publisherPolicy apply="no"/>