Sample code for 30+ languages & platforms
Dart Requires Chilkat v11.0.0+

Extract TSTInfo from RFC3161 Timestamp Reply

See more HTTP Examples

Sends an RFC 3161 timestamp request to a TSA (Timestamp Authority) server and converts the timestamp reply to XML, and then extracts the TSTInfo from the XML and converts it to XML.

Chilkat Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // Note: Requires Chilkat v9.5.0.75 or greater.

  // This requires the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // First sha-256 hash the data that is to be timestamped.
  // In this example, the data is the string "Hello World"

  final crypt = CkCrypt2();
  crypt.hashAlgorithm = 'sha256';
  crypt.encodingMode = 'base64';
  final base64Hash = crypt.hashFileENC('qa_data/hamlet.xml');

  final http = CkHttp();

  final requestToken = CkBinData();
  final optionalPolicyOid = '';
  final addNonce = false;
  final requestTsaCert = true;

  // Create a time-stamp request token
  try {
    http.createTimestampRequest('sha256', base64Hash, optionalPolicyOid, addNonce, requestTsaCert, requestToken);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // Send the time-stamp request token to the TSA.
  // This is the equivalent of the following CURL command:
  // curl -H "Content-Type: application/timestamp-query" --data-binary '@file.tsq' http://timestamp.digicert.com > file.tsr
  final tsaUrl = 'http://timestamp.digicert.com';
  final resp = CkHttpResponse();
  try {
    http.httpBd('POST', tsaUrl, requestToken, 'application/timestamp-query', resp);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // Get the timestamp reply from the HTTP response object.
  final timestampReply = CkBinData();
  resp.getBodyBd(timestampReply);

  // Convert the binary timestamp reply to XML
  final asn = CkAsn();
  try {
    asn.loadBd(timestampReply);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final xml = CkXml();
  xml.loadXml(asn.asnToXml());

  // Extract the TSTInfo from the XML.
  // The TSTInfo is this base64 encoded ASN.1 

  // 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  }

  final tstInfoBase64 = xml.getChildContent('sequence[1]|contextSpecific|sequence|sequence|contextSpecific|octets');

  final bdTstInfo = CkBinData();
  bdTstInfo.appendEncoded(tstInfoBase64, 'base64');

  final asnTstInfo = CkAsn();
  try {
    asnTstInfo.loadBd(bdTstInfo);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final xmlTstInfo = CkXml();
  xmlTstInfo.loadXml(asnTstInfo.asnToXml());
  print(xmlTstInfo.getXml());

  // Here's the TSTInfo XML:

  // <?xml version="1.0" encoding="utf-8"?>
  // <sequence>
  //     <int>01</int>
  //     <oid>2.16.840.1.114412.7.1</oid>
  //     <sequence>
  //         <sequence>
  //             <oid>2.16.840.1.101.3.4.2.1</oid>
  //             <null/>
  //         </sequence>
  //         <octets>4sRRyWOzC7EOic4fQ9+Op1pa10DbgoBGjBvkq09LZmE=</octets>
  //     </sequence>
  //     <int>00AD2C86E49872597B60F87D5C54BCFFAE</int>
  //     <universal tag="24" constructed="0">MjAyMzAzMTYxMTQ5NTJa</universal>
  // </sequence>

  //    The genTime (GeneralizedTime) is contained in the final "universal" XML element and is 
  //    in base64. It is the time at which the time-stamp token has been created by
  //    the TSA. After decoding from base64, it is:
  // 
  //    The syntax is: YYYYMMDDhhmmss[.s...]Z
  //    Example: 19990609001326.34352Z

  final sbGenTime = CkStringBuilder();
  sbGenTime.decodeAndAppend(xmlTstInfo.getChildContent('universal'), 'base64', 'utf-8');
  print(sbGenTime.getAsString());

  // Result:
  // 20230316115718Z
}