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

eu.europa.esig.dss.x509.OCSPToken Maven / Gradle / Ivy

Go to download

DSS Service Provider Interface contains the contract interface shared between the applet and the server-side of DSS.

There is a newer version: 5.4.d4j.1
Show newest version
/**
 * DSS - Digital Signature Services
 * Copyright (C) 2015 European Commission, provided under the CEF programme
 *
 * This file is part of the "DSS - Digital Signature Services" project.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package eu.europa.esig.dss.x509;

import java.io.IOException;
import java.io.StringWriter;
import java.security.PublicKey;
import java.util.List;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.CertificateStatus;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.cert.ocsp.RevokedStatus;
import org.bouncycastle.cert.ocsp.SingleResp;
import org.bouncycastle.cert.ocsp.UnknownStatus;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentVerifierProvider;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.europa.esig.dss.DSSException;
import eu.europa.esig.dss.DSSRevocationUtils;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.SignatureAlgorithm;

/**
 * OCSP Signed Token which encapsulate BasicOCSPResp (BC).
 */
public class OCSPToken extends RevocationToken {

	private static final Logger logger = LoggerFactory.getLogger(OCSPToken.class);

	/**
	 * The encapsulated basic OCSP response.
	 */
	private transient final BasicOCSPResp basicOCSPResp;

	private transient final SingleResp singleResp;

	/**
	 * In case of online source this is the source URI.
	 */
	private String sourceURI;

	/**
	 * The default constructor for OCSPToken.
	 *
	 * @param basicOCSPResp   The basic OCSP response.
	 * @param singleResp
	 */
	public OCSPToken(final BasicOCSPResp basicOCSPResp, final SingleResp singleResp) {

		if (basicOCSPResp == null) {
			throw new NullPointerException();
		}
		if (singleResp == null) {
			throw new NullPointerException();
		}
		this.basicOCSPResp = basicOCSPResp;
		this.singleResp = singleResp;
		this.issuingTime = basicOCSPResp.getProducedAt();
		setStatus(singleResp.getCertStatus());
		final ASN1ObjectIdentifier signatureAlgOID = basicOCSPResp.getSignatureAlgOID();
		final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.forOID(signatureAlgOID.getId());
		this.signatureAlgorithm = signatureAlgorithm;
		this.extraInfo = new TokenValidationExtraInfo();

		if (logger.isTraceEnabled()) {
			logger.trace("OCSP token, produced at '" + DSSUtils.formatInternal(issuingTime) + "' created.");
		}
	}

	private void setStatus(final CertificateStatus certStatus) {

		if (certStatus == null) {
			status = true;
			return;
		}
		if (logger.isInfoEnabled()) {
			logger.info("OCSP certificate status: " + certStatus.getClass().getName());
		}
		if (certStatus instanceof RevokedStatus) {

			if (logger.isInfoEnabled()) {
				logger.info("OCSP status revoked");
			}
			final RevokedStatus revokedStatus = (RevokedStatus) certStatus;
			status = false;
			revocationDate = revokedStatus.getRevocationTime();
            reason = getRevocationReason(revokedStatus);
		} else if (certStatus instanceof UnknownStatus) {

			if (logger.isInfoEnabled()) {
				logger.info("OCSP status unknown");
			}
			reason = "OCSP status: unknown";
		}
	}

	private String getRevocationReason(RevokedStatus revokedStatus) {
		int reasonId = getRevocationReasonId(revokedStatus);
		CRLReason crlReason = CRLReason.lookup(reasonId);
		return crlReason.toString();
	}

    private int getRevocationReasonId(RevokedStatus revokedStatus) {
		try {
			return revokedStatus.getRevocationReason();
		} catch (IllegalStateException e) {
		logger.warn("OCSP Revocation reason is not available: " + e.getMessage());
			return 0; //Zero means 'unspecified'
		}
	}

	/**
	 * @return the ocspResp
	 */

	public BasicOCSPResp getBasicOCSPResp() {

		return basicOCSPResp;
	}

	@Override
	public boolean isSignedBy(final CertificateToken issuerToken) {
		if (this.issuerToken != null) {
			return this.issuerToken.equals(issuerToken);
		}

		try {

			signatureInvalidityReason = "";
			JcaContentVerifierProviderBuilder jcaContentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
			jcaContentVerifierProviderBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
			final PublicKey publicKey = issuerToken.getCertificate().getPublicKey();
			ContentVerifierProvider contentVerifierProvider = jcaContentVerifierProviderBuilder.build(publicKey);
			signatureValid = basicOCSPResp.isSignatureValid(contentVerifierProvider);
			if (signatureValid) {
				this.issuerToken = issuerToken;
			}
			issuerX500Principal = issuerToken.getSubjectX500Principal();
		} catch (Exception e) {
			signatureInvalidityReason = e.getClass().getSimpleName() + " - " + e.getMessage();
			signatureValid = false;
		}
		return signatureValid;
	}

	@Override
	public String getSourceURL() {
		return sourceURI;
	}

	public void setSourceURI(final String sourceURI) {
		this.sourceURI = sourceURI;
	}

	/**
	 * Indicates if the token signature is intact.
	 *
	 * @return {@code true} or {@code false}
	 */
	@Override
	public boolean isValid() {
		return signatureValid;
	}

	/**
	 * This method returns the DSS abbreviation of the certificate. It is used for debugging purpose.
	 *
	 * @return
	 */
	@Override
	public String getAbbreviation() {
		return "OCSPToken[" + DSSUtils.formatInternal(basicOCSPResp.getProducedAt()) + ", signedBy=" + (issuerToken == null ? "?" : issuerToken.getDSSIdAsString()) +
				"]";
	}

	@Override
	public String toString(String indentStr) {
		final StringWriter out = new StringWriter();
		out.append(indentStr).append("OCSPToken[");
		out.append("ProductionTime: ").append(DSSUtils.formatInternal(issuingTime)).append("; ");
		out.append("ThisUpdate: ").append(DSSUtils.formatInternal(singleResp.getThisUpdate())).append("; ");
		out.append("NextUpdate: ").append(DSSUtils.formatInternal(singleResp.getNextUpdate())).append('\n');
		out.append("SignedBy: ").append(issuerToken != null ? issuerToken.getDSSIdAsString() : null).append('\n');
		indentStr += "\t";
		out.append(indentStr).append("Signature algorithm: ").append(signatureAlgorithm == null ? "?" : signatureAlgorithm.getJCEId()).append('\n');
		out.append(issuerToken != null ? issuerToken.toString(indentStr) : null).append('\n');
		final List validationExtraInfo = extraInfo.getValidationInfo();
		if (validationExtraInfo.size() > 0) {

			for (final String info : validationExtraInfo) {

				out.append('\n').append(indentStr).append("\t- ").append(info);
			}
			out.append('\n');
		}
		indentStr = indentStr.substring(1);
		out.append(indentStr).append("]");
		return out.toString();
	}

	@Override
	public byte[] getEncoded() {

		final OCSPResp ocspResp = DSSRevocationUtils.fromBasicToResp(basicOCSPResp);
		try {

			final byte[] bytes = ocspResp.getEncoded();
			return bytes;
		} catch (IOException e) {
			throw new DSSException("OCSP encoding error: " + e.getMessage(), e);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy