com.guardtime.asn1.TimeSignature.java Source code

Java tutorial

Introduction

Here is the source code for com.guardtime.asn1.TimeSignature.java

Source

/*
 * $Id: TimeSignature.java 268 2012-08-27 18:31:08Z ahto.truu $
 *
 *
 *
 * Copyright 2008-2011 GuardTime AS
 *
 * This file is part of the GuardTime client SDK.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.guardtime.asn1;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;

import com.guardtime.util.Util;

/**
 * GuardTime structure {@code TimeSignature}
 * ({@code contentInfo.content.signerInfo.signature}).
 *
 * <pre>
 * TimeSignature ::= SEQUENCE {
 *    location        OCTET STRING,
 *    history         OCTET STRING,
 *    publishedData   PublishedData,
 *    pkSignature     [0] IMPLICIT SignatureInfo OPTIONAL,
 *    pubReference    [1] IMPLICIT SET OF OCTET STRING OPTIONAL
 * }
 * </pre>
 *
 * @see PublishedData
 * @see SignatureInfo
 *
 * @since 0.4
 */
public final class TimeSignature extends Asn1Wrapper {
    private Asn1TimeSignature timeSignature;
    private byte[] location;
    private byte[] history;
    private PublishedData publishedData;
    private SignatureInfo pkSignature;
    private List pubReferences;

    /**
     * Parses a DER-encoded {@code TimeSignature} out from the given input stream.
     *
     * @param in
     *            the input stream to read data from.
     * @return the {@code TimeSignature} object.
     * @throws Asn1FormatException
     *             if the data read from {@code in} does not represent a valid
     *             {@code TimeSignature} object.
     * @throws IOException
     *             if {@code in} throws one.
     */
    public static TimeSignature getInstance(InputStream in) throws Asn1FormatException, IOException {
        if (in == null) {
            throw new IllegalArgumentException("invalid input stream: null");
        }

        try {
            ASN1Object obj = new ASN1InputStream(in).readObject();
            return new TimeSignature(obj);
        } catch (IOException e) {
            if (isAsnParserException(e)) {
                throw new Asn1FormatException("time signature has invalid format", e);
            } else {
                throw e;
            }
        } catch (IllegalArgumentException e) {
            if (isAsnParserException(e)) {
                throw new Asn1FormatException("time signature has invalid format", e);
            } else {
                throw e;
            }
        }
    }

    /**
     * Returns the DER representation of the {@code TimeSignature}.
     *
     * @return a DER byte array, or {@code null} on error.
     */
    public byte[] getDerEncoded() {
        try {
            return timeSignature.getEncoded(ASN1Encoding.DER);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Returns the location hash chain from the {@code TimeSignature} object.
     * <p>
     * This is the hash chain that connects the leaf corresponding to this
     * signature to the root of the global aggregation tree for the second when
     * the signature was registered in the GuardTime calendar by inserting the
     * root hash value of the aggregation tree as a leaf in the calendar tree.
     *
     * @return the contents of the {@code location} field of this
     *         {@code TimeSignature} object.
     */
    public byte[] getLocation() {
        return Util.copyOf(location);
    }

    /**
     * Returns the history hash chain from the {@code TimeSignature} object.
     * <p>
     * This is the hash chain that connects the leaf corresponding to the second
     * when the signature was registered in the GuardTime calendar to the root
     * of the calendar tree in the state the tree was at the moment
     * corresponding to the {@code publicationID} in the {@link PublishedData}.
     *
     * @return the contents of the {@code history} field of this
     *         {@code TimeSIgnature} object.
     */
    public byte[] getHistory() {
        return Util.copyOf(history);
    }

    /**
     * Returns the control publication data from the {@code TimeSignature}
     * object.
     * <p>
     * For an unextended signature, this data is not actually published. Such a
     * signature may be verified by either extending it (see {@link CertToken})
     * or by verifying the PKI signature temporarily protecting the
     * {@code PublishedData}.
     * <p>
     * For an extended signature, this represents the contents of the control
     * publication that can be used to provide tangible proof of integrity of
     * the timestamp.
     *
     * @return the contents of the {@code publishedData} field of this
     *         {@code TimeSignature} object.
     */
    public PublishedData getPublishedData() {
        return publishedData;
    }

    /**
     * Returns the temporary PKI signature protecting the {@code PublishedData}
     * until a control publication is available.
     * <p>
     * This is {@code null} for an extended signature.
     *
     * @return the PKI signature value, or {@code null}.
     */
    public SignatureInfo getPkSignature() {
        return pkSignature;
    }

    /**
     * Returns the publication references list from the {@code TimeSignature}
     * object.
     * <p>
     * This list contains bibliographic references to the print media where the
     * control publication represented by {@code PublishedData} was printed.
     * <p>
     * This list is read-only. Any attempts to modify it will result in an
     * {@code UnsupportedOperationException}.
     * <p>
     * This is {@code null} for an unextended signature.
     *
     * @return the contents of the {@code pubReferences} field of this
     *         {@code TimeSignature} object.
     */
    public List getPubReferences() {
        return ((pubReferences == null) ? null : Collections.unmodifiableList(pubReferences));
    }

    /**
     * Checks whether the signature is extended.
     * <p>
     * An extended signature is traceable to a control publication without any
     * extra information. An unextended signature needs additional information
     * from the online verification service.
     *
     * @see CertToken
     *
     * @return {@code true} if the timestamp is extended, {@code false}
     *         otherwise.
     */
    public boolean isExtended() {
        return (pkSignature == null);
    }

    /**
     * Class constructor.
     *
     * @param obj ASN.1 representation of time signature.
     *
     * @throws Asn1FormatException if provided ASN.1 object has invalid format.
     */
    TimeSignature(ASN1Encodable obj) throws Asn1FormatException {
        try {
            timeSignature = Asn1TimeSignature.getInstance(obj);

            // Check that location and history chains are present
            // (NullPointerException will be thrown otherwise)
            location = timeSignature.getLocation().getOctets();
            history = timeSignature.getHistory().getOctets();

            publishedData = new PublishedData(timeSignature.getPublishedData());

            Asn1SignatureInfo pkSig = timeSignature.getPkSignature();
            if (pkSig != null) {
                pkSignature = new SignatureInfo(pkSig);
            }

            ASN1Set pubRefs = timeSignature.getPubReferences();
            if (pubRefs != null) {
                pubReferences = new ArrayList();
                Enumeration e = pubRefs.getObjects();
                while (e.hasMoreElements()) {
                    Object nextElement = e.nextElement();
                    if (!(nextElement instanceof DERNull)) {
                        pubReferences.add(((ASN1OctetString) nextElement).getOctets());
                    }
                }
            }
        } catch (Asn1FormatException e) {
            throw e;
        } catch (Exception e) {
            throw new Asn1FormatException("time signature has invalid format", e);
        }
    }
}

/**
 * Internal implementation class for the ASN.1 representation of
 * {@code TimeSignature}.
 */
class Asn1TimeSignature extends ASN1Object {
    private ASN1OctetString location;
    private ASN1OctetString history;
    private Asn1PublishedData publishedData;
    private Asn1SignatureInfo pkSignature = null;
    private ASN1Set pubReferences = null;

    public static Asn1TimeSignature getInstance(Object obj) {
        if (obj == null || obj instanceof Asn1TimeSignature) {
            return (Asn1TimeSignature) obj;
        } else if (obj instanceof ASN1Sequence) {
            return new Asn1TimeSignature((ASN1Sequence) obj);
        }

        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
    }

    public Asn1TimeSignature(ASN1Sequence seq) {
        Enumeration en = seq.getObjects();

        // Required elements
        location = ASN1OctetString.getInstance(en.nextElement());
        history = ASN1OctetString.getInstance(en.nextElement());
        publishedData = Asn1PublishedData.getInstance(en.nextElement());

        // Optional elements
        while (en.hasMoreElements()) {
            ASN1TaggedObject obj = ASN1TaggedObject.getInstance(en.nextElement());
            int tag = obj.getTagNo();
            if (tag == 0 && pkSignature == null) {
                pkSignature = Asn1SignatureInfo.getInstance(obj, false);
            } else if (tag == 1 && pubReferences == null) {
                pubReferences = ASN1Set.getInstance(obj, false);
            } else {
                throw new IllegalArgumentException("invalid object in factory: " + obj);
            }
        }
    }

    public ASN1OctetString getHistory() {
        return history;
    }

    public ASN1OctetString getLocation() {
        return location;
    }

    public Asn1SignatureInfo getPkSignature() {
        return pkSignature;
    }

    public ASN1Set getPubReferences() {
        return pubReferences;
    }

    public Asn1PublishedData getPublishedData() {
        return publishedData;
    }

    public ASN1Primitive toASN1Primitive() {
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(location);
        v.add(history);
        v.add(publishedData);
        if (pkSignature != null) {
            v.add(new DERTaggedObject(false, 0, pkSignature));
        }
        if (pubReferences != null) {
            v.add(new DERTaggedObject(false, 1, pubReferences));
        }
        return new DERSequence(v);
    }
}