org.bouncycastle.asn1.tsp.ArchiveTimeStamp Maven / Gradle / Ivy
Show all versions of bcutil-jdk18on Show documentation
package org.bouncycastle.asn1.tsp;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
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
*/
public class ArchiveTimeStamp
extends ASN1Object
{
private final AlgorithmIdentifier digestAlgorithm;
private final Attributes attributes;
private final ASN1Sequence reducedHashTree;
private final ContentInfo timeStamp;
/**
* 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, null, reducedHashTree, timeStamp);
}
public ArchiveTimeStamp(
ContentInfo timeStamp)
{
this(null, null, null, timeStamp);
}
public ArchiveTimeStamp(
AlgorithmIdentifier digestAlgorithm,
Attributes attributes,
PartialHashtree[] reducedHashTree,
ContentInfo timeStamp)
{
this.digestAlgorithm = digestAlgorithm;
this.attributes = attributes;
if (reducedHashTree != null)
{
this.reducedHashTree = new DERSequence(reducedHashTree);
}
else
{
this.reducedHashTree = null;
}
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());
}
AlgorithmIdentifier digAlg = null;
Attributes attrs = null;
ASN1Sequence rHashTree = null;
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:
digAlg = AlgorithmIdentifier.getInstance(taggedObject, false);
break;
case 1:
attrs = Attributes.getInstance(taggedObject, false);
break;
case 2:
rHashTree = ASN1Sequence.getInstance(taggedObject, false);
break;
default:
throw new IllegalArgumentException("invalid tag no in constructor: "
+ taggedObject.getTagNo());
}
}
}
digestAlgorithm = digAlg;
attributes = attrs;
reducedHashTree = rHashTree;
timeStamp = ContentInfo.getInstance(sequence.getObjectAt(sequence.size() - 1));
}
public AlgorithmIdentifier getDigestAlgorithmIdentifier()
{
if (digestAlgorithm != null)
{
return digestAlgorithm;
}
else
{
return getTimeStampInfo().getMessageImprint().getHashAlgorithm();
}
}
public byte[] getTimeStampDigestValue()
{
return getTimeStampInfo().getMessageImprint().getHashedMessage();
}
private TSTInfo getTimeStampInfo()
{
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(
ASN1OctetString.getInstance(tsData.getEncapContentInfo().getContent()).getOctets());
return tstData;
}
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.
*
* @return the contents of the digestAlgorithm field, or null if not set.
*/
public AlgorithmIdentifier getDigestAlgorithm()
{
return digestAlgorithm;
}
/**
* Return the first node in the reduced hash tree which contains the leaf node.
*
* @return the node containing the data hashes, null if no reduced hash tree is present.
*/
public PartialHashtree getHashTreeLeaf()
{
if (reducedHashTree == null)
{
return null;
}
return PartialHashtree.getInstance(reducedHashTree.getObjectAt(0));
}
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(4);
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);
}
}