Strong Name Signing Using Smart Cards in Enterprise Software Production Environment

Encryption and signing software

 

Abstract

 Nice and seriously sounding title, huh? J. In fact I will tell you how to strong-name sign your assemblies using a key located on a smart card or any other conformant HSM (Hardware Security Module). Unfortunately this topic is not very well explained anywhere and there is a lot of confusion (well, most of people don’t know that it is even possible J).

 

Enterprise Software Production Environment

 A simplified view at the enterprise software production environment from SN-signing perspective includes 3 major processes: building, testing and release-signing. They normally should be happening in this sequence, too – first you build the software, then you test it, and then, when the testing signs off on its quality, you sign it with a real key and prepare for release. It is also possible that the software is signed immediately after it is built, but purely from security perspective this is discouraged because of the risks that buggy/vulnerable assemblies signed with a real key can be leaked and used maliciously.

 

The Process

 Building

The software building process does not require having a strong name secret key. It is recommended that the building process uses so called “partial” or “delayed“ signing. This type of signing does not really produce a valid signature (because there is no private key involved), rather it only embeds the public part of the key (which is freely available) into assemblies. To delay-sign an assembly you can put the following two attributes into one of its source files:

 

[assembly:AssemblyKeyFile("publickey.dat")]

[assembly:AssemblyDelaySign(true)]

 

Where “publickey.dat” contains the public portion of the strong name key pair. You can obtain this public portion file in several ways: grabbing it from other assembly signed with the same key (sn.exe –e …), extracting it from a full key pair file (sn.exe –p …) and pulling it from a key container on you HSM or your machine (sn.exe –pc …).

 

 Testing

Once you get assemblies delay-signed in this manner they are not usable unless the machines running them are told that the assemblies are delay-signed. If you want to test the code before you sign it with a real key, you have to register it on test machines for strong name verification skipping. This can be done by using SN.exe tool (included in .NET Framework SDK) in the following manner:

            sn.exe –Vr <assembly> [<userlist>]

 The <assembly> parameter can specify assembly names and public key tokens (don’t confuse them with public keys!) or a wildcard. The most common usage would look somewhat like this:

             sn.exe –Vr *,5823db31ac2fe204

 which would register all assemblies delay-signed by a key corresponding to the provided public key token for verification skipping. Public key tokens are shorter versions of public keys and are only used to identify the keys; you can easily obtain a public key token from a key pair file (sn.exe –t …) or from any signed or delay-signed assembly file (sn.exe –T …).

 When you have registered assemblies for strong name verification skipping the runtime thinks they are validly signed and you can test them as if they really were.

 

 Signing With a Real Key

Once the initial testing is done you can sign the assemblies for real. Normally it is done in a secure environment, where access to the company’s private key is very limited. A nice approach is storing the private key information on a HSM device, such as a smart card.

Given partially signed assemblies you have built, the thing you need to do now is to “re-sign” them. Sn.exe tool allows you to re-sign using a key pair stored in a file or in a key container. The command line is going to look like:

             sn.exe –R <assembly> <key_file>

 or

             sn.exe –Rc <assembly> <key_container>

 If you are using a smart card or other HSM, you first have to tell the strong-naming engine to use the right CSP (Crypto Service Provider). If you don’t do that it is going to use the default one and will likely look for a key container on your local machine rather than on a smart card.

To set the CSP you want to use run the SN tool with the following switch:

             sn.exe –c <CSP_name>

 Note, that after you have done it all strong name-related operations that require signing or key access will be using that CSP until you set it back to default.

 

 So, how do I know what CSP name to use?

Ok, first you have to find out what HSM device you are using. In case of a smart card it is easy – look at the card and either on the front or on the back you will find the smart card manufacturer or brand name. The two most common types are Schlumberger and GemPlus. Now that you know the name you can look for the right CSP. The cheapest way to do that is opening up a Registry Editor (regedit.exe) and navigating to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider key.

This key is going to have a bunch of sub-keys that represent different CSPs installed on your machine. Find the one that matches the name of your device. For example, for my Schlumberger card I would use the one named “Schlumberger Cryptographic Service Provider”, and my sn command line is going to be:

            sn.exe –c “Schlumberger Cryptographic Service Provider”

Once I have that set, I can run something like sn.exe –Rc myassembly.dll MyKey and be happy.

If for some reason you want the strong naming engine to get back to using the default CSP you have to use the sn.exe .c thing again, this time without a CSP name. It will reset the sn engine to the default CSP.

 

Getting the Key to the SmartCard

Ok, presumably if you want to sign with a smart card you already have a smart card with a key on it. There is a bunch of different ways to generate a key on a hardware device, and most of them have really nothing specific to .NET technology. Obviously, generating a key right on the device is the most secure way to approach this, but it could also happen that your company already has a key pair that was used in the past and now you want to move to using smart cards. In this case you will want to import the strong name key pair onto your device. Luckily there is an easy way to do that – run sn tool in the following manner (after you used the –c key to select the right CSP):

             sn.exe –i <key_pair_file> <key_container>

 

The Walkthrough

To make understanding all this stuff easier for you I’ve decided to list the steps I did on my machine to emulate the scenarios described in this document.

Here is what I did (starting with a machine with all default settings and a smart card reader attached and CSPs installed):

 

  1. Generated a new strong name key pair: sn –k MyKey.snk
  2. Switched to the smartcard CSP: sn -c "Schlumberger Cryptographic Service Provider"
  3. Imported the key pair into my smart card: sn -i MyKey.snk MyKey
  4. Deleted MyKey.snk – now I only have my private key on the smart card. If you already have a key on the device you can skip steps 1-3.
  5. Extracted the public key from my device into a file: sn -pc MyKey MyKey.pub
  6. Created a test C# program ScTest that had the following attributes:
                using System.Reflection;
                [assembly:AssemblyKeyFile("MyKey.pub")]
                [assembly:AssemblyDelaySign(true)]
  7. Compiled the assembly (I had to switch to the default csp “sn –c” to emulate the build machine that does not know anything about smart cards).
  8. Tried to run the assembly – it didn’t run because the strong name signature is invalid (we delay-signed it, but didn’t register for verification skipping).
  9. Got the public key token out of the assembly (sn –T sctest.exe) and registered it for verification skipping (sn -Vr *,4bf3e1cc9447bb8f)
  10. Ran the assembly again and made sure it runs fine.
  11. Now I “tested” my product and I am ready to sign it for real, so I am “switching” back to the signing machine: sn -c "Schlumberger Cryptographic Service Provider"
  12. Re-Signed the assembly with the real key from the smart card: sn -Rc sctest.exe MyKey
  13. Unregistered verification skipping: sn -Vu *,4bf3e1cc9447bb8f
  14. Ran my assembly and saw that it runs, which means that now it has a valid strong name signature.
  15. Finally ran “sn –vf sctest.exe” to explicitly verify the validness of assembly’s strong name.
  16. Switched back to the default CSP to not scratch my head in the future when I forget that I have a smart card CSP as my default SN CSP J sn –c

 

Whatever you may need for web site development, listening to iPodŽ, burning MP3s or viewing DivX or XVid movies you may find at our software download directory

 

(c) Ivan Medvedev    2004-2007