Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

Combine Timestamp Reply and Content File into a TimeStampData

See more ASN.1 Examples

Demonstrates how to combine a timestamp reply (RFC 3161) with a data file (any type of file) to create a TimeStampData structure (RFC 5544).

Chilkat Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.Xml,
  Chilkat.Asn,
  Chilkat.BinData;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  bdTsr: TBinData;
  asnTsr: TAsn;
  xmlTsr: TXml;
  bdContent: TBinData;
  xml: TXml;
  xContext: TXml;
  tsd: TAsn;
  tsdBase64: string;

begin
  success := False;

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

  //  Also see this example:
  //  Send a TimeStamp Request to a TimeStamp Authority and get the Response

  //  Load a timestamp reply file
  bdTsr := TBinData.Create;
  success := bdTsr.LoadFile('qa_data/tsd/sample.tsr');
  if (success <> True) then
    begin
      WriteLn('Failed to load timestamp reply file.');
      Exit;
    end;

  //  Load the tsr into an ASN.1 object.
  asnTsr := TAsn.Create;
  success := asnTsr.LoadEncoded(bdTsr.GetEncoded('base64'),'base64');
  if (success <> True) then
    begin
      WriteLn(asnTsr.LastErrorText);
      Exit;
    end;

  //  Get the timestamp reply as XML.
  xmlTsr := TXml.Create;
  xmlTsr.LoadXml(asnTsr.AsnToXml());

  //  The timestamp reply XML begins like this:
  //  We'll want to remove the 1st "sequence" subtree.

  //      <?xml version="1.0" encoding="utf-8"?>
  //      <sequence>
  //          <sequence>       <---- Remove this sub-tree.
  //              <int>00</int>
  //              <sequence>
  //                  <utf8>Operation Okay</utf8>
  //              </sequence>
  //          </sequence>
  //          <sequence>   
  //              <oid>1.2.840.113549.1.7.2</oid>
  //              <contextSpecific tag="0" constructed="1">
  //              ...

  //  Remove the 1st sub-tree..
  xmlTsr.RemoveChildByIndex(0);

  //  In this example, the data file we're combining with the timestamp into a timestampData is a .p7m.
  //  However, it can be any type of file (text or binary), it doesn't matter..
  bdContent := TBinData.Create;
  success := bdContent.LoadFile('qa_data/tsd/sample.p7m');
  if (success <> True) then
    begin
      WriteLn('Failed to load content file.');
      Exit;
    end;

  //  Begin building the TimeStampData.  
  //  We'll build as XML and then convert to ASN.1
  xml := TXml.Create;
  xml.Tag := 'sequence';
  xml.UpdateChildContent('oid','1.2.840.113549.1.9.16.1.31');
  xml.UpdateAttrAt('contextSpecific',True,'tag','0');
  xml.UpdateAttrAt('contextSpecific',True,'constructed','1');
  xml.UpdateChildContent('contextSpecific|sequence|int','01');
  xml.UpdateChildContent('contextSpecific|sequence|octets',bdContent.GetEncoded('base64'));
  xml.UpdateAttrAt('contextSpecific|sequence|contextSpecific',True,'tag','0');
  xml.UpdateAttrAt('contextSpecific|sequence|contextSpecific',True,'constructed','1');

  xContext := xml.GetChildWithTag('contextSpecific|sequence|contextSpecific');
  xContext.AddChildTree(xmlTsr);
  xContext.Free;

  //  Convert the XML to ASN.1
  tsd := TAsn.Create;
  tsd.LoadAsnXml(xml.GetXml());

  //  Write the timestamped data to a file.
  success := tsd.WriteBinaryDer('qa_output/sample.tsd');

  //  Alternatively, get the tsd ASN.1 as base64..
  tsdBase64 := tsd.GetEncodedDer('base64_mime');
  WriteLn(tsdBase64);


  bdTsr.Free;
  asnTsr.Free;
  xmlTsr.Free;
  bdContent.Free;
  xml.Free;
  tsd.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.