Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
Both strong naming and digital signatures use public key cryptography to provide evidence about the origin of an assembly, so that you can apply security policy to determine what permissions are granted to the assembly.
They differ most importantly not in their mathematical details, but in what problems they are intended to solve.
The purpose of a strong name is solely to ensure that when you load an assembly by name, you are loading exactly the assembly you think you are loading. You say "I want to load Frobber, version 4, that came from FooCorp". The strong name gear ensures that you actually load precisely that DLL, and not another assembly called Frobber, version 4, that came from Dr. Evil Enterprises. You can then set security policy which says "if I have an assembly from FooCorp on my machine, fully trust it." These scenarios are the only by-design purposes of strong names.
In order to achieve this, all that is required is that you know the public key token associated with FooCorp's private key. How you come to know that public key token is entirely your business. There is no infrastructure in place designed to help you get that information safely. You're just expected to know what it is, somehow. If evil people can trick you into believing that their key token is in fact FooCorp's key token, then you have a problem. You are expected to come up with some reasonable way to determine what FooCorp's real key token is.
The purpose of a digital signature from a publisher certificate is to establish a verifiable chain of identity and trust. The chain of trust goes from a hunk of code of unknown or uncertain origin up to a "trusted root" -- an entity which you have configured your operating system to trust.
You download some code, and the code has a digital signature with a certificate from FooCorp. You examine the certificate and it says "this program comes from FooCorp. The accuracy of this certificate is vouched for by VeriSign." Since VeriSign is one of your trusted roots, you now have confidence that this code actually did come from FooCorp.
Notice how much more complex the problem solved by digital signatures is. We're not trying to simply determine "is this hunk of code associated with this name or not?" Instead we're trying to determine where did this code come from, and who vouches for the existence of the company allegedly responsible, and should we trust that company?
The difference between strong names and digital signatures emphasizes what is hard about crypto-based security. The hard problem isn't the cryptography; that's just math. The hard problem is safely managing distribution of information about the keys and associating them with the correct entities. Strong names, because they attempt to solve a very small but important problem, do not have key management issues. Or, rather, they foist the key management problem off to you, the user. Digital signatures are all about trying to automate safe distribution of key information via certificates, in order to solve much more complex problems of trust and identity.
Hey Eric, could you forward some of your blog posts to the MSDN documentation team. It would be a real asset to have this sort of background information on much of the MSDN content which unfortunately is too terse a lot of the time.
If I had a dolllar for every time I have had to explain this to a client I probably would retire....(ok, maybe a bit more than a dollar)
One other "detail" that I have found people get "confused" on, is they believe:
That "version" means a spcific bit pattern result (rather than just the "identified version"). It is possible (and even common in some shops) for there to be many DIFFERENT revisions of assemblies with the SAME version number during early development.
Eric, I don't believe this is really accurate. A public key token is only 64 bits out of a 160 bits SHA-1 hash of the public key. SHA-1 is already considered "broken", so I is very unlikely that a 64 bit partial SHA-1 can be considered a cryptographically secure hash.
At this point (and I'm prerty sure I've seen guidance from Microsoft saying this early on in .NET's life) a strong name (that uses a public key token, instead of the full public key) is nothing more than an elaborate mechanism to prevent name clashes when naming assemblies.
@Jeroen - your point has validity, but there is another aspect to consider when any type of hash/key is used to identify something [not just .Net assemblies]
Note: The following is a more general discussion than the specifics of Strong Names, but does relate directly to this topic....
Lets assume we have a binary item "I" of size B [begause it is "B"ig], and we are going to identify it with a hash/key "H" withe a length of "L".
In many items there are bits which can be modified WITHOUT IMPACTING the functionallity of the item. i.e. these bits will impact the calculation of the hash/key, but if changed would not result in a difference in operation. A common example are bits which are used for padding. We will call the number of suchs bits "R" [because they can be "R"andom from a functionallity point of view.]
What is critical is that if R>L then BY DEFINITION there are at least 2 different items with identical functionallity that will generate the same hash/key because there are more possible items than there are unique keys.
The situation becomes even more interesting when "exact functionallity" is replaced with "apparant functionallity" (i.e. compatabile API).
The end result is that general purpose "Identification" by any hash/key should [IMHO] be only one part of he solution.
From a legal perspective, although Verisign may vouch for the authenticity of your public key, how much money they put behind that "vouch" in their terms and conditions is another question entirely.
To makes things easier, the Visual Studio Project Properties->Signing settings are actually to strong name the assemblies (rather than digitally signing them)...