Search code examples
securitycertificatex509truststore

Method to verify a signed archive's X.509 CoT


I am trying to understand the key high level details behind verifying trust when downloading an archive.

This is my understanding of how it could be done:

On the Software Developer side:

  1. Obtain a certificate from a public CA like verisign

  2. Generate a hash of your archive and then encrypt this string using the private key from your certificate, this is the "signature"

  3. Host the archive for download, along with a separate file which contains the public key from your certificate + the signature generated in step 2.

On the (user) client side:

  1. Download and unpack the archive, download the signature + public key file

  2. Decrypt the downloaded signature using the downloaded public key, save this value

  3. Iterate through the public root certificates embedded within your operating system. For each root certificate, decrypt the signature value and compare the result to the result in step 5.

  4. Once a match is found in 6, you have verified that the author's private key descends from the chain of trust of the CA which you found matched in step 6.

    • This all assumes that the software developer used a CA for which we have an embedded root certificate in our clients OS.

Questions:

  1. Is the above method sound, or am I overlooking key details?
  2. Given a blank slate client that you control, if I wanted to combine the public key + signature + archive into a single file that I could make the client understand and parse, are there any widely supported formats to leverage for organizing this data?

Solution

  • Aside from being a little too specific on Developer (2) (that describes how RSA signatures work, but ECDSA is perfectly well suited to this task) that sounds rather like Authenticode minus some EKU restrictions. This leads me to ask "why not use Authenticode signing?".

    The structure I'd consider is the PKCS#7/CMS SignedData format. It can describe multiple signatures from multiple certificates (sign it ECDSA-brainpoolP320t1-SHA-3-512 for anyone who can read it as well as RSA-2048-SHA-2-256 for most of us, and DSA-1024-SHA-1 for anyone whose computer was built in 2001).

    For data file you can just use SignedData normally, for executables it's harder since there are semantic portions (so you have to squirrel it away somewhere and use indirect signing).

    If you do your signing with .NET, PKCS#7/CMS SignedData is available for both signing and verifying via System.Security.Cryptography.Pkcs.SignedCms (though you probably have to define your own chain trust rules outside of that class).