com.opentrust.spi.pdf.PDFEnvelopedSignature.java Source code

Java tutorial

Introduction

Here is the source code for com.opentrust.spi.pdf.PDFEnvelopedSignature.java

Source

/*
 * Copyright 2004 by Paulo Soares.
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the License.
 *
 * The Original Code is 'iText, a free JAVA-PDF library'.
 *
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
 * All Rights Reserved.
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
 *
 * Contributor(s): all the names of the contributors are added in the source code
 * where applicable.
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
 * provisions of LGPL are applicable instead of those above.  If you wish to
 * allow use of your version of this file only under the terms of the LGPL
 * License and not to allow others to use your version of this file under
 * the MPL, indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by the LGPL.
 * If you do not delete the provisions above, a recipient may use your version
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the MPL as stated above or under the terms of the GNU
 * Library General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
 * details.
 *
 * If you didn't download this code from the following link, you should check if
 * you aren't using an obsolete version:
 * http://www.lowagie.com/iText/
 */
package com.opentrust.spi.pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import javax.crypto.Cipher;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OutputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DEREncodable;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERString;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.esf.CommitmentTypeIndication;
import org.bouncycastle.asn1.esf.SignaturePolicyIdentifier;
import org.bouncycastle.asn1.esf.SignerAttribute;
import org.bouncycastle.asn1.esf.SignerLocation;
import org.bouncycastle.asn1.ess.ContentHints;
import org.bouncycastle.asn1.ess.ContentIdentifier;
import org.bouncycastle.asn1.ess.ESSCertID;
import org.bouncycastle.asn1.ess.ESSCertIDv2;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedDataStreamGenerator;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.X509CertParser;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TimeStampResponse;
import org.bouncycastle.tsp.TimeStampToken;

import com.keynectis.sequoia.security.clients.interfaces.ITspClient;
import com.opentrust.spi.cms.CMSForPAdESBasicGenerator;
import com.opentrust.spi.cms.CMSSignedDataWrapper;
import com.opentrust.spi.cms.CMSVerifier;
import com.opentrust.spi.cms.ExceptionHandlerTyped;
import com.opentrust.spi.cms.helpers.ContentSignerWithProvidedSignatureValue;
import com.opentrust.spi.cms.helpers.OCSPResponse;
import com.opentrust.spi.cms.helpers.SignatureHelper;
import com.opentrust.spi.crypto.CryptoConstants;
import com.opentrust.spi.crypto.DigestHelper;
import com.opentrust.spi.crypto.CryptoConstants.AlgorithmID;
import com.opentrust.spi.crypto.CryptoConstants.AlgorithmType;
import com.opentrust.spi.crypto.ExceptionHandler;
import com.opentrust.spi.logger.Channel;
import com.opentrust.spi.logger.SPILogger;
//import com.opentrust.spi.ocsp.OCSPResponse;
import com.opentrust.spi.tsp.TimeStampProcessor;
import com.opentrust.spi.tsp.TimeStampProcessorFactory;
import com.opentrust.spi.tsp.TimestampToken;
import com.opentrust.spi.tsp.impl.BCTimeStampToken;
import com.spilowagie.text.ExceptionConverter;
import com.spilowagie.text.pdf.AcroFields;
import com.spilowagie.text.pdf.PdfName;

/**
 * This class does all the processing related to signing and verifying a PKCS#7 or PKCS#1 PDF-embedded
 * signature.
 * <p>
 * It's based in code found at org.bouncycastle.
 */
public class PDFEnvelopedSignature {
    private static SPILogger log = SPILogger.getLogger("PDFSIGN");

    private Collection<OCSPResponse> ocspResponses;

    private String timeStampDigestAlgo;

    private String timeStampPolicyId;

    private boolean timeStampUseNonce;

    private int version, signerversion;
    private ASN1ObjectIdentifier cmsContentType;

    private Collection certs, crls;

    private X509Certificate signCert;

    private byte[] pkcs1SigValue;

    private String dataDigestAlgorithm, keyAndParameterAlgorithm;

    private Signature sig;

    private byte adbePkcs7Sha1Data[];

    private TimestampToken timestampToken;

    private static final String ID_RSA = AlgorithmID.KEY_RSA.getOID();
    private static final String ID_DSA = "1.2.840.10040.4.1";

    private static final int GRANTED = 0;

    /**
     * properties from PDF signature dictionary (M, Location, Reason, ContactInfo)
     */
    private String reason;
    private String location;
    private String contactInfo;
    private byte[] dictionaryCert;
    private int[] byteRange;
    private byte[] contentsKey; // the original <CONTENTS> content

    // Used to retrieve info for signature (revision, coversWholeDocument, fieldPositions...)
    private AcroFields acroFields;
    private String signatureFieldName;

    private Calendar dicoSignDate;

    private Calendar cmsSignDate;

    /**
     * Holds value of property signName.
     */
    private String signName;

    private CMSSignedDataWrapper cmsSignature;
    private MessageDigest verifyDigest;
    private MessageDigest contentTimestampVerifyDigest;
    private OutputStream sigOut;
    private ByteArrayOutputStream bOut;
    private CMSSignedDataStreamGenerator cmsGenerator;

    TimestampToken docTimestampTStoken;//For "Document TimeStamp" signatures (PAdES LTV)

    ITspClient tspClient;

    public ITspClient getTspClient() {
        return tspClient;
    }

    public void setTspClient(ITspClient tspClient) {
        this.tspClient = tspClient;
    }

    private String subFilter;
    public static String SF_ADBE_X509_RSA_SHA1 = "adbe.x509.rsa_sha1";
    public static String SF_ADBE_PKCS7_DETACHED = "adbe.pkcs7.detached";
    public static String SF_ADBE_PKCS7_SHA1 = "adbe.pkcs7.sha1";
    public static String SF_ETSI_CADES_DETACHED = "ETSI.CAdES.detached";
    public static String SF_ETSI_RFC3161 = "ETSI.RFC3161";

    // PKCS#1 signature verification
    /**
     * Verifies a signature using the sub-filter adbe.x509.rsa_sha1.
     * @param contentsKey the /Contents key
     * @param certsKey the /Cert key
     * @param provider the provider or <code>null</code> for the default provider
     */
    public PDFEnvelopedSignature(byte[] contentsKey, byte[] certsKey, String provider, AcroFields acroFields,
            String signatureFieldName) {
        try {
            log.debug(Channel.TECH, "Verifying a adbe.x509.rsa_sha1 signature");
            this.acroFields = acroFields;
            this.signatureFieldName = signatureFieldName;
            this.subFilter = SF_ADBE_X509_RSA_SHA1;
            this.dictionaryCert = certsKey;
            X509CertParser cr = new X509CertParser();
            cr.engineInit(new ByteArrayInputStream(certsKey));
            certs = cr.engineReadAll();
            signCert = (X509Certificate) certs.iterator().next();
            crls = new ArrayList();
            ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey));
            pkcs1SigValue = ((DEROctetString) in.readObject()).getOctets();

            Cipher c = Cipher.getInstance("RSA/NONE/PKCS1Padding", BouncyCastleProvider.PROVIDER_NAME);
            c.init(Cipher.DECRYPT_MODE, signCert);
            byte[] raw = c.doFinal(pkcs1SigValue);
            ASN1Sequence in3 = (ASN1Sequence) ASN1Object.fromByteArray(raw);
            DigestInfo di = DigestInfo.getInstance(in3);
            dataDigestAlgorithm = di.getAlgorithmId().getAlgorithm().getId();
            keyAndParameterAlgorithm = ID_RSA;

            if (provider == null)
                sig = Signature.getInstance(getSignatureAlgorithm());
            else
                sig = Signature.getInstance(getSignatureAlgorithm(), provider);
            sig.initVerify(signCert.getPublicKey());
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
      * Verifies a signature using the sub-filter adbe.pkcs7.detached or
      * adbe.pkcs7.sha1 or ETSI.CAdES.detached or ETSI.RFC3161
      * @param contentsKey the /Contents key
      * @param provider the provider or <code>null</code> for the default provider
     * @param acroFields 
      */
    protected PDFEnvelopedSignature(byte[] contentsKey, String provider, PdfName subFilter, AcroFields acroFields,
            String signatureFieldName) {
        try {
            log.debug(Channel.TECH,
                    "Verifying an adbe.pkcs7.detached, adbe.pkcs7.sha1 or ETSI.CAdES.detached signature");
            this.acroFields = acroFields;
            this.signatureFieldName = signatureFieldName;
            this.contentsKey = contentsKey;
            if (subFilter == PdfName.ADBE_PKCS7_DETACHED)
                this.subFilter = SF_ADBE_PKCS7_DETACHED;
            else if (subFilter == PdfName.ADBE_PKCS7_SHA1)
                this.subFilter = SF_ADBE_PKCS7_SHA1;
            else if (subFilter == PdfName.ETSI_CADES_DETACHED)
                this.subFilter = SF_ETSI_CADES_DETACHED;
            else if (subFilter == PdfName.ETSI_RFC3161)
                this.subFilter = SF_ETSI_RFC3161;
            else
                throw new IllegalArgumentException("Unknown subFilter found in signature dictionary : "
                        + (subFilter == null ? null : new String(subFilter.getBytes())));

            log.debug(Channel.TECH, "Signature subFilter is %1$s", this.subFilter);

            if (this.subFilter == SF_ETSI_RFC3161) {
                // Then contentsKey contains a TimeStamptoken
                //docTimestampTStoken = TimestampTokenManagerFactory.getInstance().getTimeStampToken(contentsKey);
                docTimestampTStoken = new BCTimeStampToken(contentsKey);
                dataDigestAlgorithm = docTimestampTStoken.getMessageImprintAlgName();
                verifyDigest = MessageDigest.getInstance(dataDigestAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
            } else {
                cmsSignature = new CMSSignedDataWrapper(contentsKey); // uses provider BC, not provider given as parameter. TODO ?
                // the version
                version = cmsSignature.getVersion();
                log.debug(Channel.TECH, "Parsing CMS Data, version=%1$s", version);

                cmsContentType = cmsSignature.getContentType();
                log.debug(Channel.TECH, "Parsing CMS Data, cmsContentType=%1$s", cmsContentType);

                if (cmsSignature.hasMultipleSignerInfos())
                    throw new IllegalArgumentException(
                            "This PKCS#7 object has multiple SignerInfos - only one is supported at this time"); // and even forbidden for PAdES ?

                // the digestAlgorithms property is not fetched. We have no use for it, it is used internally by CMSSignature 

                certs = cmsSignature.getSignatureCertificateInfo();
                crls = cmsSignature.getCRLs();
                ocspResponses = cmsSignature.getOCSPResponses();
                log.debug(Channel.TECH, "Parsing CMS Data, certs=%1$s", certs);
                log.debug(Channel.TECH, "Parsing CMS Data, crls=%1$s", crls);
                log.debug(Channel.TECH, "Parsing CMS Data, ocspResponses=%1$s", ocspResponses);

                signerversion = cmsSignature.getSignerVersion();
                log.debug(Channel.TECH, "Parsing CMS Data, signerversion=%1$s", signerversion);

                signCert = (X509Certificate) cmsSignature.getSignerCertificate();
                if (signCert == null) {
                    throw new IllegalArgumentException("Can't find signing certificate");
                }
                log.debug(Channel.TECH, "Parsing CMS Data, signCert=%1$s", signCert);

                dataDigestAlgorithm = cmsSignature.getDataDigestAlgorithm();
                log.debug(Channel.TECH, "Parsing CMS Data, dataDigestAlgorithm=%1$s", dataDigestAlgorithm);
                keyAndParameterAlgorithm = cmsSignature.getEncryptionAlgorithm();
                log.debug(Channel.TECH, "Parsing CMS Data, keyAndParameterAlgorithm=%1$s",
                        keyAndParameterAlgorithm);

                List<TimestampToken> timestps = cmsSignature.getSignatureTimestamps();
                if (!timestps.isEmpty()) {
                    timestampToken = timestps.get(0);
                    log.debug(Channel.TECH, "Parsing CMS Data, found timestamp token with date %1$s",
                            timestampToken.getDateTime());
                } else
                    log.debug(Channel.TECH, "Parsing CMS Data, no timestamp token found");

                // sigAttr and digestAttr properties are not fetched. We have no use for them, they are used internally by CMSSignature

                if (cmsSignature.getSigningTime() != null) {
                    cmsSignDate = Calendar.getInstance();
                    cmsSignDate.setTime(cmsSignature.getSigningTime());
                }
                log.debug(Channel.TECH, "Parsing CMS Data, cmsSignDate=%1$s", cmsSignDate);

                adbePkcs7Sha1Data = cmsSignature.getEncodedEncapsulatedData();
                if (adbePkcs7Sha1Data != null) {
                    if (this.subFilter != SF_ADBE_PKCS7_SHA1)
                        throw new Exception(
                                "Invalid CMS : cannot have encapsulated data for " + this.subFilter + " subfilter");
                    verifyDigest = MessageDigest.getInstance("SHA1", BouncyCastleProvider.PROVIDER_NAME);
                } else {
                    if (this.subFilter == SF_ADBE_PKCS7_SHA1)
                        throw new Exception("Invalid CMS : must have encapsulated data for " + SF_ADBE_PKCS7_SHA1
                                + " subfilter");
                    verifyDigest = MessageDigest.getInstance(dataDigestAlgorithm,
                            BouncyCastleProvider.PROVIDER_NAME);
                    try {
                        if (cmsSignature.getContentTimestamp() != null
                                && cmsSignature.getContentTimestamp().getMessageImprintAlgName() != null)
                            contentTimestampVerifyDigest = MessageDigest.getInstance(
                                    cmsSignature.getContentTimestamp().getMessageImprintAlgName(),
                                    BouncyCastleProvider.PROVIDER_NAME);
                        //TODO : fo not compute digest for ContentTS when digestAlgo is the same as dataDigestAlgorithm
                    } catch (Exception e) {
                        log.error(Channel.TECH, "Error while parsing content timestamp : %1$s", e);
                    }
                }
            }
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
      * Used to build a PKCS7 object given all its properties (digest, certs, crls, raw signature, adbePkcs7Sha1...).
      **/

    //FIXME : move to other class !!!
    public PDFEnvelopedSignature(byte[] digest, Certificate[] certChain, CRL[] crlList,
            OCSPResponse[] ocspResponseEncoded, String dataHashAlgorithm, String provider, byte signature[],
            byte adbePkcs7Sha1Data[], String digestEncryptionAlgorithm, Date signingTime) {
        try {
            log.debug(Channel.TECH, "Building PDFEnvelopedSignature object");
            Hashtable<DERObjectIdentifier, Attribute> signedAttributesHashtable = new Hashtable<DERObjectIdentifier, Attribute>();

            List<OCSPResponse> ocspResponses = ocspResponseEncoded == null ? null
                    : Arrays.asList(ocspResponseEncoded);
            List<CRL> crls = null;
            if (crlList != null) {
                crls = Arrays.asList(crlList);
            }

            AlgorithmID algorithmID = CryptoConstants.AlgorithmID.valueOfTag(dataHashAlgorithm);
            if (algorithmID == null || algorithmID.getType() != AlgorithmType.DIGEST)
                throw new NoSuchAlgorithmException("Unknown Hash Algorithm " + dataHashAlgorithm);

            Attribute messageDigestAttribute = new Attribute(CMSAttributes.messageDigest,
                    new DERSet(new DEROctetString(digest)));

            signedAttributesHashtable.put(CMSAttributes.messageDigest, messageDigestAttribute);
            this.signCert = (X509Certificate) certChain[0];
            dataDigestAlgorithm = algorithmID.getOID();
            this.crls = crls;
            this.certs = Arrays.asList(certChain);
            this.ocspResponses = ocspResponses;
            keyAndParameterAlgorithm = digestEncryptionAlgorithm;
            this.adbePkcs7Sha1Data = adbePkcs7Sha1Data;
            cmsGenerator = (CMSSignedDataStreamGenerator) CMSForPAdESBasicGenerator.buildCMSSignedGenerator(
                    new ContentSignerWithProvidedSignatureValue(signature,
                            AlgorithmID.valueOfTag(getSignatureAlgorithm()).getOID()),
                    true, BouncyCastleProvider.PROVIDER_NAME, signedAttributesHashtable, signCert, certs,
                    signingTime, dataDigestAlgorithm, crls, ocspResponses);
            bOut = new ByteArrayOutputStream();
            sigOut = cmsGenerator.open(bOut, adbePkcs7Sha1Data != null);
            if (adbePkcs7Sha1Data != null)
                sigOut.write(adbePkcs7Sha1Data);
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * Update the digest with the specified bytes. This method is used both for signing and verifying
     * @param buf the data buffer
     * @param off the offset in the data buffer
     * @param len the data length
     * @throws SignatureException on error
     */
    public void update(byte[] buf, int off, int len) throws SignatureException {
        if (sigOut != null) // adbe.pkcs7.detached or adbe.pkcs7.sha1 (PKCS#7) generation
            try {
                if (adbePkcs7Sha1Data != null) //adbe.pkcs7.sha1
                    verifyDigest.update(buf, off, len); // verifyDigest is used to compute sha1 digest on document
                else // adbe.pkcs7.detached
                    sigOut.write(buf, off, len);
            } catch (IOException e) {
                throw new ExceptionConverter(e);
            }
        else if (verifyDigest != null) { // adbe.pkcs7.detached or adbe.pkcs7.sha1 (PKCS#7) verification
            verifyDigest.update(buf, off, len);
            if (contentTimestampVerifyDigest != null)
                contentTimestampVerifyDigest.update(buf, off, len); //Also compute digest for contentTimestamp
        } else if (sig != null) //adbe.x509.rsa_sha1 (PKCS#1) verification
            sig.update(buf, off, len);
    }

    private boolean verified = false;
    private boolean verificationResult = false;

    /**
     * Verify the signature and digest(s) conformity
     * @throws SignatureException on error
     * @return <CODE>true</CODE> if the signature checks out, <CODE>false</CODE> otherwise
     */
    public boolean verify() {
        if (!verified) {
            try {
                verificationResult = true;
                if (verifyDigest != null) {
                    if (adbePkcs7Sha1Data != null) {
                        // PKCS7 verification (with encapsulated data)
                        verificationResult = CMSVerifier.verify(cmsSignature)
                                && Arrays.equals(verifyDigest.digest(), cmsSignature.getEncodedEncapsulatedData());
                    } else if (docTimestampTStoken != null) {
                        verificationResult = docTimestampTStoken.verifySignature()
                                && docTimestampTStoken.verifyImprint(verifyDigest.digest());
                    } else {
                        verificationResult = CMSVerifier.verifyReference(verifyDigest.digest(), cmsSignature); // PKCS7 verification
                        if (contentTimestampVerifyDigest != null)
                            contentTimestampDigest = contentTimestampVerifyDigest.digest();
                    }
                } else
                    verificationResult = sig.verify(pkcs1SigValue); // PKCS1 verification
            } catch (Exception e) {
                ExceptionHandler.handleNoThrow(e, "error while verifying signature");
                verificationResult = false;
            }
            verified = true;
        }
        return verificationResult;
    }

    private byte[] encodedPKCS7;

    /**
      * Gets the bytes for the PKCS7SignedData object (performs actual signing when sigOut not null)
      * @param secondDigest NOT USED
      * @param signingTime NOT USED
      * @return the bytes for the PKCS7SignedData object
      */
    protected byte[] getEncodedPKCS7(byte secondDigest[], String signingTime) {
        if (encodedPKCS7 == null) {
            try {
                if (cmsSignature == null) {
                    if (adbePkcs7Sha1Data != null) //adbe.pkcs7.sha1
                        sigOut.write(verifyDigest.digest());
                    sigOut.close();
                    byte[] bytes = bOut.toByteArray();
                    this.cmsSignature = new CMSSignedDataWrapper(bytes);
                    if (getServerTimestamp() != null)
                        getUpdatedEncodedPKCS7WithAddedTS();
                }
                encodedPKCS7 = cmsSignature.getEncoded();
            } catch (Exception e) {
                ExceptionHandlerTyped.handle(SignatureException.class, e, "Could not retrieve bytes for signature");
            }
        }
        return encodedPKCS7;
    }

    public byte[] getUpdatedEncodedPKCS7WithAddedTS()
            throws NoSuchAlgorithmException, IOException, NoSuchFieldException, TSPException, CMSException {
        timestampToken = addTSToCMS(cmsSignature, getTimeStampDigestAlgo(), tspClient);
        return cmsSignature.getEncoded();
    }

    public static TimestampToken addTSToCMS(CMSSignedDataWrapper cmsSignature, String algoId, ITspClient tspClient)
            throws NoSuchAlgorithmException, IOException, NoSuchFieldException, TSPException, CMSException {
        //byte[] tsResponse = getTSResponse2(cmsSignature.getSignatureValue(), user, password, serverTimestamp, algoId, policyId, useNonce);
        byte[] tsResponse;
        try {
            byte[] digest = DigestHelper.getDigest(cmsSignature.getSignatureValue(), algoId);
            byte[] fullresponse = tspClient.getRawTsp(digest, algoId);

            TimeStampResponse response = new TimeStampResponse(fullresponse);
            int status = response.getStatus();
            if (status == GRANTED) {
                TimeStampToken tspValue = response.getTimeStampToken();
                tsResponse = tspValue.getEncoded();
            } else
                throw new RuntimeException(
                        "Timestamping failure, status " + status + ", " + response.getStatusString());

        } catch (Exception e) {
            throw new RuntimeException("Error getting timestamp from " + tspClient.getSource(), e);
        }
        TimestampToken timestampToken = new BCTimeStampToken(tsResponse);
        cmsSignature.appendSignatureTimeStamp(timestampToken.getEncoded());
        return timestampToken;
    }
    /*
    public static byte[] getTSResponse2(byte[] hash, String user, String password, String serverTimestamp, String algoId, String policyId, boolean useNonce) throws NoSuchAlgorithmException, IOException, NoSuchFieldException, TSPException, CMSException, SPITimestampException {
      TimeStampProcessor timeStampProcessor = TimeStampProcessorFactory.getInstance().
      getTimeStampProcessor(serverTimestamp, policyId, algoId, true);
      return timeStampProcessor.timestamp(hash);
    }
    public static byte[] getTSResponse2(InputStream stream, String user, String password, String serverTimestamp, String algoId, String policyId, boolean useNonce) throws NoSuchAlgorithmException, IOException, NoSuchFieldException, TSPException, CMSException, SPITimestampException {
      TimeStampProcessor timeStampProcessor = TimeStampProcessorFactory.getInstance().
      getTimeStampProcessor(serverTimestamp, policyId, algoId, true);
      return timeStampProcessor.timestamp(stream);
    }   
        
    protected byte [] getTsp(byte [] hash, String hashAlgorithm) throws Exception
    {
       return tspClient.getTsp(hash, hashAlgorithm);
    }
    */

    /**
     * Get the X.509 certificates associated with this PKCS#7 object
     * @return the X.509 certificates associated with this PKCS#7 object
     */
    public Certificate[] getCertificates() {
        return (X509Certificate[]) certs.toArray(new X509Certificate[certs.size()]);
    }

    /**
     * Get the X.509 certificate revocation lists associated with this PKCS#7 object
     * @return the X.509 certificate revocation lists associated with this PKCS#7 object
     */
    public Collection getCRLs() {
        return crls;
    }

    /**
     * Set the X.509 certificate revocation lists associated with this PKCS#7 object
     * @param crls
     */
    public void setCRLs(Collection crls) {
        this.crls = crls;
    }

    /**
      * Get the X.509 certificate actually used to sign the digest.
      * @return the X.509 certificate actually used to sign the digest
      */
    public X509Certificate getSigningCertificate() {
        return signCert;
    }

    /**
     * Get the version of the PKCS#7 object. Always 1
     * @return the version of the PKCS#7 object. Always 1
     */
    public int getVersion() {
        return version;
    }

    /**
     * Get the version of the PKCS#7 "SignerInfo" object. Always 1
     * @return the version of the PKCS#7 "SignerInfo" object. Always 1
     */
    public int getSigningInfoVersion() {
        return signerversion;
    }

    public ASN1ObjectIdentifier getCmsContentType() {
        return cmsContentType;
    }

    /**
     * Get the algorithm used to calculate the message digest
     * 
     * @return the algorithm used to calculate the message digest
     */
    public String getSignatureAlgorithm() {
        if (keyAndParameterAlgorithm == null)
            return null;
        String dea = keyAndParameterAlgorithm;
        if (keyAndParameterAlgorithm.equals(ID_RSA))
            dea = "RSA";
        else if (keyAndParameterAlgorithm.equals(ID_DSA))
            dea = "DSA";
        else {
            AlgorithmID algo = AlgorithmID.valueOfOID(keyAndParameterAlgorithm);
            if (algo == null)
                algo = AlgorithmID.valueOfTag(keyAndParameterAlgorithm);

            if (algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_MD5)
                    || algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_RIPEMD160)
                    || algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_SHA1)
                    || algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_SHA256)
                    || algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_SHA384)
                    || algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_RSA_SHA512)) {
                dea = "RSA";
            } else if (algo.equals(CryptoConstants.AlgorithmID.SIGNATURE_DSA_SHA1)) {
                dea = "DSA";
            }
        }

        return SignatureHelper.getSignatureAlgoFromDigestAndKeyAlgo(getDataDigestAlgorithm(), dea);
    }

    /**
     * Returns the algorithm.
     * 
     * @return the digest algorithm
     */
    public String getDataDigestAlgorithm() {
        String da = dataDigestAlgorithm;

        AlgorithmID algorithmID = CryptoConstants.AlgorithmID.valueOfOID(dataDigestAlgorithm);
        if (algorithmID != null)
            da = algorithmID.getTag();
        return da;
    }

    /**
     * Loads the default root certificates at &lt;java.home&gt;/lib/security/cacerts
     * with the default provider.
     * @return a <CODE>KeyStore</CODE>
     */
    public static KeyStore loadCacertsKeyStore() {
        return loadCacertsKeyStore(null);
    }

    /**
     * Loads the default root certificates at &lt;java.home&gt;/lib/security/cacerts.
     * @param provider the provider or <code>null</code> for the default provider
     * @return a <CODE>KeyStore</CODE>
     */
    public static KeyStore loadCacertsKeyStore(String provider) {
        File file = new File(System.getProperty("java.home"), "lib");
        file = new File(file, "security");
        file = new File(file, "cacerts");
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(file);
            KeyStore k;
            if (provider == null)
                k = KeyStore.getInstance("JKS");
            else
                k = KeyStore.getInstance("JKS", provider);
            k.load(fin, null);
            return k;
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        } finally {
            try {
                if (fin != null) {
                    fin.close();
                }
            } catch (Exception ex) {
            }
        }
    }

    /**
     * Verifies a single certificate.
     * @param cert the certificate to verify
     * @param crls the certificate revocation list or <CODE>null</CODE>
     * @param calendar the date or <CODE>null</CODE> for the current date
     * @return a <CODE>String</CODE> with the error description or <CODE>null</CODE>
     * if no error
     */
    public static String verifyCertificate(X509Certificate cert, Collection crls, OCSPResponse ocspResponse,
            Calendar calendar) {
        if (calendar == null)
            calendar = new GregorianCalendar();
        if (cert.hasUnsupportedCriticalExtension())
            return "Has unsupported critical extension";
        try {
            cert.checkValidity(calendar.getTime());
        } catch (Exception e) {
            return e.getMessage();
        }
        if (crls != null) {
            for (Iterator it = crls.iterator(); it.hasNext();) {
                if (((CRL) it.next()).isRevoked(cert))
                    return "Certificate revoked";
            }
        }
        if (ocspResponse != null) {
            //TODO implement OCSP response validation
            log.debug(Channel.TECH, "Certificate validation against OCSP response not implemented, skipped");
        }
        return null;
    }

    /**
     * Verifies a certificate chain against a KeyStore.
     * @param certs the certificate chain
     * @param keystore the <CODE>KeyStore</CODE>
     * @param crls the certificate revocation list or <CODE>null</CODE>
     * @param calendar the date or <CODE>null</CODE> for the current date
     * @return <CODE>null</CODE> if the certificate chain could be validated or a
     * <CODE>Object[]{cert,error}</CODE> where <CODE>cert</CODE> is the
     * failed certificate and <CODE>error</CODE> is the error message
     */
    public static Object[] verifyCertificates(Certificate certs[], KeyStore keystore, Collection crls,
            OCSPResponse ocspResponse, Calendar calendar) {
        if (calendar == null)
            calendar = new GregorianCalendar();
        for (int k = 0; k < certs.length; ++k) {
            X509Certificate cert = (X509Certificate) certs[k];
            String err = verifyCertificate(cert, crls, ocspResponse, calendar);
            if (err != null)
                return new Object[] { cert, err };
            try {
                for (Enumeration aliases = keystore.aliases(); aliases.hasMoreElements();) {
                    try {
                        String alias = (String) aliases.nextElement();
                        if (!keystore.isCertificateEntry(alias))
                            continue;
                        X509Certificate certStoreX509 = (X509Certificate) keystore.getCertificate(alias);
                        if (verifyCertificate(certStoreX509, crls, ocspResponse, calendar) != null)
                            continue;
                        try {
                            cert.verify(certStoreX509.getPublicKey());
                            return null;
                        } catch (Exception e) {
                            continue;
                        }
                    } catch (Exception ex) {
                    }
                }
            } catch (Exception e) {
            }
            int j;
            for (j = 0; j < certs.length; ++j) {
                if (j == k)
                    continue;
                X509Certificate certNext = (X509Certificate) certs[j];
                try {
                    cert.verify(certNext.getPublicKey());
                    break;
                } catch (Exception e) {
                }
            }
            if (j == certs.length)
                return new Object[] { cert, "Cannot be verified against the KeyStore or the certificate chain" };
        }
        return new Object[] { null, "Invalid state. Possible circular certificate chain" };
    }

    /**
     * Get the "issuer" from the TBSCertificate bytes that are passed in
     * @param enc a TBSCertificate in a byte array
     * @return a DERObject
     */
    private static DERObject getIssuer(byte[] enc) {
        try {
            ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
            ASN1Sequence seq = (ASN1Sequence) in.readObject();
            return (DERObject) seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
        } catch (IOException e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * Get the "subject" from the TBSCertificate bytes that are passed in
     * @param enc A TBSCertificate in a byte array
     * @return a DERObject
     */
    private static DERObject getSubject(byte[] enc) {
        try {
            ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
            ASN1Sequence seq = (ASN1Sequence) in.readObject();
            return (DERObject) seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4);
        } catch (IOException e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * Get the issuer fields from an X509 Certificate
     * @param cert an X509Certificate
     * @return an X509Name
     */
    public static X509Name getIssuerFields(X509Certificate cert) {
        try {
            return new X509Name((ASN1Sequence) getIssuer(cert.getTBSCertificate()));
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * Get the subject fields from an X509 Certificate
     * @param cert an X509Certificate
     * @return an X509Name
     */
    public static X509Name getSubjectFields(X509Certificate cert) {
        try {
            return new X509Name((ASN1Sequence) getSubject(cert.getTBSCertificate()));
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * Gets the bytes for the PKCS#1 object.
     * @return a byte array
     */
    public byte[] getEncodedPKCS1() {
        try {
            //            if (externalDigest != null)
            //                digest = externalDigest;
            //            else
            pkcs1SigValue = sig.sign();
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();

            ASN1OutputStream dout = new ASN1OutputStream(bOut);
            dout.writeObject(new DEROctetString(pkcs1SigValue));
            dout.close();

            return bOut.toByteArray();
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    /**
     * @deprecated not used anymore
     */
    public void setExternalDigest(byte signature[], byte adbePkcs7Sha1Data[], String digestEncryptionAlgorithm) {
    }

    /**
     * Gets the bytes for the PKCS7SignedData object.
     * @return the bytes for the PKCS7SignedData object
     * @throws SPISignatureException 
     */
    public byte[] getEncodedPKCS7() {
        return getEncodedPKCS7(null, null);
    }

    /**
     * Holds value of properties for timestamp server.
     */
    private String usernameTimestamp = null;

    private String passwordTimestamp = null;

    private String serverTimestamp = null;

    public byte[] getSignedAttrs() throws IOException {
        return cmsSignature.getEncodedSignedAttrs();
    }

    /**
     * @deprecated not used anymore
     */
    public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime) {
        return null;
    }

    public String getReason() {
        return this.reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getLocation() {
        return this.location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getContactInfo() {
        return contactInfo;
    }

    public void setContactInfo(String contactInfo) {
        this.contactInfo = contactInfo;
    }

    public byte[] getDictionaryCert() {
        return dictionaryCert;
    }

    public void setDictionaryCert(byte[] dictionaryCert) {
        this.dictionaryCert = dictionaryCert;
    }

    public int[] getByteRange() {
        return byteRange;
    }

    public void setByteRange(int[] byteRange) {
        this.byteRange = byteRange;
    }

    public byte[] getCONTENTSContent() {
        return contentsKey;
    }

    private int xRefComputedRevision;

    public void setXRefComputedRevision(int xRefComputedRevision) {
        this.xRefComputedRevision = xRefComputedRevision;
    }

    public int getXRefComputedRevision() {
        return xRefComputedRevision;
    }

    //AcroFields properties
    public boolean signatureCoversWholeDocument() {
        return acroFields.signatureCoversWholeDocument(signatureFieldName);
    }

    public int getRevision() {
        return acroFields.getRevision(signatureFieldName);
    }

    public int getTotalRevisions() {
        return acroFields.getTotalRevisions();
    }

    public int getRevisionLength() {
        return acroFields.getRevisionLength(signatureFieldName);
    }

    public float[] getFieldPositions() {
        return acroFields.getFieldPositions(signatureFieldName);
    }

    public List<String> getSignatureNames() {
        return acroFields.getSignatureNames();
    }

    public List<String> getSignatureNames(boolean withDocTS) {
        return acroFields.getSignatureNames(withDocTS);
    }

    public String getSubFilter() {
        return subFilter;
    }

    public Calendar getSignDate() {
        return this.dicoSignDate != null ? this.dicoSignDate : this.cmsSignDate;
    }

    public Calendar getDicoSignDate() {
        return this.dicoSignDate;
    }

    public Calendar getCmsSignDate() {
        return this.cmsSignDate;
    }

    public void setDicoSignDate(Calendar signDate) {
        this.dicoSignDate = signDate;
    }

    public String getSignName() {
        return this.signName;
    }

    public void setSignName(String signName) {
        this.signName = signName;
    }

    /**
     * a class that holds an X509 name
     */
    public static class X509Name {
        /**
         * country code - StringType(SIZE(2))
         */
        public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");

        /**
         * organization - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");

        /**
         * organizational unit name - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");

        /**
         * Title
         */
        public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");

        /**
         * common name - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");

        /**
         * device serial number name - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");

        /**
         * locality name - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");

        /**
         * state, or province name - StringType(SIZE(1..64))
         */
        public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");

        /** Naming attribute of type X520name */
        public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4");
        /** Naming attribute of type X520name */
        public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42");
        /** Naming attribute of type X520name */
        public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43");
        /** Naming attribute of type X520name */
        public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44");
        /** Naming attribute of type X520name */
        public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45");

        /**
         * Email address (RSA PKCS#9 extension) - IA5String.
         * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
         */
        public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");

        /**
         * email address in Verisign certificates
         */
        public static final DERObjectIdentifier E = EmailAddress;

        /** object identifier */
        public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");

        /** LDAP User id. */
        public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");

        /** A LinkedHashMap with default symbols */
        public static LinkedHashMap DefaultSymbols = new LinkedHashMap();

        static {
            DefaultSymbols.put(C, "C");
            DefaultSymbols.put(O, "O");
            DefaultSymbols.put(T, "T");
            DefaultSymbols.put(OU, "OU");
            DefaultSymbols.put(CN, "CN");
            DefaultSymbols.put(L, "L");
            DefaultSymbols.put(ST, "ST");
            DefaultSymbols.put(SN, "SN");
            DefaultSymbols.put(EmailAddress, "E");
            DefaultSymbols.put(DC, "DC");
            DefaultSymbols.put(UID, "UID");
            DefaultSymbols.put(SURNAME, "SURNAME");
            DefaultSymbols.put(GIVENNAME, "GIVENNAME");
            DefaultSymbols.put(INITIALS, "INITIALS");
            DefaultSymbols.put(GENERATION, "GENERATION");
        }
        /** A LinkedHashMap with values */
        public LinkedHashMap values = new LinkedHashMap();

        /**
         * Constructs an X509 name
         * @param seq an ASN1 Sequence
         */
        public X509Name(ASN1Sequence seq) {
            Enumeration e = seq.getObjects();

            while (e.hasMoreElements()) {
                ASN1Set set = (ASN1Set) e.nextElement();

                for (int i = 0; i < set.size(); i++) {
                    ASN1Sequence s = (ASN1Sequence) set.getObjectAt(i);
                    String id = (String) DefaultSymbols.get(s.getObjectAt(0));
                    if (id == null)
                        continue;
                    ArrayList vs = (ArrayList) values.get(id);
                    if (vs == null) {
                        vs = new ArrayList();
                        values.put(id, vs);
                    }
                    vs.add(((DERString) s.getObjectAt(1)).getString());
                }
            }
        }

        /**
         * Constructs an X509 name
         * @param dirName a directory name
         */
        public X509Name(String dirName) {
            X509NameTokenizer nTok = new X509NameTokenizer(dirName);

            while (nTok.hasMoreTokens()) {
                String token = nTok.nextToken();
                int index = token.indexOf('=');

                if (index == -1) {
                    throw new IllegalArgumentException("badly formated directory string");
                }

                String id = token.substring(0, index).toUpperCase();
                String value = token.substring(index + 1);
                ArrayList vs = (ArrayList) values.get(id);
                if (vs == null) {
                    vs = new ArrayList();
                    values.put(id, vs);
                }
                vs.add(value);
            }

        }

        public String getField(String name) {
            ArrayList vs = (ArrayList) values.get(name);
            return vs == null ? null : (String) vs.get(0);
        }

        /**
         * gets a field array from the values LinkedHashMap
         * @param name
         * @return an ArrayList
         */
        public ArrayList getFieldArray(String name) {
            ArrayList vs = (ArrayList) values.get(name);
            return vs == null ? null : vs;
        }

        /**
         * getter for values
         * @return a LinkedHashMap with the fields of the X509 name
         */
        public LinkedHashMap getFields() {
            return values;
        }

        /**
         * @see java.lang.Object#toString()
         */
        public String toString() {
            return values.toString();
        }
    }

    /**
     * class for breaking up an X500 Name into it's component tokens, ala
     * java.util.StringTokenizer. We need this class as some of the
     * lightweight Java environment don't support classes like
     * StringTokenizer.
     */
    public static class X509NameTokenizer {
        private String oid;
        private int index;
        private StringBuffer buf = new StringBuffer();

        public X509NameTokenizer(String oid) {
            this.oid = oid;
            this.index = -1;
        }

        public boolean hasMoreTokens() {
            return (index != oid.length());
        }

        public String nextToken() {
            if (index == oid.length()) {
                return null;
            }

            int end = index + 1;
            boolean quoted = false;
            boolean escaped = false;

            buf.setLength(0);

            while (end != oid.length()) {
                char c = oid.charAt(end);

                if (c == '"') {
                    if (!escaped) {
                        quoted = !quoted;
                    } else {
                        buf.append(c);
                    }
                    escaped = false;
                } else {
                    if (escaped || quoted) {
                        buf.append(c);
                        escaped = false;
                    } else if (c == '\\') {
                        escaped = true;
                    } else if (c == ',') {
                        break;
                    } else {
                        buf.append(c);
                    }
                }
                end++;
            }

            index = end;
            return buf.toString().trim();
        }
    }

    public String getPasswordTimestamp() {
        return passwordTimestamp;
    }

    public void setPasswordTimestamp(String passwordTimestamp) {
        this.passwordTimestamp = passwordTimestamp;
    }

    public String getServerTimestamp() {
        return serverTimestamp;
    }

    public void setServerTimestamp(String serverTimestamp) {
        this.serverTimestamp = serverTimestamp;
    }

    public String getUsernameTimestamp() {
        return usernameTimestamp;
    }

    public void setUsernameTimestamp(String usernameTimestamp) {
        this.usernameTimestamp = usernameTimestamp;
    }

    public byte[] getSignatureValue() {
        return cmsSignature.getSignatureValue();
    }

    public byte[] getDigest() {
        return cmsSignature.getDigestAttribute();
    }

    private byte[] contentTimestampDigest;

    public byte[] getContentTimestampDigest() {
        return contentTimestampDigest;
    }

    public ESSCertID getSigningCertificateAttribute() {
        return cmsSignature.getSigningCertificateAttribute();
    }

    public ESSCertIDv2 getSigningCertificateV2Attribute() {
        return cmsSignature.getSigningCertificateV2Attribute();
    }

    public SignaturePolicyIdentifier getSignaturePolicyIdentifierAttribute() {
        return cmsSignature.getSignaturePolicyIdentifierAttribute();
    }

    public SignerInformationStore getCounterSignatures() {
        return cmsSignature.getCounterSignatures();
    }

    public DEREncodable getContentTypeAttribute() {
        return cmsSignature.getContentTypeAttribute();
    }

    public DEREncodable getContentReferenceAttribute() {
        return cmsSignature.getContentReferenceAttribute();
    }

    public ContentIdentifier getContentIdentifierAttribute() {
        return cmsSignature.getContentIdentifierAttribute();
    }

    public ContentHints getContentHintsAttribute() {
        return cmsSignature.getContentHintsAttribute();
    }

    public CommitmentTypeIndication getCommitmentTypeIndicationAttribute() {
        return cmsSignature.getCommitmentTypeIndicationAttribute();
    }

    public SignerLocation getSignerLocationAttribute() {
        return cmsSignature.getSignerLocationAttribute();
    }

    public SignerAttribute getSignerAttributesAttribute() {
        return cmsSignature.getSignerAttributesAttribute();
    }

    public TimestampToken getContentTimestamp() {
        try {
            return cmsSignature.getContentTimestamp();
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

    public TimestampToken getDocTimeStampValue() {
        return this.docTimestampTStoken;
    }

    public Signature getSig() {
        return sig;
    }

    public void setSig(Signature sig) {
        this.sig = sig;
    }

    public TimestampToken getTimestampToken() {
        return timestampToken;
    }

    public String getTimeStampDigestAlgo() {
        return timeStampDigestAlgo;
    }

    public void setTimeStampDigestAlgo(String timeStampDigestAlgo) {
        this.timeStampDigestAlgo = timeStampDigestAlgo;
    }

    public String getTimeStampPolicyId() {
        return timeStampPolicyId;
    }

    public void setTimeStampPolicyId(String timeStampPolicyId) {
        this.timeStampPolicyId = timeStampPolicyId;
    }

    public boolean isTimeStampUseNonce() {
        return timeStampUseNonce;
    }

    public void setTimeStampUseNonce(boolean timeStampUseNonce) {
        this.timeStampUseNonce = timeStampUseNonce;
    }

    public void setOcspResponses(Collection<OCSPResponse> ocspResponses) {
        this.ocspResponses = ocspResponses;
    }

    public Collection<OCSPResponse> getOcspResponses() {
        return ocspResponses;
    }

    public String getSignatureFieldName() {
        return signatureFieldName;
    }
}