com.guardtime.asn1.PublishedData.java Source code

Java tutorial

Introduction

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

Source

/*
 * $Id: PublishedData.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.math.BigInteger;
import java.util.Enumeration;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;

import com.guardtime.util.Base32;
import com.guardtime.util.Util;

/**
 * GuardTime structure {@code PublishedData}
 * ({@code contentInfo.content.signerInfo.signature.publishedData}).
 *
 * <pre>
 * PublishedData ::= SEQUENCE {
 *    publicationIdentifier   INTEGER,
 *    publicationImprint      DataImprint
 * }
 * DataImprint ::= OCTET STRING
 * </pre>
 */
public final class PublishedData extends Asn1Wrapper {
    private Asn1PublishedData publishedData;
    private BigInteger publicationId;
    private byte[] publicationImprint;

    /**
     * Parses a DER-encoded {@code PublishedData} out from the given input
     * stream.
     *
     * @param in
     *            the input stream to read data from.
     * @return the {@code PublishedData} object.
     * @throws Asn1FormatException
     *             if the data read from {@code in} does not represent a valid
     *             {@code PublishedData} object.
     * @throws IOException
     *             if {@code in} throws one.
     */
    public static PublishedData 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 PublishedData(obj);
        } catch (IOException e) {
            if (isAsnParserException(e)) {
                throw new Asn1FormatException("publiched data has invalid format", e);
            } else {
                throw e;
            }
        } catch (IllegalArgumentException e) {
            if (isAsnParserException(e)) {
                throw new Asn1FormatException("published data has invalid format", e);
            } else {
                throw e;
            }
        }
    }

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

    /**
     * Returns the data formatted for publishing in a printed newspaper.
     * <p>
     * The formatting is as follows:
     * <ul>
     * <li>the publication ID (a 64-bit Unix <code>time_t</code> value) is
     * listed from most to least significant byte;
     * <li>and the publication imprint (the hash value from the root of the
     * GuardTime calendar tree for the moment corresponding to the publication
     * ID) is appended;
     * <li>the CCITT CRC32 checksum over the preceding data is appended;
     * <li>the result is encoded in base-32;
     * <li>the result is grouped by inserting dashes after every 6 characters.
     * </ul>
     *
     * @return the formatted control publication.
     */
    public String getEncodedPublication() {
        byte[] idBytes = Util.toByteArray(getPublicationId().longValue());
        byte[] imprintBytes = getPublicationImprint();
        byte[] result = new byte[idBytes.length + imprintBytes.length];
        System.arraycopy(idBytes, 0, result, 0, idBytes.length);
        System.arraycopy(imprintBytes, 0, result, idBytes.length, imprintBytes.length);
        return Base32.encodeWithDashes(Util.addCrc32(result));
    }

    /**
     * Returns the publication ID, which is essentially a Unix
     * <code>time_t</code> value for the second when the publication imprint
     * was extracted from the GuardTime calendar tree.
     *
     * @return the publication ID.
     */
    public BigInteger getPublicationId() {
        return publicationId;
    }

    /**
     * Returns the publication imprint, which is a 1-byte hash algorithm ID
     * followed by the root hash value from the GuardTime calendar tree.
     *
     * @return the publication imprint.
     */
    public byte[] getPublicationImprint() {
        return Util.copyOf(publicationImprint);
    }

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

            // Check that publication ID and imprint are present
            // (NullPointerException will be thrown otherwise)
            publicationId = publishedData.getPublicationIdentifier().getValue();
            publicationImprint = publishedData.getPublicationImprint().getOctets();
        } catch (Exception e) {
            throw new Asn1FormatException("published data has invalid format", e);
        }
    }
}

/**
 * Internal implementation class for the ASN.1 representation of
 * {@code PublishedData}.
 */
class Asn1PublishedData extends ASN1Object {
    private ASN1Integer publicationIdentifier;
    private ASN1OctetString publicationImprint;

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

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

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

        // Required elements
        publicationIdentifier = ASN1Integer.getInstance(en.nextElement());
        publicationImprint = ASN1OctetString.getInstance(en.nextElement());

        // Extra elements (not allowed)
        if (en.hasMoreElements()) {
            throw new IllegalArgumentException("invalid object in factory: " + en.nextElement());
        }
    }

    public ASN1Integer getPublicationIdentifier() {
        return publicationIdentifier;
    }

    public ASN1OctetString getPublicationImprint() {
        return publicationImprint;
    }

    public ASN1Primitive toASN1Primitive() {
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(publicationIdentifier);
        v.add(publicationImprint);
        return new DERSequence(v);
    }
}