Tuesday 4 July 2017

Assemblies 02 Signing

To Recap, .net uses four pieces of information to identify an Assembly:
  • Name 
  • Version 
  • Public Key 
  • Culture 
Now when you omit the public key .net only uses the assembly name/title as identification, the version number is inconsequential if the public key is not specified.

so what does it mean to specify a public key? basically you're guaranteeing that this assembly is legit and comes from you or your organization. This will prevent your assembly (dll or exe) from being overridden by one with the same name coincidentally or maliciously.

When you create a "Strong Name" for your assembly you give it a Public Key other wise it's just known as a "Regular Assembly". Regular assemblies are what Visual Studio creates by default, the difference between the two is that a strong named assembly contain a public/private key pair. A strongly Named Assembly has several benefits
Uniqueness - the public key is used to Identify the assembly which guarantees that it'll be unique.
Versioning - because of the public private key relationship users can be certain that an upgraded version of your assembly originates from the legitimate publisher.
Integrity - the .net framework sees whether a strong named assembly has changed since the moment it was signed. A strongly named assembly ensures its' origin. An assembly is signed by the private key and then verified by via the public key.

There are two ways to generate a private public key pair known as a "strong named key" or .snk file. The first way is to use the strong name tool on the the the developer command prompt. type in sn and hit enter to see all your switches:



we are interested in -k Generate a new key pari of the specified size and write it into, so lets do that "sn -k myKey.snk"



now if we open the myKey.snk file up we'll see



we see gibberish, but what we're actually looking at is the public and private keys. so lets take a look at the public key using sn -p myKey.snk myPublicKey.txt


if we open that file up we:



still see gibberish, now if we use the -tp switch on our public key file we can view our actual public key



and it's a big Hex number, no two keys are ever going to be the same. A public key token is a hash of the public key. When the assembly is complied it's signed using the private key file, think of it as a seal. if someone else where to get your seal they could package assemblies using your seal.

Now let's say we had a supper critical library such as the following

using System;

namespace Assemblies
{
    public class Program
    {
        public static void SaySomething()
        {
            Console.WriteLine("Woot Woot");
        }
    }
}

and wanted to compile it into a dll we would type:
csc /keyfile:mykey.snk /t:library /out:lib.dll program.cs



and bam we have our signed dll. Now if we want we could instead go through visual studio, right click on your project, select properties and hit the signing tab, straight forward from there.



Now your assembly is only as secure as your private key, meaning that not everyone should have access to the key file, to avoid distributing it to the entire team you can check of "Delay sign only", this will only sign the project with the Public key.

All signing an assembly proves is that whoever signed it has access to the private key.
So basically:

  • create a key 
  • sign your assembly using the key 
    • signed assembly contains the public key as an attribute 
  • when you reference the signed assembly,  the referencing assembly uses the public key token 
    • if the signed assembly is swapped, the calling assembly will check its pk token against the public key of the signed assembly and if it doesn't line up, the calling assembly will throw an error.