All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gc.iotools.fmt.decoders.TimeStampedDataParser Maven / Gradle / Ivy

The newest version!
package com.gc.iotools.fmt.decoders;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.ASN1StreamParser;
import org.bouncycastle.asn1.BEROctetStringParser;
import org.bouncycastle.asn1.BERSequenceParser;
import org.bouncycastle.asn1.BERTaggedObjectParser;
import org.bouncycastle.asn1.BERTags;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DEROctetStringParser;
import org.bouncycastle.asn1.DERSequenceParser;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.ContentInfoParser;
import org.bouncycastle.asn1.cms.Evidence;
import org.bouncycastle.asn1.cms.MetaData;
import org.bouncycastle.asn1.cms.TimeStampAndCRL;
import org.bouncycastle.asn1.cms.TimeStampTokenEvidence;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TimeStampToken;

/**
 * Stream processing of a {@link org.bouncycastle.asn1.cms.TimeStampedData} object.
 * 
 * @author Giacomo Boccardo ([email protected])
 *
 * See RFC 5544.
 * 
 * 
 * ContentInfo ::= SEQUENCE {
 * 		contentType ContentType,
 * 		content [0] EXPLICIT ANY DEFINED BY contentType
 * }
 * 
 * ContentType ::= OBJECT IDENTIFIER
 * 
 * id-ct-timestampedData OBJECT IDENTIFIER ::= {
 *                iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
 *                pkcs9(9) id-smime(16) id-ct(1) 31 }
 * 
 * TimeStampedData ::= SEQUENCE {
 *  	version              INTEGER { v1(1) },
 *  	dataUri              IA5String OPTIONAL,
 *  	metaData             MetaData OPTIONAL,
 *  	content              OCTET STRING OPTIONAL,
 *  	temporalEvidence     Evidence
 * }
 * 
 * MetaData ::= SEQUENCE {
 *  	hashProtected        BOOLEAN,
 *  	fileName             UTF8String OPTIONAL,
 *  	mediaType            IA5String OPTIONAL,
 *  	otherMetaData        Attributes OPTIONAL
 * }
 * 
 * Attributes ::=
 *  	SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
 * 
 * Evidence ::= CHOICE {
 *  	tstEvidence    [0] TimeStampTokenEvidence,   -- see RFC 3161
 *  	ersEvidence    [1] EvidenceRecord,           -- see RFC 4998
 *  	otherEvidence  [2] OtherEvidence
 * }
 * 
 * TimeStampTokenEvidence ::=
 *  	SEQUENCE SIZE(1..MAX) OF TimeStampAndCRL
 * 
 * TimeStampAndCRL ::= SEQUENCE {
 *  	timeStamp   TimeStampToken,          -- according to RFC 3161
 *  	crl         CertificateList OPTIONAL -- according to RFC 5280
 * }
 * 
* */ public final class TimeStampedDataParser { private ASN1SequenceParser tsdSeq; private ASN1ObjectIdentifier contentType; private ASN1Integer version; private DERIA5String dataUri; private MetaData metaData; private InputStream contentAsIS; private boolean contentISRead = false; /** * Instantiate a {@link TimeStampedDataParser} in order to stream process a TSD timestamp. * *

* Note: since it's a stream processing, the order in which the methods of this class are called is essential.
* In detail, you should follow these steps:
*

    *
  • instantiate a {@link TimeStampedDataParser} object passing the {@link InputStream} of the TSD;
  • *
  • get the {@link InputStream} of the content using the method {@link #getContentAsIS()} and consume it * completely (or you'll lose it after the following step);
  • *
  • get the array of the timestamps as {@link TimeStampToken} objects using the method * {@link #getTimeStampTokens()}.
  • *
*

* * @param tsdIS * The {@link InputStream} of a {@link org.bouncycastle.asn1.cms.TimeStampedData} object. * @throws IOException * @throws TSPException */ public TimeStampedDataParser(final InputStream tsdIS) throws IOException { final ASN1StreamParser asn1SP = new ASN1StreamParser(tsdIS); try { // ContentInfo final ASN1SequenceParser contentInfoSeq = (ASN1SequenceParser) asn1SP.readObject(); final ContentInfoParser contentInfoParser = new ContentInfoParser(contentInfoSeq); // ContentType contentType = contentInfoParser.getContentType(); // Content (SEQUENCE) = TimeStampedData final ASN1SequenceParser tsDataSeq = (ASN1SequenceParser) contentInfoParser.getContent(BERTags.SEQUENCE); // TimeStampedData#version version = (ASN1Integer) tsDataSeq.readObject(); // TimeStampedData#{dataUri, metaData, content} ASN1Encodable o; while ((o = tsDataSeq.readObject()) != null) { if (o instanceof DERIA5String) { dataUri = (DERIA5String) o; } else if (o instanceof BERSequenceParser) { metaData = MetaData.getInstance(((BERSequenceParser) o).toASN1Primitive()); } else if (o instanceof DERSequenceParser) { metaData = MetaData.getInstance(((DERSequenceParser) o).toASN1Primitive()); } else if (o instanceof BEROctetStringParser) { final InputStream contentIS = ((BEROctetStringParser) o).getOctetStream(); contentAsIS = contentIS; // The Evidence field can't be read until the InputStream of // the content is completely consumed. break; } else if (o instanceof DEROctetStringParser) { final InputStream contentIS = ((DEROctetStringParser) o).getOctetStream(); contentAsIS = contentIS; // The Evidence field can't be read until the InputStream of // the content is completely consumed. break; } else if (o instanceof BERTaggedObjectParser) { // TODO // If we are here, there's no content and we are reading the // Evidence field. // The content could be retrieved using the URI in the field // dataUri, if present. throw new UnsupportedOperationException("Content field not present, retrieve it using the dataUri"); } else { throw new IOException("The TimeStampedData object is malformed: [" + o + "]"); } } tsdSeq = tsDataSeq; } catch (final IOException e) { tsdSeq = null; throw new IOException("The TSD can't be recognized", e); } } public InputStream getContentAsIS() { if (hasContentBeenRead()) { throw new IllegalStateException("The stream processing doesn't allow to read the " + " content after the TimeStampToken(s) " + "(Evidence(s)) have been read"); } return contentAsIS; } public ASN1ObjectIdentifier getContentType() { return contentType; } public DERIA5String getDataUri() { return dataUri; } public MetaData getMetaData() { return metaData; } /** * Retrieves the {@link TimeStampToken}s from the {@link TimeStampTokenEvidence}. * * Note: the stream processing requires to read the content field of the TSD before the {@link Evidence} field. * * * @return the {@link TimeStampToken[]} contained in the {@link Evidence} field. * @throws IOException * @throws TSPException */ public TimeStampToken[] getTimeStampTokens() throws IOException, TSPException { // Note: before reading the Evidence field the InputStream of the // content must be completely consumed. IOUtils.copy(contentAsIS, new NullOutputStream()); contentISRead = true; // TimeStampedData#temporalEvidence final ASN1Encodable o = tsdSeq.readObject(); final ASN1Encodable temporalEvidenceDER = ((BERTaggedObjectParser) o).toASN1Primitive(); if (temporalEvidenceDER == null) { throw new TSPException("The Evidence field must me present."); } final Evidence temporalEvidence = Evidence.getInstance(temporalEvidenceDER); if (temporalEvidence == null) { throw new IOException("The Evidence field is malformed."); } // TimeStampTokenEvidence final TimeStampTokenEvidence tstEvidence = temporalEvidence.getTstEvidence(); if (tstEvidence == null) { throw new TSPException("The Evidence field must contain a " + "TimeStampTokenEvidence."); } // TimeStampTokenEvidence#TimeStampAndCRL[] final TimeStampAndCRL[] timeStampAndCRLArray = tstEvidence.toTimeStampAndCRLArray(); if (timeStampAndCRLArray.length == 0) { throw new IOException("The TimeStampTokenEvidence must contain " + " at least a TimeStampAndCRL object."); } final ArrayList tstArr = new ArrayList(); for (final TimeStampAndCRL tsAndCRL : timeStampAndCRLArray) { // TimeStampAndCRL#TimeStampToken final ContentInfo timeStamp = tsAndCRL.getTimeStampToken(); if (timeStamp == null) { throw new IOException("The TimeStampAndCRL must contain a" + " ContentInfo object."); } TimeStampToken timeStampToken = null; try { timeStampToken = new TimeStampToken(timeStamp); } catch (final Exception e) { throw new IOException("The TimeStampToken object is malformed: " + e, e); } tstArr.add(timeStampToken); } return tstArr.toArray(new TimeStampToken[tstArr.size()]); } public ASN1Integer getVersion() { return version; } public boolean hasContentBeenRead() { return contentISRead; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy