Wednesday, March 5, 2008

Strong Naming and Delay Signing Of Assemblies: Part Three

<<Part One>> <<Part Two>>

Protecting Secrets with Delay Signing or Partial Signing:

Strong names are secure only when the strong name private key is kept secure. Strong names do not have any revocation mechanism that can be used if the private key is compromised and they don’t have any expire date. So, it is very important to keep your private key as private! That is keeping your organization’s private key as secure is important to use your enterprise’s strong name for trust. What happens if a malicious person gets your private key? Answer is very simple; he can produce assemblies that appear to have been signed by you. Because of these reasons, you may wish to keep your private key as secure as possible by giving access to only few people instead of all. But then, how can you handle strong naming of assemblies? How can you sign the assemblies without having access to a private key? This is where delay signing enters the picture. With delay signing, you can build and test an assembly knowing only the public key. That is you can partially sign the assemblies during development with access only to the public key and fully sign the assemblies just before shipping your code to the customers. This way the private key can be stored securely out of the hands of the developers and allowing access to only few people.
Finally, the main purpose of delayed signing is to allow a company to protect and control its private key by using only the public key at the time of development and private key during the packaging process.

How Delay Signing Works?

A delay signed assembly contains only the public key token of the signing key, not an actual signature. Inside the PE (Portable Executable) file produced by a delay signed assembly, it has space reserved for a full signature to be placed in the future, but that signature is actually just a block of zeros until the real signature is computed. Because this block is not likely to be the actual signature value of the assembly, these assemblies will all fail to verify upon loading. Well, to overcome this issue you must configure the .NET Framework to skip verification for the delay-signed assemblies and have to reconfigure the .NET Framework to verify the assemblies after fully signed.
One important thing to note here, use the skip verification option only during development. Adding an assembly to the skip verification list creates security vulnerability. A malicious assembly could use the fully specified assembly name (assembly name, version, culture, and public key token) of the assembly added to the skip verification list to fake its identity. This would allow the malicious assembly to also skip verification. So, be sure to turn on verification after development and testing phase.
Delay signed assemblies serve to increase security by protecting private key. However, the requirement that delay signed assemblies need to be registered in the skip verification list means that developer’s machines are open to various forms of attack. Making sure that your developers are aware of the situation, in combination with not overusing your skip verification list will help to make your machines more secure in these environments.

How to: Delay Sign or Partially Sign an Assembly:-

Below is a summary of the delay signing process:

1) Extract the public key from the public/private key pair. This public key file can be distributed to the developers of your organization for partial signing of the assembly. There is no security risk with this as private key is stripped off and only pubic key is provided. To extract the public key from the key pair you need to use ‘sn’ tool with an option ‘-p’.

sn –p <key pair file name> <public key file name>
Example:
sn –p myKey.snk myPublicKey.snk
The above command strips off only public key portion from the key pair file myKey.snk and stores that public key in myPublicKey.snk file. Well, now you can distribute this myPublicKey.snk file to the developers of your organization for delay or partial signing.

2) Distribute the file containing only the public key to all of the developers in the company, and store the file containing both keys securely using ACLs or any other secure mechanism.

3) Include the public key file in your assembly information file (AssemblyInfo.cs or AssemblyInfo.vb), and specify delay signing using assembly attributes.
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("<public key file name>")]

Example:
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("..\\..\\MyPublicKey.snk")]


If you are using the assembly linker tool rather than assembly attributes, then use the /delaysign command-line switch to indicate delay signing.

al /delaysign /out:<assembly name> <module name> /keyfile:<keyfile name>
Example:
al /delaysign /out:MyApp.dll MyModule.netmodule /keyfile:myPublicKey.snk

If you are using the compiler options rather than Visual Studio, then use the /delaysign command-line switch to indicate delay signing.

<compiler> /delaysign /keyfile:<public key file> <application name>
Example:
csc /delaysign /keyfile:MyPublicKey.snk myApp.cs

If you are using Visual Studio, you can delay sign your assembly using the options in the Signing page of the Project Designer using delay sign option available on the page.

4) Now, if you try to load this assembly or run the application it will not load or run because it does not have a valid full strong name signature. You must configure the .NET Framework to skip verification for the delay-signed assemblies. You can do this by using ‘–Vr’ option of ‘sn’ tool.

sn.exe -Vr < assembly name >
Example:
sn.exe –Vr myApp.dll

The above command writes the assembly to the skip verification list along with the public key token. This list is used by CLR to skip the verification process of assemblies. This list is stored in the registry under

HKLM\Software\Microsoft\StrongName\Verification\<asmName,publicKeyToken>,

which is by default protected by an ACL such that anyone can read it, but only administrators can write to it. So, only the users with administrator rights can write to this list or ACLs need to be modified. Be cautious while making any changes to the ACLs for the above registry as it may open a security hole.
You can also use the sn.exe tool to skip signature verification for all assemblies signed with a particular key. For example, if you want to configure your machine to skip all assemblies delay signed with the same key as your application, for this first you need to know your public key token that is used in signing of your application. To know the public key token you can use ‘sn’ tool with an option of ‘-T’.
sn.exe –T <assembly name>
Example:
sn.exe –T myApp.dll
The above command prints out the value of the public key token, a shortened version of the public key used in signing of the application.
Now, use ‘sn’ tool with an option ‘-Vr *’ and with extracted public key to skip verification of all assemblies signed with the extracted public key token.
sn.exe –Vr *, <public key token>
Example:
sn.exe –Vr *, c07e5b7f21d50b3e
The above command skips the verification of all assemblies that are delay signed using the above mentioned public key.

5) At this point, it works well. You can use the delay signed assembly freely in development and while testing.

6) You use the real private key to generate the final full strong name signature before shipping your code or before deploying. For this again you need use the sn.exe tool to resign the assembly with private key using option ‘-R’.
sn.exe -R <assembly name> <key pair file name>
Example:
sn.exe -R MyApp.dll MyKey.snk
Now the assembly has a full signature. One of the pros about delay signing is that it does not require any of the assemblies that use the delay-signed assembly to be rebuilt. Any assemblies that refer to the delay-signed assembly had access to its public key and were therefore able to create a full assembly reference, even though the assembly did not have a full signature.

7) Finally, you can instruct the .NET Framework to resume verification for an assembly by using ‘sn.exe’ tool again with an option ‘-Vu’.
sn.exe –Vu <assembly name>
Example:
sn.exe –Vu myApp.dll
As I said earlier, you need to ensure the verification is turned on before shipping your code otherwise it would allow the malicious assembly to also skip verification.

Test Key Signing:

Test key signing is the new feature available in the .NET Framework 2.0. This is similar to delay signing. In test key signing you sign your assembly with an alternate private key during development and then configure your development computers to verify the signatures against the alternate public key that corresponds to the alternate private key. With delay signing, assemblies are not verified at all during the development or testing phase. This could hide performance issues because none of the strong name signatures would be verified during test runs when delay signing is turned on. So, test key signing is the one when you want almost the exact same behavior as full signing for testing purposes.
Here is a summary of the test key signing process:
Create Test key pair file using sn.exe tool with –k option.
Delay sign your assembly.
Test sign your assembly. You can do this using sn.exe and either the –TS or –TSc option. This will generate a signature for the assembly using the test private key.
Configure your .NET Framework to use the test public key to verify the test key signed assemblies. You can use the –Vr option of sn.exe tool.
Before shipping your assemblies, sign them with the real private key using sn.exe with either the –R or –Rc option.
Example:
sn.exe –k myTestKey.snk
sn.exe –TS myApp.dll myTestKey.snk
sn.exe –p myTestKey.snk myTestPKey.snk
sn.exe –Vr myApp.dll myTestPKey.snk
sn.exe –R MyApp.dll MyKey.snk
sn.exe –Vu myApp.dll

For more information on Strong Naming and Delay Signing refer to my previous posts:

Strong Naming and Delay Signing Of Assemblies: Part One
Strong Naming and Delay Signing Of Assemblies: Part Two

References:

Signing an Assembly with a Strong Name:
http://msdn2.microsoft.com/en-us/library/xc31ft41(VS.71).aspx
Delay Signing an Assembly:
http://msdn2.microsoft.com/en-us/library/t07a3dye(VS.80).aspx
CLR Inside Out:
http://msdn.microsoft.com/msdnmag/issues/06/07/CLRInsideOut/default.aspx

Add to Technorati Favorites