1

I'm currently in the process of writing a program that:

  1. Reads a binary file (a C++ program) and creates a SHA256 hash of the data (like a checksum)
  2. Use this calculated hash and a self signed CA certificate to create a CMS signature using the openssl crypt library
  3. Verify the signature using the openssl library and additionally checking if the SHA256 hash embedded in the signature matches a newly calculated hash of the same data

This part is working and I am able to create a signature and verify it.

Now my problem is, that the signature should be valid for multiple years and most likely must be valid after the CA certificate expired. I understand that for this I must use a TSA (Timestamp Authority) to prove, that the signature was created at this specific date.

But how do these two parts (CMS signature and Timestamp) interact? If i create a timestamp request and with that a timestamp response containing a timestamp token, how can that be used to verify the signature is still valid even after expiration? I don't see any information in the timestamp response that would indicate the original (and external?) signature?

Xershy
  • 13
  • 2

1 Answers1

1

Typically when creating a timestamp, you send a hash of the data you want timestamped (and the hash algorithm used to generate it). So, you create your signature (which may involve hashing your data), and then you hash the signature itself, and send that to the TSA. The TSA will return this hash+algorithm (the "messageImprint"), along with the time and its own signature, in the response token. Because the TSA's response (the "TimeStampToken") contains a hash of the original data (your signature), plus a timestamp, and is signed by the TSA, you can check the validity of the TSA's signature and if it's valid (and you trust the TSA), be sure that your signature existed at the specified timestamp. You can then (or first, if you want) verify that your CA's signature was valid at that time.

More specifically, the response token is "SignedData" in CMS (Cryptographic Message Syntax). The signature on the CMS is generated by the TSA. The content of the CMS includes the "messageImprint" that you supplied (the hash of your original signature, plus the algorithm used to hash it), plus the "genTime" when the timestamp was generated.

To verify a timestamp, you obtain the TSA's public key, and use the public key to verify the signature on the CMS. Assuming that checks out, you parse the CMS and extract the "messageImprint" from its content. You use the hash function specified in the "messageImprint" to hash the data (original signature that your tool generated), and see if it matches the hash in the messageImprint. If it does, then you know the timestamp was generated from that original data (your program's signature). Then you can check the "genTime" to see when the timestamp was created. Once you know the TSA's signature is valid, and that the signed data is your CA's signature, you can verify the CA's signature using its public key, and check that the timestamp from the TSA is during the CA's certificate's validity period (e.g. using the -attime flag to openssl -verify, or using the -no_check_time flag plus manually verifying).

Note, of course, that all this relies on the TSA having a strong, well-protected private key that it maintains for many years. An attacker who compromises that private key could forge timestamps of arbitrary data for arbitrary points in time.

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • But how can I verify that the signature was signed by my CA certificate? Lets use the openssl CLI for that example: ```openssl cms -verify -in sig -CAfile cacert.crt```. It would now check, amongst other things, if the CA is the signer (or an intermediate cert issued by the CA) for the signature. But by using the signature received by the TSA i need to verify this signature with the cert of the TSA right? So how does that get verified? Using the Timestamp token and adding it to the existing cms (my signature) isn't a possibility? Or do I have to check both? How does it work when my CA expired? – Xershy May 31 '22 at 12:33
  • @Xershy verifying that any signature was signed with any key requires three things: the signed data, the signature itself, and the public key (embedded in the certificate). To tell if the original data was signed by your CA, you need the original data, the signature, and the CA's cert. Same as you do now. To _further_ tell if that signature was created while the cert was valid, you need the timestamp token (which contains both the signed data - including a hash of your original signature, plus the timestamp - and the TSA's signature) and the TSA's cert. – CBHacking Jun 01 '22 at 04:25
  • In other words, yes, you have to check both. You can do it in either order, but you have two signatures here - one of which you created, and one the TSA created from (hash of your signature | timestamp) - and you need to verify them both. – CBHacking Jun 01 '22 at 04:27
  • I see, i think I got it now, thanks for the awesome explanation! One thing is still unclear to me tho, If i have to verify that both my signature and the signature of the TSA is valid, wouldn't the verification process of my own signature fail after the validity of my CA is expired? For example the command ```openssl cms -verify -in sig -CAfile cacert.crt``` would fail, right? On the other hand the validity of the TSA's signature should be valid as long as their public key is valid, if I understood that correct. – Xershy Jun 01 '22 at 06:59
  • Right, you'd want the `-attime` flag (specifying the time in the timestamp) to confirm that the cert was valid _at that time_, or just check manually and pass `-no_check_time` to `openssl`. See https://www.openssl.org/docs/man3.0/man1/openssl-verification-options.html for more info on those options. Also, if the answer helps, please click the up arrow next to it (and the checkmark, if it answers your question) to help people know what answers were useful. – CBHacking Jun 01 '22 at 08:27