Strong Naming Notes
I noticed earlier in the week that someone pointed out that you can use ILDASM to pull out the strong-name from a strong-named assembly, and recompile using a different key. I remembered an article I came across on MSDN that talked about this, so I thought I'd quote it here.
Most of the wizard-generated projects in Microsoft Visual Studio® .NET place this attribute in a file called AssemblyInfo, but you can put it in any source file you like. When the compiler sees this attribute, it copies the entire public key into the assembly's metadata, and uses the private key to form a digital signature. This is done by hashing the files in the assembly, incorporating those hash values into the manifest for the assembly, hashing the manifest, and, finally, encrypting this final hash value using the corresponding private key and tucking it away as yet another block of metadata in the assembly.(Note that using this simplistic approach, the compiler needs to have not only the public key, but the private key as well, from the file c:\temp\mykeyfile. You'll see a safer way to approach code signing later in this article.)
If you look at an assembly's manifest using ILDASM, you'll be able to see its public key quite plainly, as shown in Figure 1.
Figure 1. A public key assigned to an assembly
What you won't see is the signature or the intermediate hash values. This sometimes confuses people who are learning about strong names. ILDASM doesn't show these things because ILDASM is a disassembler—it is supposed to produce IL that can be compiled into an assembly, and remember that the signature and hash values are output by the compiler (which would be ILASM in this case).
So there you have it. Just because you can use ILDASM doesn't mean you'll be able to access everything in an assembly. You can change the public key, but you won't be able to change the signature or the hash. By changing the public key, you'll render the signature invalid, and the assembly will fail to load.
Now, what they can do is delay-sign malicious code using your public key, and spoof any publicly available delay-signed assemblies... and very easily, I might add. This is why, you should NEVER let unsigned or delay-signed assemblies outside whatever environment you develop in. If you're a third party component developer, and you're releasing unsigned assemblies.... SHAME ON YOU.
I might note that the point (at least from Microsoft's perspective) was to not be able to substitute assemblies in a componentized environment. If you built the program with a strong named assembly system, the name, version number, culture code, and public key hash are stored in the manifest. If the runtime comes across an assembly with the same weak name but missing or incorrect strong name, it will fail to execute.
This prevents someone from building an assembly with the same names and methods but does something bad, like deleting everything out of the "Program Files" directory or something. Even if they could recompile an assembly without signatures, and had physical access to your server to replace it, it still would not work.
What really needs to happen is twofold.... there needs to be an Identity Authority to be able to have certificates specific to the publisher that can be authenticated, revoked, etc (kind of like Authenticode, but I don't belive that works for .NET), and you need to be able to encrypt assemblies using a PKI, and have the assemblies decrypted in protected memory (NGSCB anyone?) and then executed. That would stop people from disassembling production assemblies, and compormising security.