I am trying to write some code to verify that a digitally signed file came from my company.

I was horrified to stumble across this deeply buried answer on Stack Overflow, an out-of-left-field possibility I had not considered and had certainly not coded for: https://stackoverflow.com/a/46770722

[I]t's possible for Authenticode to have multiple signatures. ...

WinVerifyTrust will tell you the file is valid if any of the signatures are valid and come from a trusted certificate chain. However it won't tell you which of the signatures was valid. ...

If you're using the details of the primary signature to validate that the certificate is one your software trusts, you're vulnerable to a situation where WinVerifyTrust is trusting a secondary signature, but your code is checking the primary signature's certificate is what you expected, and you haven't noticed that the signature from the primary certificate is nonsense. An attacker could use your public certificate without owning its private key, combined with some other code-signing certificate issued to someone else, to bypass a publisher check this way.

I really could not believe how poorly documented (and designed) this is.

So, what are all the possibilities people need to consider and should test their apps against (or even better, an equivalent of BadSSL.com for Authenticode would be amazing). So far I have:

Trusted (Standard Validation)
Trusted (Extended Validation)
Trusted (Unicode characters in certificate e.g. company name)
Trusted (Expired certificate with external timestamp made within validity of certificate)
Trusted (Self-signed certificate manually added to Trusted list)
Trusted (Weak hash)
Trusted (WHQL verified)

Untrusted (No certificate)
Untrusted (Certificate revoked)
Untrusted (Certificate expired and not timestamped)
Untrusted (Certificate expired and timestamped outside of validity period of certificate)
Untrusted (Certificate expired and timestamped by a non-trusted authority)
Untrusted (File Contents tampered with)
Untrusted (Self-signed, not trusted)
Untrusted (Insufficiently long key)
Untrusted (Certificate is issued in the same company name, by a Trusted CA, but company is registered in another country and is not your real company)
Untrusted (Malicious use of multiple certificates, some of which are invalid)

Other (Computer clock is wrong)

Are there any more possibilities to consider?

  • 1
    As a general rule, revoked signing certificate that was revoked after signing (determined by a timestamp) doesn't invalidate the signature. Revoked timestamping certificate doesn't invalidate the signature, but makes it non-stamped. – Crypt32 Jan 23 at 21:05
  • 1
    Trusted (Unicode characters in certificate e.g. company name) -- subject/issuer fields are often encoded with UTF8String or PrintableString ASN.1 types, which are not unicode. BMPString is used only when non-UTF8 characters are used in names. – Crypt32 Jan 23 at 21:07
  • 2
    @Crypt32: huh?! UTF8 can most certainly encode any Unicode characters; that's its entire reason for existing. When Unicode was new there was some interest in using UCS2 (now UTF16 = ASN.1 BMPString) and then UCS4 (ASN.1 UniversalString), but since 2008 rfc5280 says to prefer PrintableString and UTF8String (only) in subject&issuer names. – dave_thompson_085 Jan 24 at 10:32
  • UTF8 in ASN.1 uses 1 byte (8 bits) to store the character. I doubt that you can encode any unicode character with 1 byte. – Crypt32 Jan 24 at 10:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.