Time Stamping

If you are after validation when a piece of data was generated and verified. It is possible to sign arbitrary data with a timestamp in the same way as Authenticode.

Why would you want to do this? In my scenario I have a scanned image database, This database contains all the Proof of Delivery documents for a large transport company. Suppose I want to sign all the inward images at the time they were first imported into the database.

This level of protection costs about 2kb per image, and will provide assurance that the image has not changed since the timestamp was signed. It would not provide protection if the file is resigned. You could employ some sort of anti-replay protection.

To get started, for the proof of concept, suppose we want to sign “testfile.txt” with the text abcdxyz inside

# openssl ts -query -data "testtimestamp.txt" -cert -sha256 -no_nonce -out request.tsq

This will result in the request file “request.tsq” being generated. Which is essentially the SHA256 hash of test file.txt.

request.tsq
000 30390201 01303130  0d060960 86480165  |09...010...`.H.e|
010 03040201 05000420  073f5622 473e0b6b  |....... .?V"G>.k|
020 3f485afe fcadff10  b281b8df be81e308  |?HZ.............|
030 882cf331 e667f068  0101ff             |.,.1.g.h...|

This file is now served to the time stamping service of our choice.

# cat request.tsq | curl -s -S -H 'Content-Type: application/timestamp-query' --data-binary @- http://timestamp.globalsign.com/scripts/timestamp.dll -o response.tsr

You will then get a P7 response that contains the timestamp and signature of when the file signature was signed. This is the most important file to save for verification. You can also verify against the hashed request file, it will save you time when it comes to verifying large files.

The easiest way to display the signature time is through openssl again,

# openssl ts -reply -in response.tsr  -text

Status info:
Status: Granted.
Status description: unspecified
Failure info: unspecified

TST info:
Version: 1
Policy OID: 1.3.6.1.4.1.4146.2.2
Hash Algorithm: sha256
Message data:
    0000 - 07 3f 56 22 47 3e 0b 6b-3f 48 5a fe fc ad ff 10   .?V"G>.k?HZ.....
    0010 - b2 81 b8 df be 81 e3 08-88 2c f3 31 e6 67 f0 68   .........,.1.g.h
Serial number: 0x1DAAB7B41F40C33E4F29A4CC09BF0582A684BFCD
Time stamp: Sep  1 01:10:50 2020 GMT
Accuracy: unspecified
Ordering: no
Nonce: unspecified
TSA: DirName:/C=SG/O=GMO GlobalSign Pte Ltd/CN=GlobalSign TSA for Standard - G2
Extensions:

If you have the root certificate file you can also verify the signature chain through this method.

Saved Signature Verification
# openssl ts -verify -CAfile ./bundle.cer -in response.tsr -queryfile request.tsq 
Using configuration from /usr/lib/ssl/openssl.cnf
Verification: OK

Verifying directly against source file
# openssl ts -verify -CAfile ./bundle.cer -data testfile.txt -in response.tsr 
Using configuration from /usr/lib/ssl/openssl.cnf
Verification: OK

Testing whether the timestamp becomes invalid
# echo abcxyy > testfile.txt && openssl ts -verify -CAfile ./bundle.cer -data testfile.txt -in response.tsr 
Using configuration from /usr/lib/ssl/openssl.cnf
Verification: FAILED
139911881494976:error:2F064067:time stamp routines:ts_check_imprints:message imprint mismatch

Please be aware that to verify your certificate bundle, you already need a working trust store. Whether you built that trust store manually by concatenating multiple root and intermediate certificates you wish to trust or using the system trust model.

As expected if your source file changes but your verifying the TSQ against the TSR then it will still return it is valid.