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

io.rubrica.ocsp.ValidadorOCSP Maven / Gradle / Ivy

/*
 * Copyright 2009-2017 Rubrica
 *
 * This program 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program.  If not, see .
 */

package io.rubrica.ocsp;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.CertificateID;
import org.bouncycastle.cert.ocsp.CertificateStatus;
import org.bouncycastle.cert.ocsp.OCSPException;
import org.bouncycastle.cert.ocsp.OCSPReq;
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
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.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;

import io.rubrica.core.RubricaException;

/**
 * Clase que permite la validacion de un certificado utilizando OCSP.
 *
 * @author Ricardo Arguello 
 */
public class ValidadorOCSP {

	private static final Logger logger = Logger.getLogger(ValidadorOCSP.class.getName());

	public void validar(X509Certificate checkCert, X509Certificate rootCert, List urls)
			throws IOException, OcspValidationException, RubricaException {

		for (String url : urls) {
			validar(checkCert, rootCert, url);
		}
	}

	public void validar(X509Certificate checkCert, X509Certificate rootCert, String ocspURL)
			throws IOException, OcspValidationException, RubricaException {

		OCSPReq request;

		try {
			request = generateOCSPRequest(rootCert, checkCert.getSerialNumber());
		} catch (CertificateEncodingException | OperatorCreationException | OCSPException e) {
			throw new RubricaException(e);
		}

		byte[] array = request.getEncoded();

		// Enviar la peticion al servidor OCSP:
		URL url = new URL(ocspURL);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		con.setRequestProperty("Content-Type", "application/ocsp-request");
		con.setRequestProperty("Accept", "application/ocsp-response");
		con.setDoOutput(true);

		OutputStream out = con.getOutputStream();
		DataOutputStream dataOut = new DataOutputStream(new BufferedOutputStream(out));
		dataOut.write(array);
		dataOut.flush();
		dataOut.close();

		if (con.getResponseCode() / 100 != 2) {
			throw new RubricaException("Respuesta HTTP inválida: " + con.getResponseCode());
		}

		// Get Response
		InputStream in = (InputStream) con.getContent();
		OCSPResp ocspResponse = new OCSPResp(in);

		System.out.println("ocspResponse.getStatus()" + ocspResponse.getStatus());
		if (ocspResponse.getStatus() != 0) {
			throw new RubricaException("Status HTTP inválido: " + ocspResponse.getStatus());
		}

		BasicOCSPResp basicResponse;
		try {
			basicResponse = (BasicOCSPResp) ocspResponse.getResponseObject();
		} catch (OCSPException e) {
			throw new RubricaException("Problema al decodificar respuesta", e);
		}

		if (basicResponse == null) {
			throw new RubricaException("Respuesta OCSP inválida");
		}

		SingleResp[] responses = basicResponse.getResponses();
		SingleResp response = responses[0];
		CertificateStatus certStatus = response.getCertStatus();

		if (certStatus == CertificateStatus.GOOD) {
			System.out.println("yeah");
			return;
		} else if (certStatus instanceof RevokedStatus) {
			RevokedStatus revokedStatus = (RevokedStatus) certStatus;
			throw new OcspValidationException(revokedStatus.getRevocationReason(), revokedStatus.getRevocationTime());
		} else {
			UnknownStatus unknownStatus = (UnknownStatus) certStatus;
			throw new OcspValidationException();
		}
	}

	private static OCSPReq generateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber)
			throws OperatorCreationException, CertificateEncodingException, OCSPException, IOException {
		// Add provider BC
		Provider prov = new BouncyCastleProvider();
		Security.addProvider(prov);

		DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(prov).build();
		CertificateID id = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1),
				new JcaX509CertificateHolder(issuerCert), serialNumber);

		// Basic request generation with nonce
		OCSPReqBuilder gen = new OCSPReqBuilder();
		gen.addRequest(id);

		// Add nonce extension
		ExtensionsGenerator extGen = new ExtensionsGenerator();
		byte[] nonce = new byte[16];
		Random rand = new Random();
		rand.nextBytes(nonce);
		extGen.addExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, new DEROctetString(nonce));
		gen.setRequestExtensions(extGen.generate());

		// Build request
		return gen.build();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy