Do I need to publish the public key from .snk file?

ⅰ亾dé卋堺 提交于 2019-11-28 01:20:42

No, you don't need to publish your public key outside of the assembly since it is hashed and stored as a token alongside the reference inside the client's application:

AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07"

This gives a method to ensure that all future versions of the assembly are compiled against the same key pair and therefore from the same publisher.

More details about how having this information stops another source from pretending to be you can be found in my other answer.

I've always understood the purpose of signing an assembly to be a runtime check to ensure that upgrades to the code come from a trusted source. Effectively they are trying to avoid this kind of scenario:

I purchase a encryption library from Company A, shortly afterwards Company B gets hold of my email details and sends me a free upgrade to the assembly pretending to be a major security bug fix from Company A when it really injects a hidden method into my code that sends all the data I was trying to encrypt off to company B's servers. Assuming that I'm an idiot and blindly add this new dll into my application's bin directory the fact that this wasn't signed with the same private key as the old version will be picked up at runtime causing an exception and protecting my data.

So, I see no reason that you would publish the public key outside of the assembly since it isn't supposed to guarantee that the original file comes from a specific vendor, only that all subsequent versions come from the same place as the first.

Wikipedia says much the same thing (only in significantly fewer words).


Edited to add further information in an attempt to make this clearer...

I think the thing that needs to be clarified first is that the pairs of public and private keys are unique. That means that knowing the public key is not enough information to rebuild the assembly in a way that it will pass the same hash checks.

So User Z who is using an encryption library from Company A which is in his applications bin folder. To do this he is referencing the DLL as follows:

Encryption, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bcd6707151635d07"

The purpose of the public key is to provide us with three benefits which I'll handle one at a time.

Firstly, it provides a unique name for the assembly - this gives us no extra security but does stop C style dll Hell where two different companies could release two different libraries called Encyption version 1.0.0.0 and you wouldn't be able to store them in the same directory since there is no way to differentiate them.

Secondly, it prevents the scenario that I outlined in my original post. It is impossible for Company B to create another version of the Encryption library which is also version 1.0.0.0 and has the same public key (so that the whole name would match and you'd call their code instead of Company A's). They can't do this because if their public key matched then the private key must also match (since each pair is unique). The only way they can get the private key to match is by compromising Company A's security.

Finally it ensures the integrity of the file (either changed through corruption or malicious code injection). The dll is hashed at runtime (when it is private and in the bin folder of the application) or install time (when you put it in the GAC) using the public key and that hash is compared to the hash that was encrpyted by the private key and stored in the assembly. This page has some diagrams and more details. Once again the only way to fake this hash is to know the private key.

So, to cover the specific scenario that I described above, pretend that I am Company B trying to supply User Z with a malicious version of the encryption dll. My first attempt is to simply make my own dll with the name Encryption and Version 1.0.0.0 and sign it with my own key pair. Unfortunately I can't change the reference code in User Z's application so it fails the full name check and doesn't get loaded. "Okay," says I while twirling my moustache, "I'll simply change the public key of my assembly to match that of Company A's". Once I've done this the name check passes, but the hash check will fail because User Z's app won't be able to decrypt the hash stored in the assembly (which was encrypted with Company B's private key) with the public key (Company A's) that has been supplied. Therefore the only way for Company B to create a library that pretends to be Company A's is to know Company A's private key. None of these security checks are reliant on Company A publishing the public key anywhere else but in the original release of the assembly.

Note also that all of these features don't ensure (and don't claim to ensure) that the original assembly came from Company A, that is handled by other systems such as Verisign or Microsoft's Authenticode service, they only ensure that once you have referenced the assembly only Company A can make changes to that code.

  1. You can go to some 3d party certificate provider (e.g. VeriSign) and purchase a certificate from them (Code Signing At Verisign).
  2. You use given certificate that has your company name, URL, etc. on it to sign your code.
  3. I download you app, and look at the list of certificates your app was signed with.
  4. I use your certificate, go back to VeriSign and verify that the certificate has been indeed issued to MyCompany, LLC.
  5. I look at the certificates that has been used to issue your certificate, and verify that VeriSign is one of them (Windows comes with few trusted certificates installed).

Summary:
You not only verify that code has not been tinkered with, but also was signed with a certificate that was issued by a party you trust.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!