I'm a newbie with digital signing and you'll have to take a BIG step back to have me understand this
Ok, let's take a big step back and ask some more basic questions then. I'll boldface every word that has a precise meaning.
What is the purpose of a security system?
To protect a resource (a pile of gold doubloons) against the threat of successful attack (theft) by a hostile party (a thief) who seeks to take advantage of a vulnerability (an unlocked window). (*)
How does .NET's Code Access Security work in general?
This is a sketch of the .NET 1.0 security system; it is rather complicated and has been more or less replaced by a somewhat simpler system, but the basic features are the same.
Every assembly presents evidence to the runtime. A domain administrator, machine administrator, user and appdomain creator each may create a security policy. A policy is a statement of what permissions are granted when a certain piece of evidence is present. When an assembly attempts to perform a potentially dangerous operation -- that is, an operation that might be a threat to a resource -- the runtime demands that the permission be granted. If the evidence is insufficient to grant that permission then the operation fails with an exception.
So for example, suppose an assembly presents the evidence "I was just downloaded from the internet", and the policy says "code downloaded from the internet gets permission to run and access the printer" and that code then attempts to write to C:\Windows\System32. The permission was not granted because of insufficient evidence, and so the operation fails. The resource -- the contents of the system directory -- are protected from tampering.
What is the purpose of signing an assembly with a digital certificate that I got from VeriSign?
An assembly signed with a digital certificate presents evidence to the runtime describing the certificate that was used to sign the assembly. An administrator, user or application may modify security policy to state that this evidence can grant a particular permission.
The evidence presented by an assembly signed with a digital certificate is: this assembly was signed by someone who possessed the private key associated with this certificate, and moreover. the identity of the certificate holder has been verified by VeriSign.
Digital certificates enable the user of your software to make a trust decision on the basis of your identity being verified by a trusted third party.
So how does that protect my DLL?
It doesn't. Your DLL is the crowbar that is going to be used to jimmy the window, not the pile of gold coins! Your DLL isn't a resource to be protected in the first place. The user's data is the resource to be protected. Digital signatures are there to facilitate an existing trust relationship. Your customer trusts you to write code that does what it says on the label. The signature enables them to know that the code they are running really came from you because the identity of the author of the code was verified by a trusted third party.
Isn't strong naming the same thing then?
Strong naming is similar, in that a strong-named DLL presents cryptographically strong evidence to the runtime that the assembly was signed by a particular private key associated with a particular public key. But the purpose of strong naming is different. As the term implies, strong naming is about creating a name for an assembly that can only be associated with the real assembly. Anyone can make a DLL named foo.dll, and if you load foo.dll into memory by its weak name, you'll get whatever DLL is on the machine of that name, regardless of who created it. But only the owner of the private key corresponding to the public key can make a dll with the strong name foo, Version=126.96.36.199, Culture=en, PublicKeyToken=03689116d3a4ae33 .
So again, the purpose of strong naming is not directly to facilitate a trust relationship between a software provider and a user. The purpose of strong naming is to ensure that a developer who uses your library is really using the specific version of that
library that you actually released .
I notice that VeriSign wasn't a factor in strong naming. Is there no trusted third party?
That's right; with a strong name there is no trusted third party that verifies that the public key associated with a given strong name is actually associated with a particular organization or individual.
This mechanism in digital certificates facilitates a trust relationship because the trusted third party can vouch that the public key really is associated with the trusted organization. Lacking that mechanism, somehow the consumer of a strong name needs to know what the public key of your organization is. How you communicate that to them securely is up to you.
Are there other implications to the fact that there is no trusted third party when strong naming?
Yes. Suppose for example that someone breaks into your office and steals the computer with the digital certificate private key on it. That attacker can now produce software signed with that key. But certifying authorities such as VeriSign publish "revocation lists" of known-to-be-compromised certificates. If your customers are up-to-date on downloading revocation lists from their certifying authorities then once you revoke your certificate, they can detect that your software might be from a hostile third party. You then have the difficult task of getting a new cert, re-signing all your code, and distributing it to customers, but at least there is some mechanism in place for dealing with the situation.
Not so with strong names. There is no central certifying authority to appeal to for a list of compromised strong names. If your strong name private key is stolen, you are out of luck. There is no revocation mechanism.
I took a look at my default security policy and it says that (1) any code on the local machine is fully trusted, and (2) any code on the local machine that is strong-named by Microsoft is fully trusted. Isn't that redundant?
Yes. This way if the first policy is made more restrictive then the second policy still applies. It seems reasonable that an administrator might want to lower the trust level of installed software without lowering the trust level of the assemblies that must be fully trusted because they keep the security system itself working.
But wait a moment, that still seems redundant. Why not set the default policy to "(1) any code on the local machine is trusted (2) any code strong-named by Microsoft is fully trusted"?
Suppose a disaster strikes and the Microsoft private key is compromised. It is stored deep in a vault under building 11, protected by sharks with laser beams, but still, suppose that happened. This would be a disaster of epic proportions because like I just said, there's no revocation system. If that happened AND the security policy was as you describe then the attacker who has the key can put hostile software on the internet that is then fully trusted by the default security policy! With the security policy as it actually is stated -- requiring both a strong name and a local machine location -- the attacker who has the private key now has to trick the user into downloading and installing it.
This is an example of "defense in depth". Always assume that every other security system has failed, and still do the best to stop the attacker.
As a best practice you should always set a strong name or digital signing policy to include a location.
So again, strong naming isn't to protect my DLL.
Right. The purpose of the security system is never to protect you. the software vendor, or any artifact you produce. It is to protect your customers from attackers who seek to take advantage of the trust relationship between your customers and you. A strong name ensures that code which uses your libraries is really using your libraries. It does this by making an extremely convenient mechanism for identifying a particular version of a particular DLL.
Where can I read more?
I've written an entire short book on the .NET 1.0 security system but it is now out of print, and superseded by the new simplified system anyways.