openssltimestamprfc3161

OpenSSL: how to extract certificates and token status from RFC3161 timestamping reply?


using openssl ts (https://www.openssl.org/docs/man1.1.0/man1/openssl-ts.html) I can create TS queries, replies, extract tokens from replies and verify tokens (if I have the signing certificate in DER format) of the RFC3161 format as specified here: https://www.ietf.org/rfc/rfc3161.txt

To get a token, I can do:

openssl ts -query -digest 899ba3d9f777e2a74bdd34302bc06cb3f7a46ac1f565ee128f79fd5dab99d68b -sha256 \
| curl -s -H "Content-Type: application/timestamp-query" -H "Accept: application/timestamp-reply" --data-binary @- https://freetsa.org/tsr > response.tsr
openssl ts -reply -in response.tsr -token_out -out token.tk

I can also print the response in human readable form using openssl ts -reply -in response.tsr -text

To verify the token, I need to provide the parameter

-CAfile trusted_certs.pem
The name of the file containing a set of trusted self-signed CA certificates in PEM format.
The file should contain one or more certificates in PEM format.

Question 1:

Why does this only require the trust-anchor (=self-signed) certificate and not the whole chain down to the TSA certificate (or does -verify only work with tokens for which the certificate chain has been included in the token)?

Question 2:

-cert
The TSA is expected to include its signing certificate in the response.

If I specify the -cert parameter in the first openssl call, then token.tk will be longer and also contain the certificate that was used to sign it. How can I extract that certificate from token.tk?

Question 3:

I'm surprised that token.tk gets longer when I request the response to include the certificates (I would have assumed only response.tsr to get longer, not the token itself), since the specification specifies TimeStampToken like so:

   A TimeStampToken is as follows.  It is defined as a ContentInfo
   ([CMS]) and SHALL encapsulate a signed data content type.

   TimeStampToken ::= ContentInfo
     -- contentType is id-signedData ([CMS])
     -- content is SignedData ([CMS])

   The fields of type EncapsulatedContentInfo of the SignedData
   construct have the following meanings:

   eContentType is an object identifier that uniquely specifies the
   content type.  For a time-stamp token it is defined as:

   id-ct-TSTInfo  OBJECT IDENTIFIER ::= { iso(1) member-body(2)
   us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4}

   eContent is the content itself, carried as an octet string.
   The eContent SHALL be the DER-encoded value of TSTInfo.

   TSTInfo ::= SEQUENCE  {
   version                      INTEGER  { v1(1) },
   policy                       TSAPolicyId,
   messageImprint               MessageImprint,
     -- MUST have the same value as the similar field in
     -- TimeStampReq
   serialNumber                 INTEGER,
    -- Time-Stamping users MUST be ready to accommodate integers
    -- up to 160 bits.
   genTime                      GeneralizedTime,
   accuracy                     Accuracy                 OPTIONAL,
   ordering                     BOOLEAN             DEFAULT FALSE,
   nonce                        INTEGER                  OPTIONAL,
     -- MUST be present if the similar field was present
     -- in TimeStampReq.  In that case it MUST have the same value.
   tsa                          [0] GeneralName          OPTIONAL,
   extensions                   [1] IMPLICIT Extensions   OPTIONAL  }

So, where is the signing certificate stored? is it an extension? or is it part of the ContentType identifier?

Question 4:

If I did specify the -cert parameter, how can I extract a file token_stripped.tk from token.tk, so that token_stripped.tk is the same as if I would have created the request without the -cert argument?

Question 5:

How can I extract the PKIStatus (as specified in the linked specification) from response.tsr (optimally without first converting it to human readable form)?


Solution

  • Answering my own questions:

    Question 1:

    Why does this only require the trust-anchor (=self-signed) certificate and not the whole chain down to the TSA certificate (or does -verify only work with tokens for which the certificate chain has been included in the token)?

    It actually does require it, but if the token already contains the entire trust chain embedded, then it's not needed. Otherwise it must be provided using the -untrusted argument

    Question 2:

    -cert
    The TSA is expected to include its signing certificate in the response.
    

    If I specify the -cert parameter in the first openssl call, then token.tk will be longer and also contain the certificate that was used to sign it. How can I extract that certificate from token.tk?

    The following call extracts the embedded certificates:

    penssl pkcs7 -inform DER -in tokenfile.tst -print_certs -outform PEM -out certificatechain.pem
    

    Question 3:

    I'm surprised that token.tk gets longer when I request the response to include the certificates (I would have assumed only response.tsr to get longer, not the token itself

    TstInfo actually remains the same length, but the timestamp token is not the TstInfo but the wrapping CMS ContentInfo, and the certificates are (conforming to specification) embedded as a signed attribute in that ContentInfo object.

    Question 4:

    If I did specify the -cert parameter, how can I extract a file token_stripped.tk from token.tk, so that token_stripped.tk is the same as if I would have created the request without the -cert argument?

    Since the certificates are embedded in a signed attribute and not an unsigned, it's not possible to generate a valid stripped token from one that contains the certificate chain.

    Question 5:

    How can I extract the PKIStatus (as specified in the linked specification) from response.tsr (optimally without first converting it to human readable form)?

    i didn't find a way other than parsing the human readable form using openssl cli