Example usage for org.bouncycastle.cms SignerId getIssuer

List of usage examples for org.bouncycastle.cms SignerId getIssuer

Introduction

In this page you can find the example usage for org.bouncycastle.cms SignerId getIssuer.

Prototype

public X500Name getIssuer() 

Source Link

Usage

From source file:be.fedict.eid.applet.service.signer.time.TSPTimeStampService.java

License:Open Source License

public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
    // digest the message
    MessageDigest messageDigest = MessageDigest.getInstance(this.digestAlgo);
    byte[] digest = messageDigest.digest(data);

    // generate the TSP request
    BigInteger nonce = new BigInteger(128, new SecureRandom());
    TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator();
    requestGenerator.setCertReq(true);/* w  w  w .j  av  a 2 s. co m*/
    if (null != this.requestPolicy) {
        requestGenerator.setReqPolicy(this.requestPolicy);
    }
    TimeStampRequest request = requestGenerator.generate(this.digestAlgoOid, digest, nonce);
    byte[] encodedRequest = request.getEncoded();

    // create the HTTP client
    HttpClient httpClient = new HttpClient();
    if (null != this.username) {
        Credentials credentials = new UsernamePasswordCredentials(this.username, this.password);
        httpClient.getState().setCredentials(AuthScope.ANY, credentials);
    }
    if (null != this.proxyHost) {
        httpClient.getHostConfiguration().setProxy(this.proxyHost, this.proxyPort);
    }

    // create the HTTP POST request
    PostMethod postMethod = new PostMethod(this.tspServiceUrl);
    RequestEntity requestEntity = new ByteArrayRequestEntity(encodedRequest, "application/timestamp-query");
    postMethod.addRequestHeader("User-Agent", this.userAgent);
    postMethod.setRequestEntity(requestEntity);

    // invoke TSP service
    int statusCode = httpClient.executeMethod(postMethod);
    if (HttpStatus.SC_OK != statusCode) {
        LOG.error("Error contacting TSP server " + this.tspServiceUrl);
        throw new Exception("Error contacting TSP server " + this.tspServiceUrl);
    }

    // HTTP input validation
    Header responseContentTypeHeader = postMethod.getResponseHeader("Content-Type");
    if (null == responseContentTypeHeader) {
        throw new RuntimeException("missing Content-Type header");
    }
    String contentType = responseContentTypeHeader.getValue();
    if (!contentType.startsWith("application/timestamp-reply")) {
        LOG.debug("response content: " + postMethod.getResponseBodyAsString());
        throw new RuntimeException("invalid Content-Type: " + contentType);
    }
    if (0 == postMethod.getResponseContentLength()) {
        throw new RuntimeException("Content-Length is zero");
    }

    // TSP response parsing and validation
    InputStream inputStream = postMethod.getResponseBodyAsStream();
    TimeStampResponse timeStampResponse = new TimeStampResponse(inputStream);
    timeStampResponse.validate(request);

    if (0 != timeStampResponse.getStatus()) {
        LOG.debug("status: " + timeStampResponse.getStatus());
        LOG.debug("status string: " + timeStampResponse.getStatusString());
        PKIFailureInfo failInfo = timeStampResponse.getFailInfo();
        if (null != failInfo) {
            LOG.debug("fail info int value: " + failInfo.intValue());
            if (PKIFailureInfo.unacceptedPolicy == failInfo.intValue()) {
                LOG.debug("unaccepted policy");
            }
        }
        throw new RuntimeException("timestamp response status != 0: " + timeStampResponse.getStatus());
    }
    TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken();
    SignerId signerId = timeStampToken.getSID();
    BigInteger signerCertSerialNumber = signerId.getSerialNumber();
    X500Principal signerCertIssuer = signerId.getIssuer();
    LOG.debug("signer cert serial number: " + signerCertSerialNumber);
    LOG.debug("signer cert issuer: " + signerCertIssuer);

    // TSP signer certificates retrieval
    CertStore certStore = timeStampToken.getCertificatesAndCRLs("Collection",
            BouncyCastleProvider.PROVIDER_NAME);
    Collection<? extends Certificate> certificates = certStore.getCertificates(null);
    X509Certificate signerCert = null;
    Map<String, X509Certificate> certificateMap = new HashMap<String, X509Certificate>();
    for (Certificate certificate : certificates) {
        X509Certificate x509Certificate = (X509Certificate) certificate;
        if (signerCertIssuer.equals(x509Certificate.getIssuerX500Principal())
                && signerCertSerialNumber.equals(x509Certificate.getSerialNumber())) {
            signerCert = x509Certificate;
        }
        String ski = Hex.encodeHexString(getSubjectKeyId(x509Certificate));
        certificateMap.put(ski, x509Certificate);
        LOG.debug("embedded certificate: " + x509Certificate.getSubjectX500Principal() + "; SKI=" + ski);
    }

    // TSP signer cert path building
    if (null == signerCert) {
        throw new RuntimeException("TSP response token has no signer certificate");
    }
    List<X509Certificate> tspCertificateChain = new LinkedList<X509Certificate>();
    X509Certificate certificate = signerCert;
    do {
        LOG.debug("adding to certificate chain: " + certificate.getSubjectX500Principal());
        tspCertificateChain.add(certificate);
        if (certificate.getSubjectX500Principal().equals(certificate.getIssuerX500Principal())) {
            break;
        }
        String aki = Hex.encodeHexString(getAuthorityKeyId(certificate));
        certificate = certificateMap.get(aki);
    } while (null != certificate);

    // verify TSP signer signature
    timeStampToken.validate(tspCertificateChain.get(0), BouncyCastleProvider.PROVIDER_NAME);

    // verify TSP signer certificate
    this.validator.validate(tspCertificateChain, revocationData);

    LOG.debug("time-stamp token time: " + timeStampToken.getTimeStampInfo().getGenTime());

    byte[] timestamp = timeStampToken.getEncoded();
    return timestamp;
}

From source file:be.fedict.eid.dss.model.bean.TrustValidationServiceBean.java

License:Open Source License

public void validate(TimeStampToken timeStampToken, List<OCSPResp> ocspResponses, List<X509CRL> crls)
        throws CertificateEncodingException, TrustDomainNotFoundException, RevocationDataNotFoundException,
        ValidationFailedException, NoSuchAlgorithmException, NoSuchProviderException, CMSException,
        CertStoreException, IOException {
    LOG.debug("performing historical TSA validation...");
    String tsaTrustDomain = this.configuration.getValue(ConfigProperty.TSA_TRUST_DOMAIN, String.class);
    LOG.debug("TSA trust domain: " + tsaTrustDomain);

    Date validationDate = timeStampToken.getTimeStampInfo().getGenTime();
    LOG.debug("TSA validation date is TST time: " + validationDate);
    LOG.debug("# TSA ocsp responses: " + ocspResponses.size());
    LOG.debug("# TSA CRLs: " + crls.size());

    /*/*from  w  w  w. j a  v a 2s.c o  m*/
     *Building TSA chain. (Code from eID-applet)
     * 
     */

    SignerId signerId = timeStampToken.getSID();
    BigInteger signerCertSerialNumber = signerId.getSerialNumber();
    //X500Principal signerCertIssuer = signerId.getIssuer();

    X500Principal signerCertIssuer = new X500Principal(signerId.getIssuer().getEncoded());

    LOG.debug("signer cert serial number: " + signerCertSerialNumber);
    LOG.debug("signer cert issuer: " + signerCertIssuer);

    // TSP signer certificates retrieval
    CertStore certStore = timeStampToken.getCertificatesAndCRLs("Collection",
            BouncyCastleProvider.PROVIDER_NAME);
    Collection<? extends Certificate> certificates = certStore.getCertificates(null);
    X509Certificate signerCert = null;
    Map<String, X509Certificate> certificateMap = new HashMap<String, X509Certificate>();
    for (Certificate certificate : certificates) {
        X509Certificate x509Certificate = (X509Certificate) certificate;
        if (signerCertIssuer.equals(x509Certificate.getIssuerX500Principal())
                && signerCertSerialNumber.equals(x509Certificate.getSerialNumber())) {
            signerCert = x509Certificate;
        }
        String ski = Hex.encodeHexString(getSubjectKeyId(x509Certificate));
        certificateMap.put(ski, x509Certificate);
        LOG.debug("embedded certificate: " + x509Certificate.getSubjectX500Principal() + "; SKI=" + ski);
    }

    // TSP signer cert path building
    if (null == signerCert) {
        throw new RuntimeException("TSP response token has no signer certificate");
    }
    List<X509Certificate> tspCertificateChain = new LinkedList<X509Certificate>();

    X509Certificate tsaIssuer = loadCertificate(
            "be/fedict/eid/dss/CA POLITICA SELLADO DE TIEMPO - COSTA RICA.crt");
    X509Certificate rootCA = loadCertificate("be/fedict/eid/dss/CA RAIZ NACIONAL COSTA RICA.cer");
    LOG.debug("adding to certificate chain: " + signerCert.getSubjectX500Principal());
    tspCertificateChain.add(signerCert);
    LOG.debug("adding to certificate chain: " + tsaIssuer.getSubjectX500Principal());
    tspCertificateChain.add(tsaIssuer);
    LOG.debug("adding to certificate chain: " + rootCA.getSubjectX500Principal());
    tspCertificateChain.add(rootCA);

    /*
     * Perform PKI validation via eID Trust Service.
     */
    getXkms2Client().validate(tsaTrustDomain, tspCertificateChain, validationDate, ocspResponses, crls);
}

From source file:be.fedict.eid.dss.spi.utils.XAdESUtils.java

License:Open Source License

public static void verifyTimeStampTokenSignature(TimeStampToken timeStampToken)
        throws XAdESValidationException {

    try {// ww  w.  j a  v a  2 s  . c  o m
        SignerId signerId = timeStampToken.getSID();
        BigInteger signerCertSerialNumber = signerId.getSerialNumber();
        //X500Principal signerCertIssuer = signerId.getIssuer();
        X500Principal signerCertIssuer = new X500Principal(signerId.getIssuer().getEncoded());

        CertStore certStore = timeStampToken.getCertificatesAndCRLs("Collection",
                BouncyCastleProvider.PROVIDER_NAME);
        Collection<? extends Certificate> certificates = certStore.getCertificates(null);
        X509Certificate tsaCertificate = null;
        for (Certificate certificate : certificates) {
            X509Certificate x509Certificate = (X509Certificate) certificate;
            if (signerCertIssuer.equals(x509Certificate.getIssuerX500Principal())
                    && signerCertSerialNumber.equals(x509Certificate.getSerialNumber())) {
                tsaCertificate = x509Certificate;
                break;
            }
        }

        if (null == tsaCertificate) {
            throw new XAdESValidationException("TSA certificate not present in TST");
        }

        timeStampToken.validate(tsaCertificate, BouncyCastleProvider.PROVIDER_NAME);
    } catch (Exception e) {
        throw new XAdESValidationException(e);
    }
}

From source file:br.gov.jfrj.siga.cd.TimeStamper.java

License:Open Source License

private static TimeStampToken getTimeStampToken(byte[] content) throws Exception {
    TimeStampToken tsToken;/*  www.j ava2 s. co  m*/

    boolean fSTF = true;

    if (!fSTF) {
        TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();

        reqGen.setCertReq(true);

        MessageDigest md = MessageDigest.getInstance("SHA1");

        md.update(content);

        byte[] assinatura = md.digest();

        TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, assinatura);

        // TimeStampRequestGenerator reqGen = new
        // TimeStampRequestGenerator();
        //
        // // request TSA to return certificate
        // reqGen.setCertReq(true);
        //
        // // Dummy request for sha1
        // // Sha256 "2.16.840.1.101.3.4.2.1", //
        // TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1,
        // MessageDigest.getInstance("SHA").digest(content));

        byte[] reqData = request.getEncoded();

        URL url;
        URLConnection urlConn;
        DataOutputStream printout;
        DataInputStream input;

        Properties systemProperties = System.getProperties();
        systemProperties.setProperty("http.proxyHost", SigaCdProperties.getProxyHost());
        systemProperties.setProperty("http.proxyPort", SigaCdProperties.getProxyPort());

        // URL of CGI-Bin script.
        //url = new URL("http://www.edelweb.fr/cgi-bin/service-tsp");
        url = new URL(SigaCdProperties.getTSPUrl());
        // url = new URL("http://www.cryptopro.ru/tsp/tsp.srf");
        // url = new URL("http://ns.szikszi.hu:8080/tsa");
        // url = new URL("http://time.certum.pl/");
        // URL connection channel.
        urlConn = url.openConnection();
        // Let the run-time system (RTS) know that we want input.
        urlConn.setDoInput(true);
        // Let the RTS know that we want to do output.
        urlConn.setDoOutput(true);
        // No caching, we want the real thing.
        urlConn.setUseCaches(false);
        // Specify the content type.
        urlConn.setRequestProperty("Content-Type", "application/timestamp-query");
        urlConn.setRequestProperty("Content-Length", String.valueOf(reqData.length));

        // Send POST output.
        printout = new DataOutputStream(urlConn.getOutputStream());
        printout.write(reqData);
        printout.flush();
        printout.close();
        // Get response data.
        input = new DataInputStream(urlConn.getInputStream());
        // byte[] ba = streamToByteArray(input);
        TimeStampResponse response = new TimeStampResponse(input);
        input.close();

        tsToken = response.getTimeStampToken();
    } else {

        tsToken = gerarCarimboTempo(content);
    }
    SignerId signer_id = tsToken.getSID();
    BigInteger cert_serial_number = signer_id.getSerialNumber();

    System.out.println("Signer ID serial " + signer_id.getSerialNumber());
    System.out.println("Signer ID issuer " + signer_id.getIssuer().toString());

    Store cs = tsToken.getCertificates();

    Collection certs = cs.getMatches(null);

    Iterator iter = certs.iterator();
    X509Certificate certificate = null;
    while (iter.hasNext()) {
        X509Certificate cert = (X509Certificate) iter.next();

        if (cert_serial_number != null) {
            if (cert.getSerialNumber().equals(cert_serial_number)) {
                System.out.println("using certificate with serial: " + cert.getSerialNumber());
                System.out.println(
                        "using certificate with base 64: " + Base64.encode(cert.getEncoded()) + "\n\n");

                certificate = cert;
            }
        } else {
            if (certificate == null) {
                certificate = cert;
            }
        }
        System.out.println("Certificate subject dn " + cert.getSubjectDN());
        System.out.println("Certificate serial " + cert.getSerialNumber());
    }

    // Nato: validao do carimbo de tempo est desabilitada porque existe
    // um problema no certificado do STF
    if (!fSTF)
        tsToken.validate(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(certificate));

    System.out.println("TS info " + tsToken.getTimeStampInfo().getGenTime());
    System.out.println("TS info " + tsToken.getTimeStampInfo());
    System.out.println("TS info " + tsToken.getTimeStampInfo().getAccuracy());
    System.out.println("TS info " + tsToken.getTimeStampInfo().getNonce());
    return tsToken;
}

From source file:ee.ria.xroad.common.signature.TimestampVerifier.java

License:Open Source License

private static X509Certificate getTspCertificate(SignerId signerId, List<X509Certificate> tspCerts)
        throws Exception {
    log.trace("getTspCertificate({}, {}, {})", new Object[] { signerId.getIssuer(), signerId.getSerialNumber(),
            Arrays.toString(signerId.getSubjectKeyIdentifier()) });
    for (X509Certificate cert : tspCerts) {
        log.trace("Comparing with cert: {}, {}", cert.getIssuerDN(), cert.getSerialNumber());
        if (signerId.match(new X509CertificateHolder(cert.getEncoded()))) {
            return cert;
        }/*from w w  w.  java 2  s .c om*/
    }

    return null;
}

From source file:eu.europa.esig.dss.cades.validation.CAdESSignature.java

License:Open Source License

/**
 * ETSI TS 101 733 V2.2.1 (2013-04)/*from   w  w  w  .  j  a  v  a  2 s.  c o  m*/
 * 5.6.3 Signature Verification Process
 * ...the public key from the first certificate identified in the sequence
 * of certificate identifiers from SigningCertificate shall be the key used
 * to verify the digital signature.
 *
 * @return
 */
@Override
public CandidatesForSigningCertificate getCandidatesForSigningCertificate() {
    if (candidatesForSigningCertificate != null) {
        return candidatesForSigningCertificate;
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug("Searching the signing certificate...");
    }
    candidatesForSigningCertificate = new CandidatesForSigningCertificate();

    final Collection<CertificateToken> keyInfoCertificates = getCertificateSource().getKeyInfoCertificates();
    final SignerId signerId = signerInformation.getSID();
    for (final CertificateToken certificateToken : keyInfoCertificates) {

        final CertificateValidity certificateValidity = new CertificateValidity(certificateToken);
        candidatesForSigningCertificate.add(certificateValidity);

        final X509CertificateHolder x509CertificateHolder = DSSASN1Utils
                .getX509CertificateHolder(certificateToken);
        final boolean match = signerId.match(x509CertificateHolder);
        if (match) {

            this.signingCertificateValidity = certificateValidity;
            break;
        }
    }
    if (signingCertificateValidity == null) {
        LOG.warn("Signing certificate not found: " + signerId.getIssuer() + " " + signerId.getSerialNumber());
    } else if (!verifySignedReferencesToSigningCertificate()) {
        LOG.warn("There is no valid signed reference to the signing certificate: "
                + signingCertificateValidity.getCertificateToken().getAbbreviation());
    }
    return candidatesForSigningCertificate;
}

From source file:mitm.common.security.cms.SignerInfoImpl.java

License:Open Source License

@Override
public SignerIdentifier getSignerId() throws IOException {
    SignerId id = signerInformation.getSID();

    return new SignerIdentifierImpl(X500PrincipalUtils.fromX500Name(id.getIssuer()), id.getSerialNumber(),
            id.getSubjectKeyIdentifier());
}

From source file:net.ripe.rpki.commons.provisioning.cms.ProvisioningCmsObjectParser.java

License:BSD License

/**
 * http://tools.ietf.org/html/draft-ietf-sidr-rescerts-provisioning-09#section-3.1.1.6.2
 *///from   w  w w.j  a  v  a 2s .  c  o  m
private void verifySubjectKeyIdentifier(SignerInformation signer) {
    SignerId sid = signer.getSID();
    validationResult.rejectIfFalse(Arrays.equals(X509CertificateUtil.getSubjectKeyIdentifier(cmsCertificate),
            sid.getSubjectKeyIdentifier()), CMS_SIGNER_INFO_SKI);
    validationResult.rejectIfFalse(sid.getIssuer() == null && sid.getSerialNumber() == null,
            CMS_SIGNER_INFO_SKI_ONLY);
}

From source file:net.sf.jsignpdf.verify.VerifierLogic.java

License:Mozilla Public License

public Exception validateTimeStampToken(TimeStampToken token) {
    if (token == null) {
        return null;
    }/*  w w  w  . j a  v  a  2  s .co  m*/
    try {
        SignerId signer = token.getSID();

        X509Certificate certificate = null;
        X500Principal sign_cert_issuer = signer.getIssuer();
        BigInteger sign_cert_serial = signer.getSerialNumber();

        CertStore store = token.getCertificatesAndCRLs("Collection", "BC");

        // Iterate CertStore to find a signing certificate
        Collection<? extends Certificate> certs = store.getCertificates(null);
        Iterator<? extends Certificate> iter = certs.iterator();

        while (iter.hasNext()) {
            X509Certificate cert = (X509Certificate) iter.next();
            if (cert.getIssuerX500Principal().equals(sign_cert_issuer)
                    && cert.getSerialNumber().equals(sign_cert_serial)) {
                certificate = cert;
                break;
            }
        }

        if (certificate == null) {
            throw new TSPException("Missing signing certificate for TSA.");
        }

        // check TS token's certificate against keystore
        if (certs.size() == 1) {
            boolean verifyTimestampCertificates = PdfPKCS7.verifyTimestampCertificates(token, kall, null);
            if (!verifyTimestampCertificates) {
                throw new Exception("Timestamp certificate can't be verified.");
            }
        } else {
            int certSize = certs.size();
            Certificate[] array = certs.toArray(new Certificate[certSize]);
            Certificate[] certArray = new Certificate[certSize];
            // reverse order
            for (int i = 0; i < certSize; i++) {
                certArray[i] = array[certSize - 1 - i];
            }
            // token.validate(SignerInformationVerifier) will check if certificate has been valid at the time the timestamp was created
            Object[] verifyCertificates = PdfPKCS7.verifyCertificates(certArray, kall, null, null);
            if (verifyCertificates != null) {
                throw new Exception("Timestamp certificate can't be verified.");
            }
        }

        SignerInformationVerifier verifier = new JcaSimpleSignerInfoVerifierBuilder().build(certificate);
        token.validate(verifier);
    } catch (Exception e) {
        return e;
    }
    return null;
}

From source file:org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService.java

License:Apache License

@SuppressWarnings("unchecked")
public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
    // digest the message
    MessageDigest messageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getTspDigestAlgo());
    byte[] digest = messageDigest.digest(data);

    // generate the TSP request
    BigInteger nonce = new BigInteger(128, new SecureRandom());
    TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator();
    requestGenerator.setCertReq(true);//www  .j a  v a 2 s  .co m
    String requestPolicy = signatureConfig.getTspRequestPolicy();
    if (requestPolicy != null) {
        requestGenerator.setReqPolicy(new ASN1ObjectIdentifier(requestPolicy));
    }
    ASN1ObjectIdentifier digestAlgoOid = mapDigestAlgoToOID(signatureConfig.getTspDigestAlgo());
    TimeStampRequest request = requestGenerator.generate(digestAlgoOid, digest, nonce);
    byte[] encodedRequest = request.getEncoded();

    // create the HTTP POST request
    Proxy proxy = Proxy.NO_PROXY;
    if (signatureConfig.getProxyUrl() != null) {
        URL proxyUrl = new URL(signatureConfig.getProxyUrl());
        String host = proxyUrl.getHost();
        int port = proxyUrl.getPort();
        proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, (port == -1 ? 80 : port)));
    }

    HttpURLConnection huc = (HttpURLConnection) new URL(signatureConfig.getTspUrl()).openConnection(proxy);

    if (signatureConfig.getTspUser() != null) {
        String userPassword = signatureConfig.getTspUser() + ":" + signatureConfig.getTspPass();
        String encoding = DatatypeConverter
                .printBase64Binary(userPassword.getBytes(Charset.forName("iso-8859-1")));
        huc.setRequestProperty("Authorization", "Basic " + encoding);
    }

    huc.setRequestMethod("POST");
    huc.setConnectTimeout(20000);
    huc.setReadTimeout(20000);
    huc.setDoOutput(true); // also sets method to POST.
    huc.setRequestProperty("User-Agent", signatureConfig.getUserAgent());
    huc.setRequestProperty("Content-Type", signatureConfig.isTspOldProtocol() ? "application/timestamp-request"
            : "application/timestamp-query"); // "; charset=ISO-8859-1");

    OutputStream hucOut = huc.getOutputStream();
    hucOut.write(encodedRequest);

    // invoke TSP service
    huc.connect();

    int statusCode = huc.getResponseCode();
    if (statusCode != 200) {
        LOG.log(POILogger.ERROR, "Error contacting TSP server ", signatureConfig.getTspUrl());
        throw new IOException("Error contacting TSP server " + signatureConfig.getTspUrl());
    }

    // HTTP input validation
    String contentType = huc.getHeaderField("Content-Type");
    if (null == contentType) {
        throw new RuntimeException("missing Content-Type header");
    }

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    IOUtils.copy(huc.getInputStream(), bos);
    LOG.log(POILogger.DEBUG, "response content: ", bos.toString());

    if (!contentType.startsWith(signatureConfig.isTspOldProtocol() ? "application/timestamp-response"
            : "application/timestamp-reply")) {
        throw new RuntimeException("invalid Content-Type: " + contentType);
    }

    if (bos.size() == 0) {
        throw new RuntimeException("Content-Length is zero");
    }

    // TSP response parsing and validation
    TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray());
    timeStampResponse.validate(request);

    if (0 != timeStampResponse.getStatus()) {
        LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus());
        LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString());
        PKIFailureInfo failInfo = timeStampResponse.getFailInfo();
        if (null != failInfo) {
            LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue());
            if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) {
                LOG.log(POILogger.DEBUG, "unaccepted policy");
            }
        }
        throw new RuntimeException("timestamp response status != 0: " + timeStampResponse.getStatus());
    }
    TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken();
    SignerId signerId = timeStampToken.getSID();
    BigInteger signerCertSerialNumber = signerId.getSerialNumber();
    X500Name signerCertIssuer = signerId.getIssuer();
    LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber);
    LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer);

    // TSP signer certificates retrieval
    Collection<X509CertificateHolder> certificates = timeStampToken.getCertificates().getMatches(null);

    X509CertificateHolder signerCert = null;
    Map<X500Name, X509CertificateHolder> certificateMap = new HashMap<X500Name, X509CertificateHolder>();
    for (X509CertificateHolder certificate : certificates) {
        if (signerCertIssuer.equals(certificate.getIssuer())
                && signerCertSerialNumber.equals(certificate.getSerialNumber())) {
            signerCert = certificate;
        }
        certificateMap.put(certificate.getSubject(), certificate);
    }

    // TSP signer cert path building
    if (signerCert == null) {
        throw new RuntimeException("TSP response token has no signer certificate");
    }
    List<X509Certificate> tspCertificateChain = new ArrayList<X509Certificate>();
    JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter();
    x509converter.setProvider("BC");
    X509CertificateHolder certificate = signerCert;
    do {
        LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject());
        tspCertificateChain.add(x509converter.getCertificate(certificate));
        if (certificate.getSubject().equals(certificate.getIssuer())) {
            break;
        }
        certificate = certificateMap.get(certificate.getIssuer());
    } while (null != certificate);

    // verify TSP signer signature
    X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded());
    DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator();
    DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder();
    DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder();
    BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider();
    BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder,
            hashAlgoFinder, calculator);
    SignerInformationVerifier verifier = verifierBuilder.build(holder);

    timeStampToken.validate(verifier);

    // verify TSP signer certificate
    if (signatureConfig.getTspValidator() != null) {
        signatureConfig.getTspValidator().validate(tspCertificateChain, revocationData);
    }

    LOG.log(POILogger.DEBUG, "time-stamp token time: " + timeStampToken.getTimeStampInfo().getGenTime());

    byte[] timestamp = timeStampToken.getEncoded();
    return timestamp;
}