locked
Requiring valid assembly signature RRS feed

  • Question

  • Hello,
    I have created a .NET executable assembly, signed it using signtool.exe, opened it in a hex editor and changed some bytes of copyright info or so, so that the signature gets invalid. If I then try to execute the file, absolutely nobody complains, and actually to find out that the executable has invalid signature, I need to want to see the certificate details in the file properties. I simply can't believe it...

    Anyway, is there any possibility, at least for managed code, at least for my code, to force the CLR to not execute it if the signature does not match? Like adding some security attribute to the assembly...

    Thanks, Jan
    Thursday, October 8, 2009 10:29 PM

Answers

  • You are talking about two different kind of signatures.  Signtool adds a digital signature that needs to be verified through an independent trusted authority like Verisign so that the client can verify that it came from you.   You are looking for strong naming, done by the sn.exe tool.  .NET verifies that when the binary file came from an untrusted location, it will detect tampering with the file content.  Beware that your hard drive is not an untrusted location.  Neither is the local network since .NET 3.5 SP1.  This can be overridden with caspol.exe.

    Hans Passant.
    Friday, October 9, 2009 12:44 AM
  • Thanks Hans! I'd like to supplement some infomation:

    http://blogs.msdn.com/shawnfa/archive/2005/12/13/502779.aspx
    This document explains the difference between Authenticode Signatures and Strong Name Signatures in detail. The "Signature Verification Errors" may be paticularly interesting to you.

    1. Authenticode Signatures:

    When the CLR loads an assembly which has an Authenticode signature, it will always try to verify that signature. If the assembly fails to verify, the loader will not reject it!  Instead, the assembly will continue to load, but will not be granted the PublisherIdentityPermission associated with the certificate.  This means that it will not match PublisherMembershipCondition code groups, and will fail demands for the associated permission (unless this is v2.0 and the assembly is FullTrust, since FullTrust means FullTrust).

    In other words, if your application is not running on .net 2.0, and it's not FullTrust, you may consider demanding PublisherIdentityPermission, then quiting the process if the demand fails.

    2. Strong Name Signature

    A strong name verification error will cause the CLR to refuse to load the assembly (unless it is delay or test signed, and registered for skip verification). This looks what you are looking for, as mentioned by Hans. More reading about strong name signature can be found in http://msdn.microsoft.com/en-us/magazine/cc163583.aspx

    Regards,
    Jialiang Ge

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, October 9, 2009 9:37 AM
  • 1a) How can I validate the authenticode signature of any file from code?
    Do you really want it for any file type, or just for .NET assemblies?



    1b) Does .NET framework makes the authenticode signature of assembly accessible somehow, like via reflection or so?
    If the signature is valid, it will be exposed as Publisher evidence (http://msdn.microsoft.com/en-us/library/system.security.policy.publisher.aspx) for the assembly.  However, you may want to keep in mind that generation of Publisher evidence can be disabled via configuration (http://blogs.msdn.com/shawnfa/archive/2007/05/07/bypassing-the-authenticode-signature-check-on-startup.aspx).  Then again, presumably anyone who can modify your config could also presumably modify your assemblies.


    2) Does the strong naming require assemblies loaded via Assembly.Load/Assembly.ReflectionOnlyLoad to be also strong named?
    The CLR requires that _referenced_ assemblies of strongly named assemblies also be strongly named.  There's nothing stopping you from using Assembly.Load to load an assembly that isn't strong named from code in assembly that is strongly named, although this isn't necessarily the best idea in the world.  Also, I'm not sure how this addresses your underlying problem, which you've never really revealed.  Perhaps you might tell us what you are trying to accomplish instead of asking about side issues that emerge from your attempted solutions...
    Friday, October 9, 2009 1:47 PM

All replies

  • You are talking about two different kind of signatures.  Signtool adds a digital signature that needs to be verified through an independent trusted authority like Verisign so that the client can verify that it came from you.   You are looking for strong naming, done by the sn.exe tool.  .NET verifies that when the binary file came from an untrusted location, it will detect tampering with the file content.  Beware that your hard drive is not an untrusted location.  Neither is the local network since .NET 3.5 SP1.  This can be overridden with caspol.exe.

    Hans Passant.
    Friday, October 9, 2009 12:44 AM
  • Thanks Hans! I'd like to supplement some infomation:

    http://blogs.msdn.com/shawnfa/archive/2005/12/13/502779.aspx
    This document explains the difference between Authenticode Signatures and Strong Name Signatures in detail. The "Signature Verification Errors" may be paticularly interesting to you.

    1. Authenticode Signatures:

    When the CLR loads an assembly which has an Authenticode signature, it will always try to verify that signature. If the assembly fails to verify, the loader will not reject it!  Instead, the assembly will continue to load, but will not be granted the PublisherIdentityPermission associated with the certificate.  This means that it will not match PublisherMembershipCondition code groups, and will fail demands for the associated permission (unless this is v2.0 and the assembly is FullTrust, since FullTrust means FullTrust).

    In other words, if your application is not running on .net 2.0, and it's not FullTrust, you may consider demanding PublisherIdentityPermission, then quiting the process if the demand fails.

    2. Strong Name Signature

    A strong name verification error will cause the CLR to refuse to load the assembly (unless it is delay or test signed, and registered for skip verification). This looks what you are looking for, as mentioned by Hans. More reading about strong name signature can be found in http://msdn.microsoft.com/en-us/magazine/cc163583.aspx

    Regards,
    Jialiang Ge

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, October 9, 2009 9:37 AM
  • Hello, thanks both for your replies.

    I cannot use strong name signature as this requires all the referenced assemblies to by strong named (right?), which is not my case and I can't do anything with it.

    I was indeed talking about authenticode signatures, and while writing reply to Hans I did found the PublisherIdentityPermission, this seems to be what I need. However I cannot manage it to fail. Since I have no experience with permissions, could you please give me some example?

    I've tried to apply

    [

     

    assembly: System.Security.Permissions.PublisherIdentityPermission(System.Security.Permissions.SecurityAction.RequestMinimum)]


    but not sure how to demand (tried the same with Security.Demand action on the entry point). The above attribute causes the application to throw an exception only if RequestOptional is set and a debugger is attached.

    Thank you,
    Jan
    Friday, October 9, 2009 9:54 AM
  • PS. (Hans, as long as unmanaged code is considered, I know that trusted party is required to validate the certificate, but not to validate the signature itself. I expected at least to be warned that something is that wrong.)

    Friday, October 9, 2009 10:11 AM
  • Jan,

    There are a few problems with this approach:

    1. When using PublisherIdentityPermissionAttribute, you need to specify one of the CertFile, SignedFile, or X509Certificate properties in order to provide the publisher evidence that you expect to see on the assembly.
    2. In .NET 2.0 and higher, an unrestricted permission grant (aka "full trust") includes all identity permissions, regardless of whether an assembly actually provides evidence matching the identity condition.  In other words, all fully trusted assemblies will be granted your PublisherIdentityPermission, even if they are not signed with the specified publisher key.
    3. If someone is going to modify your assembly after signing, what's to stop them from removing your RequestMinimum attribute?

    Publisher evidence is much more useful for granting permissions to code via CAS policy than it is for trying to control the permissions of your own assemblies via attributes.

    Friday, October 9, 2009 11:35 AM
  • And what's to stop them removing the signature completely... I am aware of that.

    Okay seems this does not have a solution.

    So, two unrelated questions remain to me:

    1a) How can I validate the authenticode signature of any file from code?
    1b) Does .NET framework makes the authenticode signature of assembly accessible somehow, like via reflection or so?

    2) Does the strong naming require assemblies loaded via Assembly.Load/Assembly.ReflectionOnlyLoad to be also strong named?

    Thanks,
    Jan

    Friday, October 9, 2009 12:57 PM
  • 1a) How can I validate the authenticode signature of any file from code?
    Do you really want it for any file type, or just for .NET assemblies?



    1b) Does .NET framework makes the authenticode signature of assembly accessible somehow, like via reflection or so?
    If the signature is valid, it will be exposed as Publisher evidence (http://msdn.microsoft.com/en-us/library/system.security.policy.publisher.aspx) for the assembly.  However, you may want to keep in mind that generation of Publisher evidence can be disabled via configuration (http://blogs.msdn.com/shawnfa/archive/2007/05/07/bypassing-the-authenticode-signature-check-on-startup.aspx).  Then again, presumably anyone who can modify your config could also presumably modify your assemblies.


    2) Does the strong naming require assemblies loaded via Assembly.Load/Assembly.ReflectionOnlyLoad to be also strong named?
    The CLR requires that _referenced_ assemblies of strongly named assemblies also be strongly named.  There's nothing stopping you from using Assembly.Load to load an assembly that isn't strong named from code in assembly that is strongly named, although this isn't necessarily the best idea in the world.  Also, I'm not sure how this addresses your underlying problem, which you've never really revealed.  Perhaps you might tell us what you are trying to accomplish instead of asking about side issues that emerge from your attempted solutions...
    Friday, October 9, 2009 1:47 PM
  • Hello Jan

    The thread hasn't been updated for a long time. May I know the current status of the issue on your side?

    Regards,
    Jialiang Ge
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, October 22, 2009 8:41 AM
  • Hello, I am facing what I think is a similar problem. In the company I work, I am making some web server controls, using an snk for signing them. Everybody in the company actually have a copy of the same snk file. I want to use signtool to sign my server controls with another certificate, and deny the execution of my control to everyone until they install the same certificate on their machines. How can I validate if the same certificate used to sign my assembly is installed on the developer machine?

     

    Thank you so much.

    Tuesday, June 21, 2011 10:02 PM