package org.bouncycastle.asn1.tsp;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.Attributes;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.SignedData;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

Implementation of the Archive Timestamp type defined in RFC4998. {@see RFC 4998}

ASN.1 Archive Timestamp

ArchiveTimeStamp ::= SEQUENCE { digestAlgorithm [Ø] AlgorithmIdentifier OPTIONAL, attributes [1] Attributes OPTIONAL, reducedHashtree [2] SEQUENCE OF PartialHashtree OPTIONAL, timeStamp ContentInfo}

PartialHashtree ::= SEQUENCE OF OCTET STRING

Attributes ::= SET SIZE (1..MAX) OF Attribute

/** * Implementation of the Archive Timestamp type defined in RFC4998. * {@see <a href="https://tools.ietf.org/html/rfc4998">RFC 4998</a>} * <p> * ASN.1 Archive Timestamp * <p> * ArchiveTimeStamp ::= SEQUENCE { * digestAlgorithm [Ø] AlgorithmIdentifier OPTIONAL, * attributes [1] Attributes OPTIONAL, * reducedHashtree [2] SEQUENCE OF PartialHashtree OPTIONAL, * timeStamp ContentInfo} * <p> * PartialHashtree ::= SEQUENCE OF OCTET STRING * <p> * Attributes ::= SET SIZE (1..MAX) OF Attribute */
public class ArchiveTimeStamp extends ASN1Object { private AlgorithmIdentifier digestAlgorithm; private Attributes attributes; private ASN1Sequence reducedHashTree; private ContentInfo timeStamp;
Return an ArchiveTimestamp from the given object.
Params:
  • obj – the object we want converted.
Throws:
Returns:an ArchiveTimestamp instance, or null.
/** * Return an ArchiveTimestamp from the given object. * * @param obj the object we want converted. * @return an ArchiveTimestamp instance, or null. * @throws IllegalArgumentException if the object cannot be converted. */
public static ArchiveTimeStamp getInstance(final Object obj) { if (obj instanceof ArchiveTimeStamp) { return (ArchiveTimeStamp)obj; } else if (obj != null) { return new ArchiveTimeStamp(ASN1Sequence.getInstance(obj)); } return null; } public ArchiveTimeStamp( AlgorithmIdentifier digestAlgorithm, PartialHashtree[] reducedHashTree, ContentInfo timeStamp) { this.digestAlgorithm = digestAlgorithm; this.reducedHashTree = new DERSequence(reducedHashTree); this.timeStamp = timeStamp; } public ArchiveTimeStamp( AlgorithmIdentifier digestAlgorithm, Attributes attributes, PartialHashtree[] reducedHashTree, ContentInfo timeStamp) { this.digestAlgorithm = digestAlgorithm; this.attributes = attributes; this.reducedHashTree = new DERSequence(reducedHashTree); this.timeStamp = timeStamp; } public ArchiveTimeStamp( ContentInfo timeStamp) { this.timeStamp = timeStamp; } private ArchiveTimeStamp(final ASN1Sequence sequence) { if (sequence.size() < 1 || sequence.size() > 4) { throw new IllegalArgumentException("wrong sequence size in constructor: " + sequence.size()); } for (int i = 0; i < sequence.size() - 1; i++) { Object obj = sequence.getObjectAt(i); if (obj instanceof ASN1TaggedObject) { ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(obj); switch (taggedObject.getTagNo()) { case 0: digestAlgorithm = AlgorithmIdentifier.getInstance(taggedObject, false); break; case 1: attributes = Attributes.getInstance(taggedObject, false); break; case 2: reducedHashTree = ASN1Sequence.getInstance(taggedObject, false); break; default: throw new IllegalArgumentException("invalid tag no in constructor: " + taggedObject.getTagNo()); } } } timeStamp = ContentInfo.getInstance(sequence.getObjectAt(sequence.size() - 1)); } public AlgorithmIdentifier getDigestAlgorithmIdentifier() { if (digestAlgorithm != null) { return digestAlgorithm; } else { if (timeStamp.getContentType().equals(CMSObjectIdentifiers.signedData)) { SignedData tsData = SignedData.getInstance(timeStamp.getContent()); if (tsData.getEncapContentInfo().getContentType().equals(PKCSObjectIdentifiers.id_ct_TSTInfo)) { TSTInfo tstData = TSTInfo.getInstance(tsData.getEncapContentInfo()); return tstData.getMessageImprint().getHashAlgorithm(); } else { throw new IllegalStateException("cannot parse time stamp"); } } else { throw new IllegalStateException("cannot identify algorithm identifier for digest"); } } }
Return the contents of the digestAlgorithm field - null if not set.
Returns:the contents of the digestAlgorithm field, or null if not set.
/** * Return the contents of the digestAlgorithm field - null if not set. * * @return the contents of the digestAlgorithm field, or null if not set. */
public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public PartialHashtree[] getReducedHashTree() { if (reducedHashTree == null) { return null; } PartialHashtree[] rv = new PartialHashtree[reducedHashTree.size()]; for (int i = 0; i != rv.length; i++) { rv[i] = PartialHashtree.getInstance(reducedHashTree.getObjectAt(i)); } return rv; } public ContentInfo getTimeStamp() { return timeStamp; } public ASN1Primitive toASN1Primitive() { ASN1EncodableVector v = new ASN1EncodableVector(); if (digestAlgorithm != null) { v.add(new DERTaggedObject(false, 0, digestAlgorithm)); } if (attributes != null) { v.add(new DERTaggedObject(false, 1, attributes)); } if (reducedHashTree != null) { v.add(new DERTaggedObject(false, 2, reducedHashTree)); } v.add(timeStamp); return new DERSequence(v); } }