org.digidoc4j.impl.bdoc.OcspNonceValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.digidoc4j.impl.bdoc.OcspNonceValidator.java

Source

/* DigiDoc4J library
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*/

package org.digidoc4j.impl.bdoc;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.DigestAlgorithm;
import eu.europa.esig.dss.xades.validation.XAdESSignature;

public class OcspNonceValidator implements Serializable {

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

    private XAdESSignature signature;
    private BasicOCSPResp ocspResponse;

    public OcspNonceValidator(XAdESSignature signature) {
        this.signature = signature;
        ocspResponse = getLatestOcspResponse(signature.getOCSPSource().getContainedOCSPResponses());
    }

    public boolean isValid() {
        if (signature.getPolicyId() == null) {
            return true;
        }
        if (ocspResponse == null) {
            logger.debug("OCSP response was not found in signature: " + signature.getId());
            return true;
        }
        return isOcspResponseValid(ocspResponse);
    }

    private BasicOCSPResp getLatestOcspResponse(List<BasicOCSPResp> ocspResponses) {
        if (ocspResponses.size() == 0) {
            return null;
        }

        BasicOCSPResp basicOCSPResp = ocspResponses.get(0);
        Date latestDate = basicOCSPResp.getProducedAt();

        for (int i = 1; i < ocspResponses.size(); i++) {
            BasicOCSPResp ocspResponse = ocspResponses.get(i);
            if (ocspResponse.getProducedAt().after(latestDate)) {
                latestDate = ocspResponse.getProducedAt();
                basicOCSPResp = ocspResponse;
            }
        }
        return basicOCSPResp;
    }

    private boolean isOcspResponseValid(BasicOCSPResp latestOcspResponse) {
        Extension extension = latestOcspResponse.getExtension(new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1.2"));
        if (extension == null) {
            logger.error("No valid OCSP extension found in signature: " + signature.getId());
            return false;
        }
        return isOcspExtensionValid(extension);
    }

    private boolean isOcspExtensionValid(Extension extension) {
        try {
            byte[] octets = extension.getExtnValue().getOctets();
            byte[] signatureDigestValue = getSignatureDigestValue(octets);
            byte[] foundHash = ((DEROctetString) ASN1Sequence.getInstance(octets).getObjectAt(1)).getOctets();
            boolean extensionHashMatchesSignatureHash = Arrays.equals(foundHash, signatureDigestValue);
            logger.debug("OCSP extension contains valid signature digest: " + extensionHashMatchesSignatureHash);
            return extensionHashMatchesSignatureHash;
        } catch (Exception e) {
            logger.error("Invalid nonce format: " + e.getMessage());
            return false;
        }
    }

    private byte[] getSignatureDigestValue(byte[] octets) {
        DigestAlgorithm usedDigestAlgorithm = getExtensionDigestAlgorithm(octets);
        String signatureValueInBase64 = signature.getSignatureValue().getFirstChild().getNodeValue();
        byte[] signatureValue = Base64.decodeBase64(signatureValueInBase64.getBytes());
        return DSSUtils.digest(usedDigestAlgorithm, signatureValue);
    }

    private DigestAlgorithm getExtensionDigestAlgorithm(byte[] octets) {
        ASN1Encodable oid = ASN1Sequence.getInstance(octets).getObjectAt(0);
        String oidString = ((DLSequence) oid).getObjects().nextElement().toString();
        return DigestAlgorithm.forOID(oidString);
    }
}