Class CAdESArchiveTimestampUtil

java.lang.Object
org.bouncycastle.cades.CAdESArchiveTimestampUtil

public final class CAdESArchiveTimestampUtil extends Object
Helpers for upgrading a CAdES B-LT signature to B-LTA by attaching an archive-time-stamp covering the entire SignedData.

The helper emits the ETSI TS 101 733 v1.7.4 "v2" form (id-aa-ets-archiveTimestampV2, OID 1.2.840.113549.1.9.16.2.48). The newer ETSI EN 319 122-1 "v3" form, which embeds an ats-hash-index-v3 signed attribute inside the TSA token, is not yet supported — v3 generation requires custom signed-attribute injection on the TSA token that is not yet exposed by the tsp module.

The v2 imprint is the digest, under the caller-supplied algorithm, of the canonical concatenation defined by ETSI TS 101 733 Annex A:

  1. the content octets of the encapsulated content (omitted if the signed-data is detached or has no eContent),
  2. each Certificate from the certificates field, in wire-encoding order, as its own DER encoding,
  3. each CertificateList from the crls field, in wire-encoding order, as its own DER encoding,
  4. for each SignerInfo (in wire-encoding order), its DER encoding with any archive-time-stamp attributes removed from the unsignedAttrs field.
Typical caller flow:
  1. computeArchiveTimestampImprint(CMSSignedData, AlgorithmIdentifier, DigestCalculatorProvider) returns the digest bytes.
  2. The caller obtains a TimeStampToken from a TSA over those bytes (transport is out of scope for BC).
  3. applyArchiveTimestamp(CMSSignedData, SignerId, TimeStampToken) returns a new CMSSignedData with the token attached as an id-aa-ets-archiveTimestampV2 unsigned attribute on the chosen signer.
  • Field Details

    • id_aa_ets_archiveTimestampV2

      public static final org.bouncycastle.asn1.ASN1ObjectIdentifier id_aa_ets_archiveTimestampV2
      ETSI TS 101 733 v1.7.4 id-aa-ets-archiveTimestampV2 OID.
  • Method Details

    • computeArchiveTimestampImprint

      public static byte[] computeArchiveTimestampImprint(CMSSignedData signed, org.bouncycastle.asn1.x509.AlgorithmIdentifier digestAlg, DigestCalculatorProvider digCalcProv) throws CAdESException, OperatorCreationException, IOException
      Digest the canonical archive-time-stamp v2 input for signed under digestAlg.
      Throws:
      CAdESException
      OperatorCreationException
      IOException
    • computeArchiveTimestampImprint

      public static byte[] computeArchiveTimestampImprint(CMSSignedDataParser parser, org.bouncycastle.asn1.x509.AlgorithmIdentifier digestAlg, DigestCalculatorProvider digCalcProv) throws CAdESException, CMSException, OperatorCreationException, IOException
      Streaming variant: digest the canonical archive-time-stamp v2 input directly from a CMSSignedDataParser without materialising the whole SignedData. The parser's signed content is fully drained during this call; cert/CRL/SignerInfo sections are then parsed in stream order. After this method returns the parser's content stream has been consumed and cannot be re-read from the same parser.

      The supplied parser must be positioned at the start of the SignedData (i.e. freshly constructed, with getSignedContent() not yet drained).

      Throws:
      CAdESException
      CMSException
      OperatorCreationException
      IOException
    • applyArchiveTimestamp

      public static CMSSignedData applyArchiveTimestamp(CMSSignedData signed, SignerId signerId, TimeStampToken token) throws CAdESException
      Attach an archive-time-stamp v2 to the signer matched by signerId. If the signer already has one or more archive-timestamp attributes the new token is appended into the existing attribute's value-set; archive-timestamps form an ordered chain so this preserves earlier timestamps.
      Throws:
      CAdESException
    • getArchiveTimestamps

      public static List<TimeStampToken> getArchiveTimestamps(SignerInformation signer) throws CAdESException
      Return the archive-time-stamp tokens carried by the signer, drawn from both the id-aa-ets-archiveTimestampV2 attribute and the legacy id-aa-ets-archiveTimestamp (RFC 5126 sec. 6.4.1) attribute, in attribute-value order (v2 first when both are present).

      The list reflects the v2 chain: each entry independently covers the canonical archive-time-stamp input (with all archive-time-stamps stripped), so a chain of N tokens gives N independent integrity witnesses over the same canonical bytes — chain renewability relies on the most-recent token's TSA cert still being fresh.

      Parameters:
      signer - the signer to inspect.
      Returns:
      an unmodifiable list of timestamp tokens, empty when neither archive-time-stamp attribute is present (signer has not been upgraded to B-LTA).
      Throws:
      CAdESException - if an attribute value cannot be parsed as a TimeStampToken.
    • validateArchiveTimestamps

      public static void validateArchiveTimestamps(CMSSignedData signed, SignerInformation signer, DigestCalculatorProvider digCalcProv) throws CAdESException, OperatorCreationException, IOException
      Self-consistency check on B-LTA material: for every archive-time-stamp attached to the signer, verify the token's MessageImprint equals computeArchiveTimestampImprint(CMSSignedData, AlgorithmIdentifier, DigestCalculatorProvider) run over the canonical-stripped signed structure under the token's own hash algorithm.

      The signed argument must be the CMSSignedData the tokens were attached to (after applyArchiveTimestamp); a different SignedData with the same signer will not produce matching canonical bytes.

      What this method does not do: validate the TSA's signature on each token, walk the TSA cert chain to a trust anchor, or check the archive-time-stamp dates against the signer cert's validity window. Those steps are the caller's responsibility, built on getArchiveTimestamps(SignerInformation) plus the tsp module's token validators.

      Parameters:
      signed - the SignedData carrying signer.
      signer - the signer to validate. Must carry at least one archive-time-stamp.
      digCalcProv - source of digest calculators.
      Throws:
      CAdESException - if no archive-time-stamp is present, a token cannot be parsed, or any token's imprint does not match the canonical input.
      OperatorCreationException
      IOException