tech.ydb.shaded.bouncycastle.asn1.tsp.ArchiveTimeStamp Maven / Gradle / Ivy
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
 */
public class ArchiveTimeStamp
    extends ASN1Object
{
    private AlgorithmIdentifier digestAlgorithm;
    private Attributes attributes;
    private ASN1Sequence reducedHashTree;
    private 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 = 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.
     *
     * @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);
    }
}