开发者

How to programmatically verify an assembly is signed with a specific Certificate?

My scenario is we have one program (exe) that will start other programs if found in a particular folder. I want to ensure it only ever starts programs which are signed with our Corporate certificate (Verisign approved etc). Essentially then it will only start the programs with the same certificate as itself. I don't want to ship the certificate itself.

I've been searching the web and the system namespace and haven't found a clear example that reads the certificate data from a file and also validates it, and can check against another file. The closest I've found is Signtool and and having this ve开发者_JAVA技巧rification in a separate exe is kind of point less. I know the Strong Naming stuff wont help because a digitally signed file is different as helpfully explained here (http://blog.codingoutloud.com/2010/03/13/three-ways-to-tell-whether-an-assembly-dl-is-strong-named/) Also some other examples in SO showing encryption and verification of raw data but not an assembly where it's packaged up together in some way.

Any ideas or suggestions?


Here's a blog post with code samples on how to verify assembly signatures:
http://blogs.msdn.com/b/shawnfa/archive/2004/06/07/150378.aspx

The code sample at the end shows how to verify if an assembly was signed by Microsoft or not - you can do the same by getting the certificate token for your company's certificate(s).

Update: user @Saber edited this with the following update, but that update was rejected by others. However, it is very valid advice, so I am reposting his/her edit since SO won't let me approve it:

Edit (thank you, OP): If you want to do this more securely (i.e. make your program more tamper-proof), reference an assembly in your program which is strongly named with the relevant key, then use the token of the referenced assembly to compare with the token of the calling assembly. If you use a byte arrays (as per the link), it can simply be hex edited and changed.


You can try three option here.

1) The first one is using Assembly load like here:

Assembly myDll =
    Assembly.Load("myDll, Version=1.0.0.1, Culture=neutral, PublicKeyToken=9b35aa32c18d4fb1");

You can print the hexadecimal format of the public key and public key token for a specific assembly by using the following Strong Name (Sn.exe) command:

sn -Tp <assembly>

If you have a public key file, you can use the following command instead (note the difference in case on the command-line option):

sn -tp <assembly>

2) The second one is mentioned here. And use p/Invoke for such issue.

3) Also exists third, more agile, and more complex way for doing this. This is a Binding Policy. You can take it into account in the case when you should to provide upgrades for an application that's already deployed. When a new version of a shared component comes out that your application can benefit from, an application policy file will allow you to provide these benefits without recompiling or replacing existing installations.

You can find more about this feature here:

http://msdn.microsoft.com/en-us/library/aa309359%28v=vs.71%29.aspx

http://ondotnet.com/pub/a/dotnet/2003/03/17/bindingpolicy.html


There exist two signing technologies for .NET assemblies: strongnaming and Authenticode (authenticode is used to sign PE and some other files, not just .NET assemblies). They are used for different purposes. Certificates are used in Authenticode only to authenticate the author. Strongnaming doesn't authenticate the author at all.

Besides checking the signature, the certificate must be validated to ensure that it was issued for given author. Proper validation is a complex procedure that involves CRL (certificate revocation list) and OCSP (online certificate status) checking.

To perform verification of Authenticode signature you need Authenticode verification component. One of the options is to use PKIBlackbox package of our SecureBlackbox product. The package includes Authenticode verification as well as complete certificate validation mechanisms.

Note that if you are not going to validate the certificate, there's no sense in verifying the signature at all, because one can create a self-signed certificate with the same Subject, Serial number etc., and use it to sign the forged assembly.


I believe there is a way to use strong name for the purpose of "Trust". I understand Microsoft only recommends strong name to ensure assembly contents have not been modified and suggests using "Authenticode" for trust.

But if the loader application (the application which loads these assemblies/programs) maintains an Encrypted list of "Assemblies" which it can load; wouldn't that solve the "Trust" problem?

For example, the package loader can maintain assembly name with public keys and loads the assembly/program via full assembly name?

<PackageHandlers>
  <PackageHandler>
    <Package type="Package1" assembyName="SomeAssembly" publickey="d45755dbb8b44e59" />
  </PackageHandler>
</PackageHandlers>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜