Reference: http://www.cnblogs.com/cpcpc/archive/2011/01/17/2123086.html
A strong name consists of an assembly's identity plus a public key and a digital signature. Where the identity of the assembly includes simple text names, version numbers, and culture information, if provided. A strong name is generated by using the corresponding private key, through the assembly file (the file that contains the assembly manifest, and therefore the names and hashes of all the files that make up the assembly). Microsoft? Visual Studio?. NET and other development tools that are available in the. NET Framework SDK can assign strong names to an assembly. Assemblies with the same strong name should be the same. By signing a strong-named assembly, you can ensure that the name is globally unique. Strong names also specifically meet the following requirements: 1) Strong names rely on a unique key pair to ensure the uniqueness of the name. No one will generate the same assembly name that you generated, because the name of the assembly generated with one private key is not the same as the name of the assembly generated with the other private key. 2) Strong name protect the version lineage of the assembly. A strong name ensures that no one can build subsequent versions of your assembly. Users can be confident that the version of the assembly they are loading comes from the same publisher who created the version (the application was built with that version). Strong names provide a reliable integrity check. After the. NET Framework security Check, you can be confident that the contents of the assembly have not been changed since it was built. Note, however, that a strong name or strong name itself does not imply a trust level, such as a trust provided by a digital signature and a support certificate. Although the strong name is. NET encryption is also the Microsoft recommended application protection mechanism, but because the managed program can be disassembled into IL code, change or remove the strong name is also possible. The strength of strong names is therefore greatly diminished. 9.2.1 Protecting code integrity with strong names
When we download an assembly from the Internet for local invocation, how do we ensure that the assembly is not maliciously tampered with by a third party? If the name, size, and version number of the two assemblies are the same, does that mean the two assembly files are the same?
The method used to differentiate assemblies under the. NET platform is the same as Win32, with names, but with strong and weak names. A weak name contains the version number, assembly name, and culture. A strong name adds a digital signature based on a weak name. There are three main functions of strong names: one is to distinguish different assemblies, and the other is to ensure that the code has not been tampered with; NET, only assemblies with strong name signatures can be placed in the global assembly cache.
To include an assembly with a strong name we first generate a key pair for asymmetric encryption, which will be used for signing and validating the assembly. Signed and validated in process 9-3 as shown.
Figure 9-3 Signing (above) and verifying (next) Strong name process
9-3, in the strong name signature when we first on the Assembly (excluding DOS head and PE header) hash, get the hash value of the file, and then use the private key to encrypt the hash value, get ciphertext. Then, the public key, public key identification (the last 8 bytes of ciphertext obtained after SHA-1 hashing of the public key) and three ciphertext information are saved in the assembly. When the assembly is loaded, the assembly is first hashed to get a hash value (what we call "new hash Value"), and then extract the public key from the assembly to decrypt the ciphertext to get the original hash value, if the two hash value is the same, that is verified.
There are two ways to sign an assembly with both normal and deferred signatures.
Delay signing is used when our developers have access to the public key only and do not have access to the private key. This is where we can compile the assembly and reserve the signature space first. The assembly does not function and debug at this time.
9.2.2.1 creating strong-named signed assemblies in the SDK
Strong name signing of the Assembly, we have to prepare the key first. In the 6th chapter of this book, the key pair can be generated using the Strong Name tool (Sn.exe) provided in the Visual Studio SDK. We use the 9-4 command to generate a new key pair and save it to the local file test.snk.
Figure 9-4 Generating a key file
Next we create a new console test project StrongName, the main code is shown in Listing 9-3.
Code Listing 9-3 StrongName Project main code
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Text;
Using System.Reflection;
Namespace StrongName
{
Class Program
{
static void Main (string[] args)
{
string aa = "";
Assembly-assembly.getexecutingassembly ();
Console.WriteLine (The. Fullname.tostring ());
byte[] PKey =. GetName (). Getpublickey ();
byte[] Pkeytoken =. GetName (). Getpublickeytoken ();
String pkeystring = GetString (PKey);
String pkeytokenstring = GetString (Pkeytoken);
Console.WriteLine ("Public key is: {0}", pkeystring);
Console.WriteLine ("Public key ID is {0}", pkeytokenstring);
Console.read ();
}
private static string GetString (byte[] bytes)
{
StringBuilder sb = new StringBuilder ();
foreach (Byte b in bytes)
{
Sb. Append (String. Format ("{0:x}", b));
}
Return SB. ToString ();
}
}
}
The code in Listing 9-3 is simple, using reflection to enumerate the name of the current assembly and the public key and public key identity used. When the assembly is not strongly named, we run the program to get 9-5 results.
Figure 9-5 Run result of code listing 9-3 without strong name signing of the Assembly
The following is a command line for the C # compiler (csc.exe) to execute 9-4 of the commands shown.
Figure 9-4 Applying a strong name to an assembly
Now let's do the Program.exe we just generated, and see what the results are, 9-5.
Figure 9-5 Running result of code listing 9-3 after strong name signing of the Assembly
As we can see from figure 9-5, we successfully output the public key and public key identity after performing a strong name signature.
In order for the compiler to automatically sign strong names for code we can add attributes for the code to indicate the key file required for strong name signing. An example of code after adding an attribute is shown in Listing 9-4.
Code listing 9-4 using attributes for Strong name signing
Using System;
Using System.Reflection;
[Assembly:assemblykeyfileattribute ("Testkey.snk")]
Code Listing 9-4 uses assemblykeyfileattribute to specify the name of the file that contains the key pair.
When we need to delay signing the assembly, we need to use the AssemblyDelaySignAttribute feature and the AssemblyKeyFileAttribute in the form of code listing 9-5 .
Using System;
Using System.Reflection;
[Assembly:assemblykeyfileattribute ("mykey.snk")]
[Assembly:assemblydelaysignattribute (True)]
In code listing 9-5, when we need to delay signing the assembly, we specify the file containing the public key and set the AssemblyDelaySignAttribute attribute value to True.
9.2.2.2 creating strong-named signed assemblies in VS
Strong name signing in the SDK it's a bit of a hassle, let's take VS2010 as an example of how to do strong name signing in Visual Studio.
We open the project's properties and switch to the signature page, shown in 9-6.
Figure 9-6 Signature page of the project
As I can see from Figure 9-6, the Project Signature property page contains three large configuration items, the first one is to sign the ClickOnce manifest, the second is to sign the assembly, and the third is a delay signature.
In order to publish an application using ClickOnce deployment, the application and deployment manifests must be strongly named with a public/private key pair and signed using AUTHENTICOD technology. You can use the certificate or key file for the Windows certificate store to sign the manifest. You can also create a new test certificate.
In the option to sign the assembly, we can either select the key file or generate a new key file to sign the assembly.
If the delay-only signature is checked, the assembly is delayed-signed.
9-7, after the ClickOnce signature and assembly signature have been created, the project automatically adds two key files Strongname_temporarykey.pfx and test.pfx.
Figure 9-7 Creating a ClickOnce signature and assembly signature
If an assembly with a strong name signature is tampered with, the CLR fails when it loads the assembly for integrity verification. We now use the text Editing tool to open the StrongName.exe, in the guarantee does not destroy the PE file format under the premise of the simple modification, here I only have to replace the variable AA defined in the program as shown in Bb,9-8.
Figure 9-8 Modifying a strong name signature assembly
After the modification, we run StrongName.exe again and see that the exception that the program reported is a strong name validation failure, as shown in Figure 9-9.
Figure 9-9 Strong Name validation failed
Note :
1. An assembly with a strong name signature cannot reference an assembly that is not signed.
2. Starting with the. NET Framework version 3.5 service Pack 1, a strong name signature will not be validated when the assembly is loaded into a full-trust application domain, such as the default application domain for the MyComputer zone. This is known as the strong-name bypass feature. In a full-trust environment, the requirements for strongnameidentitypermission are always successful for signed full-trust assemblies, regardless of the signature of those assemblies. The strong-name bypass feature avoids the unnecessary overhead of validating a strong-name signature for a full-trust assembly in this situation, which allows the assembly to load more quickly.
The bypass feature applies to any assembly that is signed with a strong name and has the following characteristics:
1) Fully trusted without strongname evidence (for example, with MyComputer area evidence).
2) load into the fully trusted AppDomain.
3) Load from the location under the ApplicationBase property of the AppDomain.
4) signature without delay.
You can disable this feature for individual applications or for the entire computer.
1) Disable the strong-name bypass feature for all applications
On a 32-bit computer, create a subkey under the Hkey_local_machine/software/microsoft/.netframework key in the system registry. Use a DWORD value of 0 for the item name Allowstrongnamebypass.
On a 64-bit computer, create a subkey under the Hkey_local_machine/software/microsoft/.netframework key in the system registry. Use a DWORD value of 0 for the item name Allowstrongnamebypass. Create the same subkey under the Hkey_local_machine/software/wow6432node/microsoft/.netframework key.
2) Disable the strong-name bypass feature for a single application
Open or create an application configuration file. Add the following key:
<configuration>
<runtime>
< Bypasstrustedappstrongnames enabled= "false"/>
</runtime>
</configuration>
You can restore the bypass feature for the application by removing the profile setting or by setting the attribute to "true".
9.2.2 an assembly that references a strong name signature
The process of referencing a strong-named assembly is transparent to us, and we do not need to do extra work. But we can examine the role of strong-named assemblies in this way.
9-10 We first create a class library project Strongnamereferencelib, which is strongly named.
Figure 9-10 Referencing a strong name assembly
Next we modify the previously created StrongName project to refer to the Strongnamereferencelib project and invoke its Gethello method.
The main code for the Strongnamereferencelib project is shown in Listing 9-6.
Code Listing 9-6 Strongnamereferencelib Project main code
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Text;
Namespace Strongnamereferencelib
{
public class Class1
{
public static string Gethello ()
{
return "Hello";
}
}
}
The modified StrongName project code is shown in code listing 9-7.
Code Listing 9-7 StrongName Project code
Using System.Text;
Using System.Reflection;
Using Strongnamereferencelib;
Namespace StrongName
{
Class Program
{
static void Main (string[] args)
{
Console.WriteLine (Class1.gethello ());
Console.read ();
}
}
}
To recompile the StrongName project, we now get the new StrongName.exe file. Open the StrongName.exe file with ILDASM, and view its assembly manifest, shown in 9-11.
Figure 9-11 StrongName.exe assembly manifest
In the manifest of the assembly in Figure 9-11, we can see that it references two strong-named signed assemblies, mscorlib and our newly created strongnamereferencelib, and added version and PublicKeyToken identities to the two assemblies respectively.
Below we remove the strong name signature of Strongnamereferencelib, recompile the project, but we do not recompile the StrongName project, Instead, replace the StrongNameReferenceLib.dll referenced before StrongName.exe with the newly generated StrongNameReferenceLib.dll to see what happens. As shown in result 9-12.
Figure 9-12 The result after replacing the DLL with the StrongName project
We can see from the exception information in Figure 9-10 that the StrongName project cannot find a matching assembly. The reason is that the PublicKeyToken value is stored in the StrongName assembly manifest, and the item without a strong name signature does not have that property.
Vulnerability of 9.2.3 strong names
The above sections let us experience the protection and principle of strong names on assemblies, but how powerful is this protection? Can you get an effective defense against a malicious person who tampered with it? Let's look at the following example.
Now let's go back to listing 9-7, re-sign the Strongnamereferencelib project with a strong name, and then compile the StrongName project. Now there are StrongNam.exe and StrongNameReferenceLib.dll two files in the bin directory of the StrongName project. Then use ILDASM to open the StrongNameReferenceLib.dll file, dump it as Il file, here I use Notepad to open the Il file, as shown in 9-13.
Figure 9-13 Il source of StrongNameReferenceLib.dll
We found three code in the. Il file: Publickkeytoken, PublicKey, and hash, delete the corresponding content, and then re-use the ILAsm compilation, when the strong name of the assembly is successfully removed.
The strong name method for replacing an assembly is basically the same. There are many tools for removing and replacing strong names on the Web, and this is not a cover-up.
So what is the way we should protect the strong name from being removed or tampered with? I will discuss this question in a special article.
Code Listing 9-5 attribute declaration for delay signing of an assembly
. NET assembly strong Name signing practice