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

ee.sk.digidoc.factory.BouncyCastleNotaryFactory Maven / Gradle / Ivy

Go to download

A Java libray for manipulating Estonian digital signature container files DDOC and BDOC. Note that this library is deprecated. It is recommended to use the new DigiDoc4j library at https://github.com/open-eid/digidoc4j

The newest version!
/*
 * BouncyCastleNotaryFactory.java
 * PROJECT: JDigiDoc
 * DESCRIPTION: Digi Doc functions for creating
 *	handling OCSP requests and responses. 
 * AUTHOR:  Sander Aiaots 
 *  Adopted from Sanders version and converted to
 *  latest level of service by Veiko Sinivee
 *==================================================
 * Copyright (C) AS Sertifitseerimiskeskus
 * 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.
 * GNU Lesser General Public Licence is available at
 * http://www.gnu.org/copyleft/lesser.html
 *==================================================
 */

package ee.sk.digidoc.factory;
import ee.sk.digidoc.DigiDocException;
import ee.sk.digidoc.SignedDoc;
import ee.sk.digidoc.OcspRef;
import ee.sk.utils.ConfigManager;
import ee.sk.utils.ConvertUtils;
import ee.sk.digidoc.Base64Util;
import ee.sk.digidoc.Notary;
import ee.sk.digidoc.Signature;
import ee.sk.digidoc.CertValue;
import ee.sk.digidoc.SignatureValue;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.KeyStore;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Set;
import java.util.Vector;
import java.net.*;
import java.io.*;
import java.util.Random;
import java.security.SecureRandom;
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.ocsp.CertID;
import org.bouncycastle.asn1.ocsp.ResponderID;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.CertificateID;
import org.bouncycastle.cert.ocsp.OCSPReq;
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.cert.ocsp.SingleResp;
import org.bouncycastle.cert.ocsp.RevokedStatus;
import org.bouncycastle.cert.ocsp.UnknownStatus;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
import org.bouncycastle.cert.ocsp.CertificateStatus;
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
import org.bouncycastle.cert.ocsp.Req;
import org.bouncycastle.cert.ocsp.RespID;
import org.bouncycastle.cert.ocsp.jcajce.JcaBasicOCSPRespBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.apache.log4j.Logger;



/**
 * Implements the NotaryFactory by using
 * BouncyCastle JCE toolkit
 * @author  Sander Saiaots, Veiko Sinivee
 * @version 1.0
 */
public class BouncyCastleNotaryFactory implements NotaryFactory 
{
	/** NONCE extendion oid */
    public static final String nonceOid = "1.3.6.1.5.5.7.48.1.2";
    /** cert used to sign to all OCSP requests */
    private X509Certificate m_signCert;
    /** key used to sign all OCSP requests */
    private PrivateKey m_signKey;
    private boolean m_bSignRequests;
    private Logger m_logger = null;
    private static final Random RANDOM_GENERATOR = new SecureRandom();
    
    /** Creates new BouncyCastleNotaryFactory */
    public BouncyCastleNotaryFactory() {
        m_signCert = null;
        m_signKey = null;
        m_bSignRequests = false;
        m_logger = Logger.getLogger(BouncyCastleNotaryFactory.class);
    }
    
    private byte[] createRandomBytes(int byteCount)
    {
      byte[] randomBytes = new byte[byteCount];
      RANDOM_GENERATOR.nextBytes(randomBytes);
      return randomBytes;
    }
    
    /**
     * Returns the n-th OCSP responders certificate if there are many
     * certificates registered for this responder.
     * @param responderCN responder-id's CN
     * @param idx certificate index starting with 0
     * @returns OCSP responders certificate or null if not found
     */
    /*public X509Certificate findNotaryCertByIndex(String responderCN, int idx)
    {
    	X509Certificate cert = null;
    	
    	if(m_logger.isInfoEnabled())
    		m_logger.info("Find responder for: " + responderCN + " index: " + idx);
    	String certKey = null;
    	if(idx == 0)
    		certKey = responderCN;
    	else
    		certKey = responderCN + "-" + idx;
    	if(m_logger.isInfoEnabled())
        	m_logger.info("Searching responder: " + certKey);
    	cert = (X509Certificate)m_ocspCerts.get(certKey);
    	if(m_logger.isInfoEnabled() && cert != null && certKey != null)
    		m_logger.info("Selecting cert " + cert.getSerialNumber().toString() +
    				" key: " + certKey + " valid until: " + cert.getNotAfter().toString());
    	return cert;
    }*/
    
    /**
     * Returns the OCSP responders certificate
     * @param responderCN responder-id's CN
     * @param specificCertNr specific cert number that we search.
     * If this parameter is null then the newest cert is seleced (if many exist)
     * @returns OCSP responders certificate
     */
    public X509Certificate getNotaryCert(String responderCN, String specificCertNr)
    	
    {
    	try {
    	  TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
          return tslFac.findOcspByCN(responderCN, true);
    	} catch(Exception ex) {
    		m_logger.error("Error searching responder cert for: " + responderCN + " - " + ex);
    	}
    	return null;
    }
    
    /**
     * Returns the OCSP responders certificate
     * @param responderCN responder-id's CN
     * @param specificCertNr specific cert number that we search.
     * If this parameter is null then the newest cert is seleced (if many exist)
     * @returns OCSP responders certificate
     */
    public X509Certificate[] getNotaryCerts(String responderCN, String specificCertNr)
    	
    {
    	try {
    	  TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
          return tslFac.findOcspsByCNAndNr(responderCN, true, specificCertNr);
    	} catch(Exception ex) {
    		m_logger.error("Error searching responder cert for: " + responderCN + " - " + ex);
    	}
    	return null;
    }
    
    /**
     * Returns the OCSP responders CA certificate
     * @param responderCN responder-id's CN
     * @returns OCSP responders CA certificate
     */
    public X509Certificate getCACert(String responderCN)
    {
    	try {
      	  TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
      	  X509Certificate cert = tslFac.findOcspByCN(responderCN, true);
      	  if(cert != null)
      	    return tslFac.findCaForCert(cert, true, null);
      	} catch(Exception ex) {
      		m_logger.error("Error searching responder ca cert for: " + responderCN + " - " + ex);
      	}
      	return null;
    }

    
	/**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response
     * @param nonce signature nonce
     * @param signersCert signature owners cert
     * @param notId new id for Notary object
     * @param httpFrom HTTP_FROM header value (optional)
     * @returns Notary object
     * @deprecated use Notary getConfirmation(Signature sig, byte[] nonce, X509Certificate signersCert, X509Certificate caCert,
     *   X509Certificate notaryCert, String notId, String ocspUrl, String httpFrom, String format, String formatVer)
     */
    public Notary getConfirmation(byte[] nonce, 
        X509Certificate signersCert, String notId, String httpFrom) 
        throws DigiDocException
    {        
        TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
        X509Certificate caCert = tslFac.findCaForCert(signersCert, true, null);
        X509Certificate ocspCert = tslFac.findOcspByCN(ConvertUtils.getCommonName(ConvertUtils.convX509Name(signersCert.getIssuerX500Principal())), true);
        return getConfirmation(nonce, signersCert, caCert, ocspCert, notId, httpFrom);
    }
    
    /**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response. Used by DigiDocGenFactory.
     * @param sig Signature object
     * @param nonce signature nonce
     * @param signersCert signature owners cert
     * @param caCert CA cert for this signer
     * @param notaryCert notarys own cert
     * @param notId new id for Notary object
     * @param httpFrom HTTP_FROM header value (optional)
     * @returns Notary object
     */
    public Notary getConfirmation(Signature sig, byte[] nonce, 
        X509Certificate signersCert, X509Certificate caCert,
        X509Certificate notaryCert, String notId, String ocspUrl, 
        String httpFrom, String format, String formatVer) 
        throws DigiDocException 
    {
        Notary not = null;
        OCSPReq req = null;
        OCSPResp resp = null;
        try {        
        	if(m_logger.isDebugEnabled())
                m_logger.debug("getConfirmation, nonce " + Base64Util.encode(nonce, 0) +
                " cert: " + ((signersCert != null) ? signersCert.getSerialNumber().toString() : "NULL") + 
                " CA: " + ((caCert != null) ? caCert.getSerialNumber().toString() : "NULL") +
                " responder: " + ((notaryCert != null) ? notaryCert.getSerialNumber().toString() : "NULL") +
                " notId: " + notId + " signRequest: " + m_bSignRequests +
                " url: " + ocspUrl);
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("Check cert: " + ((signersCert != null) ? signersCert.getSubjectDN().getName() : "NULL"));            	
            	m_logger.debug("Check CA cert: " + ((caCert != null) ? caCert.getSubjectDN().getName() : "NULL"));
        	}
            // create the request - sign the request if necessary
            req = createOCSPRequest(nonce, signersCert, caCert, m_bSignRequests, (sig != null && sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC)));
            //debugWriteFile("req.der", req.getEncoded());
            if(m_logger.isDebugEnabled())
                m_logger.debug("REQUEST:\n" + Base64Util.encode(req.getEncoded(), 0));
            // send it
            resp = sendRequestToUrl(req, ocspUrl, httpFrom, format, formatVer);
            //debugWriteFile("resp.der", resp.getEncoded());
            if(m_logger.isDebugEnabled())
                m_logger.debug("RESPONSE:\n" + ((resp != null) ? Base64Util.encode(resp.getEncoded(), 0) : "NULL"));
            // check response status
            if(resp != null)
            verifyRespStatus(resp);
            // check the result
            not = parseAndVerifyResponse(sig, notId, signersCert, resp, nonce, notaryCert, caCert);
            if(m_logger.isDebugEnabled())
                m_logger.debug("Confirmation OK!");
        } catch(DigiDocException ex) {
        	m_logger.error("Error receiving OCSP confirmation: " + ex + " nonce: " + ConvertUtils.bin2hex(nonce) + " len: " + nonce.length);
        	try {
        	byte[] b = req.getEncoded();
        	m_logger.error("OCSP req: " + ConvertUtils.bin2hex(b) + " len: " + b.length);
        	b = resp.getEncoded();
        	m_logger.error("OCSP req: " + ConvertUtils.bin2hex(b) + " len: " + b.length);
        	} catch(Exception ex2) {
        		m_logger.error("Error converting OCSP info: " + ex2);
        	}
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return not;
    }

    
    /**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response
     * @param nonce signature nonce
     * @param signersCert signature owners cert
     * @param caCert CA cert for this signer
     * @param notaryCert notarys own cert
     * @param notId new id for Notary object
     * @returns Notary object
     * @deprecated use Notary getConfirmation(Signature sig, byte[] nonce, X509Certificate signersCert, X509Certificate caCert,
     *   X509Certificate notaryCert, String notId, String ocspUrl, String httpFrom, String format, String formatVer)
     */
    public Notary getConfirmation(byte[] nonce, 
        X509Certificate signersCert, X509Certificate caCert,
        X509Certificate notaryCert, String notId, String httpFrom) // TODO: remove param notaryCert
        throws DigiDocException 
    {
        return getConfirmation(null, nonce, 
                signersCert, caCert,
                notaryCert, notId, ConfigManager.instance().
            	getProperty("DIGIDOC_OCSP_RESPONDER_URL"), httpFrom, null, null);
    }


    
    /**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response
     * @param sig Signature object. 
     * @param signersCert signature owners cert
     * @param caCert CA cert for this signer
     * @returns Notary object
     * @deprecated use Notary getConfirmation(Signature sig, byte[] nonce, X509Certificate signersCert, X509Certificate caCert,
     *   X509Certificate notaryCert, String notId, String ocspUrl, String httpFrom, String format, String formatVer)
     */
    public Notary getConfirmation(Signature sig, 
        X509Certificate signersCert, X509Certificate caCert) 
        throws DigiDocException 
    {
    	Notary not = null;
        if(sig == null) {
    		throw new DigiDocException(DigiDocException.ERR_INPUT_VALUE, "Signature is NULL for ocsp request!", null);
    	}
        try {
        	String notId = sig.getId().replace('S', 'N');
            // calculate the nonce
        	// test if it works with sha256
            byte[] nonce = SignedDoc.digestOfType(sig.getSignatureValue().getValue(),
            		sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE);
            X509Certificate notaryCert = null;
            if(sig.getUnsignedProperties() != null)
            	notaryCert = sig.getUnsignedProperties().getRespondersCertificate();
            // check the result
            // TODO: select correct ocsp url
            not = getConfirmation(sig, nonce, signersCert, caCert, notaryCert, notId, 
            		ConfigManager.instance().getProperty("DIGIDOC_OCSP_RESPONDER_URL"), 
            		sig.getHttpFrom(), sig.getSignedDoc().getFormat(), sig.getSignedDoc().getVersion());
            // add cert to signature
            if(notaryCert == null && sig != null && sig.getUnsignedProperties() != null) {
            	OCSPResp resp = new OCSPResp(not.getOcspResponseData()); 
            	if(resp != null && resp.getResponseObject() != null) {
            	String respId = responderIDtoString((BasicOCSPResp)resp.getResponseObject());
            	TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
            	notaryCert = tslFac.findOcspByCN(SignedDoc.getCommonName(respId), true); // must use local store here since ocsp certs are not in tsl
            	if(notaryCert != null)
            	  sig.getUnsignedProperties().setRespondersCertificate(notaryCert);
            	  ee.sk.digidoc.CertID cid = new ee.sk.digidoc.CertID(sig, notaryCert, ee.sk.digidoc.CertID.CERTID_TYPE_RESPONDER);
                  sig.addCertID(cid);
                  cid.setUri("#" + sig.getId() + "-RESPONDER_CERT");
            	}
            }
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return not;
    }
    
    /**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response. This getConfirmation() is used by DigiDocGenfactory.
     * @param sig Signature object. 
     * @param signersCert signature owners cert
     * @param caCert CA cert for this signer
     * @param notaryCert OCSP responders cert
     * @param ocspUrl OCSP responders url
     * @returns Notary object
     */
    public Notary getConfirmation(Signature sig, 
        X509Certificate signersCert, X509Certificate caCert, 
        X509Certificate notaryCert, String ocspUrl) 
        throws DigiDocException 
    {
    	
        Notary not = null;
        if(sig == null) {
    		throw new DigiDocException(DigiDocException.ERR_INPUT_VALUE, "Signature is NULL for ocsp request!", null);
    	}
        try {
        	
        	String notId = sig.getId().replace('S', 'N');
            // calculate the nonce
        	// TODO: sha256?
            //byte[] nonce = SignedDoc.digest(sig.getSignatureValue().getValue());
        	byte[] nonce = SignedDoc.digestOfType(sig.getSignatureValue().getValue(),
            		sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE);
        	if(notaryCert == null && sig.getUnsignedProperties() != null)
            	notaryCert = sig.getUnsignedProperties().getRespondersCertificate();
            // check the result
        	
            not = getConfirmation(sig, nonce, signersCert, caCert, notaryCert, notId, ocspUrl, 
            		sig.getHttpFrom(), sig.getSignedDoc().getFormat(), sig.getSignedDoc().getVersion());
            if(not != null && sig.getUnsignedProperties() != null)
            	sig.getUnsignedProperties().setNotary(not);
            // add cert to signature
            if(notaryCert == null && sig != null && sig.getUnsignedProperties() != null && sig.getUnsignedProperties().getNotary() != null) {
            	OCSPResp resp = new OCSPResp(sig.getUnsignedProperties().getNotary().getOcspResponseData()); 
            	if(resp != null && resp.getResponseObject() != null && notaryCert == null) {
            	  String respId = responderIDtoString((BasicOCSPResp)resp.getResponseObject());
            	  TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
                  notaryCert = tslFac.findOcspByCN(ConvertUtils.getCommonName(respId), true);
                  if(notaryCert != null) {
            	  sig.getUnsignedProperties().setRespondersCertificate(notaryCert);
            	  ee.sk.digidoc.CertID cid = new ee.sk.digidoc.CertID(sig, notaryCert, ee.sk.digidoc.CertID.CERTID_TYPE_RESPONDER);
                  sig.addCertID(cid);
                  cid.setUri("#" + sig.getId() + "-RESPONDER_CERT");
                  }
            	}
            }
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return not;
    }

    /**
     * Get confirmation from AS Sertifitseerimiskeskus
     * by creating an OCSP request and parsing the returned
     * OCSP response. CA and reponders certs are read 
     * using paths in the config file or maybe from
     * a keystore etc.
     * @param sig Signature object
     * @param signersCert signature owners cert
     * @returns Notary object
     * @deprecated use Notary getConfirmation(Signature sig, byte[] nonce, X509Certificate signersCert, X509Certificate caCert,
     *   X509Certificate notaryCert, String notId, String ocspUrl, String httpFrom, String format, String formatVer) 
     */
    public Notary getConfirmation(Signature sig, X509Certificate signersCert) 
        throws DigiDocException 
    {
    	String notId = sig.getId().replace('S', 'N');
    	//byte[] nonce = SignedDoc.digest(sig.getSignatureValue().getValue()); // sha256?
    	byte[] nonce = SignedDoc.digestOfType(sig.getSignatureValue().getValue(),
        		sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE);
    	TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
        X509Certificate caCert = tslFac.findCaForCert(signersCert, true, null);
        X509Certificate ocspCert = tslFac.findOcspByCN(ConvertUtils.getCommonName(ConvertUtils.convX509Name(signersCert.getIssuerX500Principal())), true);
        return getConfirmation(nonce, signersCert, caCert, ocspCert, notId, sig.getHttpFrom());
    }
    
    
    
    private String composeHttpFrom()
	{
		// set HTTP_FROM to some value
		String sFrom = null;
		try {
			NetworkInterface ni = null;
			Enumeration eNi = NetworkInterface.getNetworkInterfaces();
			if(eNi != null && eNi.hasMoreElements())
				ni = (NetworkInterface)eNi.nextElement();
			if(ni != null) {
				InetAddress ia = null;
				Enumeration eA = ni.getInetAddresses();
				if(eA != null && eA.hasMoreElements())
					ia = (InetAddress)eA.nextElement();
				if(ia != null)
					sFrom = ia.getHostAddress();
				if(m_logger.isDebugEnabled())
					m_logger.debug("FROM: " + sFrom);
			}
		} catch(Exception ex2) {
			m_logger.error("Error finding ip-adr: " + ex2);
		}
		return sFrom;
	}
    
    /**
     * Verifies the certificate by creating an OCSP request
     * and sending it to SK server.
     * @param cert certificate to verify
     * @param httpFrom HTTP_FROM optional argument
     * @throws DigiDocException if the certificate is not valid
     * @return ocsp response
     * @deprecated not thorougly tested
     */   
    public OCSPResp checkCertificate(X509Certificate cert) 
        throws DigiDocException
    {
    	return checkCertificate(cert, composeHttpFrom());
    }
    
    /**
     * Verifies the certificate by creating an OCSP request
     * and sending it to SK server.
     * @param cert certificate to verify
     * @param httpFrom HTTP_FROM optional argument
     * @throws DigiDocException if the certificate is not valid
     * @return ocsp response
     * @deprecated not thorougly tested
     */   
    public OCSPResp checkCertificate(X509Certificate cert, String httpFrom) 
        throws DigiDocException 
    {
    	OCSPResp resp = null;
        try {
        	// create the request
            DigiDocFactory ddocFac = ConfigManager.instance().getDigiDocFactory();
            TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
            X509Certificate caCert = tslFac.findCaForCert(cert, true, null);
        	if(m_logger.isDebugEnabled()) {
        		m_logger.debug("Find CA for: " + SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())));
            	m_logger.debug("Check cert: " + cert.getSubjectDN().getName());            	
            	m_logger.debug("Check CA cert: " + caCert.getSubjectDN().getName());
        	}
        	byte[] nonce1 = SignedDoc.digest(createRandomBytes(32)); // sha256?
            OCSPReq req = createOCSPRequest(nonce1, cert, caCert, m_bSignRequests, false);
            //debugWriteFile("req1.der", req.getEncoded());
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("Sending ocsp request: " + req.getEncoded().length + " bytes");
                m_logger.debug("REQUEST:\n" + Base64Util.encode(req.getEncoded(), 0));
            }    
            // send it
            String ocspUrl = tslFac.findOcspUrlForCert(cert, 0, true);
            resp = sendRequestToUrl(req, ocspUrl, httpFrom, null, null);
            //debugWriteFile("resp1.der", resp.getEncoded());
            if(m_logger.isDebugEnabled()) {
                m_logger.debug("Got ocsp response: " + ((resp != null) ? resp.getEncoded().length : 0) + " bytes");
                if(resp != null)
                m_logger.debug("RESPONSE:\n" + Base64Util.encode(resp.getEncoded(), 0));
            }
            // check response status
            verifyRespStatus(resp);
            // now read the info from the response
            BasicOCSPResp basResp = 
                (BasicOCSPResp)resp.getResponseObject();
            
            byte[] nonce2 = getNonce(basResp, null);
            if(m_logger.isDebugEnabled()) 
                m_logger.debug("Nonce1: " + ((nonce1 != null) ? ConvertUtils.bin2hex(nonce1) + " len: " + nonce1.length : "NULL") + 
                		" nonce2: " + ((nonce2 != null) ? ConvertUtils.bin2hex(nonce2) + " len: " + nonce2.length : "NULL"));
            if(!SignedDoc.compareDigests(nonce1, nonce2)) 
            	throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL,
                    "Invalid nonce value! Possible replay attack!", null); 
            // verify the response
            try {
            	String respId = responderIDtoString(basResp);
            	X509Certificate notaryCert = getNotaryCert(ConvertUtils.getCommonName(respId), null);
            	boolean bOk = false;
            	if(notaryCert != null) {
            		X509CertificateHolder ch = new X509CertificateHolder(notaryCert.getEncoded());
                	bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
            	} else
            		throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY,
                            "Responder cert not found for: " + respId, null);
            	if(!bOk)
            		throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY,
                            "OCSP verification error!", null);
            } catch (Exception ex) {
                m_logger.error("OCSP Signature verification error!!!", ex); 
                DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_VERIFY);
            } 
            // check the response about this certificate
            checkCertStatus(cert, basResp, caCert);
            
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return resp;
    }

    
    /**
     * Verifies the certificate by creating an OCSP request
     * and sending it to ocsp server.
     * @param cert certificate to verify
     * @param caCert CA certificate
     * @param url OCSP responder url
     * @param bosNonce buffer to return generated nonce
     * @param sbRespId buffer to return responderId field
     * @param bosReq buffer to return ocsp request
     * @param httpFrom http_from atribute
     * @throws DigiDocException if the certificate is not valid
     * @deprecated not thorougly tested
     */   
    public OCSPResp sendCertOcsp(X509Certificate cert, X509Certificate caCert, String url, 
    		ByteArrayOutputStream bosNonce, StringBuffer sbRespId, 
    		ByteArrayOutputStream bosReq, String httpFrom) 
        throws DigiDocException 
    {
        try {
        	OCSPResp resp = null;
        	// create the request
            if(m_logger.isDebugEnabled()) {
        		m_logger.debug("Find CA for: " + SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())));
            	m_logger.debug("Check cert: " + cert.getSubjectDN().getName());            	
            	m_logger.debug("Check CA cert: " + caCert.getSubjectDN().getName());
        	}
        	byte[] nonce1 = SignedDoc.digest(createRandomBytes(32)); //sha256?
        	//byte[] nonce1 = SignedDoc.digestOfType(strTime.getBytes(),
            //		sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE);
            
            bosNonce.write(nonce1);
            OCSPReq req = createOCSPRequest(nonce1, cert, caCert, false, false);
            //debugWriteFile("req1.der", req.getEncoded());
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("Sending ocsp request: " + req.getEncoded().length + " bytes");
                m_logger.debug("REQUEST:\n" + Base64Util.encode(req.getEncoded(), 0));
            }    
            if(req != null && bosReq != null)
            	bosReq.write(req.getEncoded());
            // send it
            resp = sendRequestToUrl(req, url, httpFrom, null, null);
            if(resp != null) {
            BasicOCSPResp basResp = 
                (BasicOCSPResp)resp.getResponseObject();
            String sRespId = responderIDtoString(basResp);
            if(sRespId != null)
            sbRespId.append(sRespId);
            }
            //debugWriteFile("resp1.der", resp.getEncoded());
            if(m_logger.isDebugEnabled()) {
                m_logger.debug("Got ocsp response: " + ((resp != null) ? resp.getEncoded().length : 0) + " bytes");
                if(resp != null)
                m_logger.debug("RESPONSE:\n" + Base64Util.encode(resp.getEncoded(), 0));
            }
            
            return resp;
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return null;
    }
    
    /**
     * Verifies OCSP response by given responder cert. Checks actual certificate status. 
     * @param resp ocsp response
     * @param cert certificate to check
     * @param ocspCert OCSP responders cert
     * @param nonce1 initial nonce value
     * @return true if verified ok
     * @throws DigiDocException
     * @deprecated not thorougly tested
     */
    public boolean checkCertOcsp(OCSPResp resp, X509Certificate cert, 
    		X509Certificate ocspCert, byte[] nonce1, X509Certificate caCert)
    throws DigiDocException
    {
    	try {
    		// check response status
            verifyRespStatus(resp);
            // now read the info from the response
            BasicOCSPResp basResp = 
                (BasicOCSPResp)resp.getResponseObject();
            byte[] nonce2 = getNonce(basResp, null);
            if(!SignedDoc.compareDigests(nonce1, nonce2)) 
            	throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL,
                    "Invalid nonce value! Possible replay attack!", null); 
            // verify the response
            boolean bOk = false;
            try {
            	//String respId = responderIDtoString(basResp);
            	X509CertificateHolder ch = new X509CertificateHolder(ocspCert.getEncoded());
            	bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
            } catch (Exception ex) {
                m_logger.error("OCSP Signature verification error!!!", ex); 
                DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_VERIFY);
            } 
            // check the response about this certificate
            checkCertStatusWithCa(cert, basResp, caCert);
            return bOk;
    	} catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
        return false;
    }
    
    
    /**
     * Verifies the certificate.
     * @param cert certificate to verify
     * @param bUseOcsp flag: use OCSP to verify cert. (obsolete, false,e.g CRL no longer supported)
     * @throws DigiDocException if the certificate is not valid
     * @deprecated not thorougly tested
     */   
    public void checkCertificateOcspOrCrl(X509Certificate cert, boolean bUseOcsp) 
        throws DigiDocException 
    {
        try {
        	// create the request
            TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
            X509Certificate caCert = tslFac.findCaForCert(cert, true, null);
        	if(m_logger.isDebugEnabled()) {
        		m_logger.debug("Find CA for: " + SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())));
            	m_logger.debug("Check cert: " + cert.getSubjectDN().getName());            	
            	m_logger.debug("Check CA cert: " + caCert.getSubjectDN().getName());
        	}
        	byte[] nonce1 = SignedDoc.digest(createRandomBytes(32)); // sha256?
            OCSPReq req = createOCSPRequest(nonce1, cert, caCert, m_bSignRequests, false);
            //debugWriteFile("req1.der", req.getEncoded());
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("Sending ocsp request: " + req.getEncoded().length + " bytes");
                m_logger.debug("REQUEST:\n" + Base64Util.encode(req.getEncoded(), 0));
            }    
            // send it
            OCSPResp resp = sendRequest(req, null, null, null);
            //debugWriteFile("resp1.der", resp.getEncoded());
            if(m_logger.isDebugEnabled()) {
                m_logger.debug("Got ocsp response: " + resp.getEncoded().length + " bytes");
                m_logger.debug("RESPONSE:\n" + Base64Util.encode(resp.getEncoded(), 0));
            }
            // check response status
            verifyRespStatus(resp);
            // now read the info from the response
            BasicOCSPResp basResp = 
                (BasicOCSPResp)resp.getResponseObject();
            byte[] nonce2 = getNonce(basResp, null);
            if(!SignedDoc.compareDigests(nonce1, nonce2)) 
            	throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL,
                    "Invalid nonce value! Possible replay attack!", null); 
            // verify the response
            try {
            	String respId = responderIDtoString(basResp);
            	X509Certificate notaryCert = getNotaryCert(SignedDoc.getCommonName(respId), null);
            	X509CertificateHolder ch = new X509CertificateHolder(notaryCert.getEncoded());
            	boolean bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
            	if(!bOk) {
            		m_logger.error("OCSP Signature verification error!!!"); 
                    throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY, "OCSP Signature verification error!!!", null );
            	}
            } catch (Exception ex) {
                m_logger.error("OCSP Signature verification error!!!", ex); 
                DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_VERIFY);
            } 
            // check the response about this certificate
            checkCertStatus(cert, basResp, caCert);
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);        
        }
    }    
    
    /**
     * Check the response and parse it's data.
     * @param sig Signature object
     * @param resp OCSP response
     * @param nonce1 nonve value used for request
     * @param notaryCert notarys own cert
     * @returns Notary object
     */
    private Notary parseAndVerifyResponse(Signature sig, OCSPResp resp, 
        byte[] nonce1/*, X509Certificate notaryCert*/)
        throws DigiDocException
    {
    	String notId = sig.getId().replace('S', 'N');
    	X509Certificate sigCert = sig.getKeyInfo().getSignersCertificate();
    	return parseAndVerifyResponse(sig, notId, sigCert, resp, nonce1, null, null);
    }
    

    /**
     * Check the response and parse it's data
     * @param sig Signature object
     * @param notId new id for Notary object
     * @param signersCert signature owners certificate
     * @param resp OCSP response
     * @param nonce1 nonve value used for request
     * @returns Notary object
     */
    private Notary parseAndVerifyResponse(Signature sig, String notId, 
    	X509Certificate signersCert, OCSPResp resp, byte[] nonce1, X509Certificate notaryCert, X509Certificate caCert)
        throws DigiDocException
    {
        Notary not = null;
        // check the result
        if(resp == null) {
        	throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL, 
            "OCSP response is null!", null); 
        }
        if(resp.getStatus() != OCSPRespBuilder.SUCCESSFUL) {
            if (resp.getStatus() == OCSPRespBuilder.UNAUTHORIZED){ 
             	throw new DigiDocException(DigiDocException.ERR_OCSP_UNAUTHORIZED, 
                "OCSP response unauthorized! ", null); 
            } else { 
            	throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL, 
                        "OCSP response unsuccessfull!", null); 
            } 
        }
        try {            
            // now read the info from the response
            BasicOCSPResp basResp = 
                (BasicOCSPResp)resp.getResponseObject();
            // find real notary cert suitable for this response
            String respId = responderIDtoString(basResp);
            if(notaryCert == null) {
            	String nCn = ConvertUtils.getCommonName(respId);
            	/*int n = nCn.indexOf(',');
            	if(n > 0)
            		nCn = nCn.substring(0, n); */ // fix CN search
            	notaryCert = getNotaryCert(nCn, null);
            	if(m_logger.isDebugEnabled())
            	  m_logger.debug("Find notary cert: " + nCn + " found: " + ((notaryCert != null) ? "OK" : "NULL"));
            }
            if(notaryCert == null) {
            	throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY, "Notary cert not found for: " + respId, null);
            }
            // verify the response
            boolean bOk = false;
            try {
            	X509CertificateHolder ch = new X509CertificateHolder(notaryCert.getEncoded());
        		bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
            } catch (Exception ex) {
                m_logger.error("OCSP Signature verification error!!!", ex); 
                DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_VERIFY);
            }
            if(!bOk) {
            	 m_logger.error("OCSP Signature verification error!!!"); 
                 throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY, "OCSP Signature verification error!!!", null);
            }
            if(m_logger.isDebugEnabled() && notaryCert != null)
        		m_logger.debug("Using responder cert: " + notaryCert.getSerialNumber().toString());
            // done't care about SingleResponses because we have
            // only one response and the whole response was successfull
            // but we should verify that the nonce hasn't changed
            byte[] nonce2 = getNonce(basResp, (sig != null) ? sig.getSignedDoc() : null);
            boolean ok = true;
            if(nonce1 == null || nonce2 == null || nonce1.length != nonce2.length)
                ok = false;
            for(int i = 0; (nonce1 != null) && (nonce2 != null) && (i < nonce1.length); i++)
                if(nonce1[i] != nonce2[i])
                    ok = false;
            if(m_logger.isDebugEnabled() && notaryCert != null)
        		m_logger.debug("NONCE ddoc: " + ((sig != null) ? sig.getSignedDoc().getFormat() : "NULL") + " ok: " + ok);
            if(!ok && sig != null) {
            	m_logger.error("DDOC ver: " + sig.getSignedDoc().getVersion() + " SIG: " + sig.getId() +
            			" Real nonce: " + Base64Util.encode(nonce2, 0)
            			+ " SigVal hash: " + Base64Util.encode(nonce1, 0)
            			+ " SigVal hash hex: " + ConvertUtils.bin2hex(nonce1));
                throw new DigiDocException(DigiDocException.ERR_OCSP_NONCE,
                   "OCSP response's nonce doesn't match the requests nonce!", null);
            }
            // check the response on our cert
            checkCertStatus(signersCert, basResp, caCert);
            // create notary            
            not = new Notary(notId, resp.getEncoded(), respId, basResp.getProducedAt()); 
            if(notaryCert != null)
            	not.setCertNr(notaryCert.getSerialNumber().toString());
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_PARSE);
        }
        return not;
    }


    /**
     * Verifies that the OCSP response is about our signers
     * cert and the response status is successfull
     * @param sig Signature object
     * @param basResp OCSP Basic response
     * @throws DigiDocException if the response is not successfull
     */
    private void checkCertStatus(Signature sig, BasicOCSPResp basResp)
        throws DigiDocException
    {
        checkCertStatus(sig.getKeyInfo().getSignersCertificate(), basResp, null);
    }
    
    
    /**
     * Verifies that the OCSP response is about our signers
     * cert and the response status is successfull
     * @param sig Signature object
     * @param basResp OCSP Basic response
     * @throws DigiDocException if the response is not successfull
     */
    private void checkCertStatus(X509Certificate cert, BasicOCSPResp basResp, X509Certificate caCert)
        throws DigiDocException
    {
        try {
        	if(m_logger.isDebugEnabled())
            	m_logger.debug("Checking response status, CERT: " + ((cert != null) ? cert.getSubjectDN().getName() : "NULL") + 
            		" SEARCH: " + ((cert != null) ? SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())) : "NULL"));
        	if(cert == null)
        		throw new DigiDocException(DigiDocException.ERR_CERT_UNKNOWN,
        				"No certificate to check! Error reading certificate from file?", null);
            // check the response on our cert
        	TrustServiceFactory tslFac = ConfigManager.instance().getTslFactory();
        	if(caCert == null)
            	caCert = tslFac.findCaForCert(cert, true, null);
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("CA cert: " + ((caCert != null) ? caCert.getSubjectDN().getName() : "NULL"));
            	m_logger.debug("RESP: " + basResp);
            	m_logger.debug("CERT: " + cert.getSubjectDN().getName() + 
            				" ISSUER: " + ConvertUtils.convX509Name(cert.getIssuerX500Principal()) +
            				" nr: " + ((caCert != null) ? ConvertUtils.bin2hex(caCert.getSerialNumber().toByteArray()) : "NULL"));
            }
            if(caCert == null)
            	throw new DigiDocException(DigiDocException.ERR_CERT_UNKNOWN, "Unknown CA cert: " + cert.getIssuerDN().getName(), null);
            SingleResp[] sresp = basResp.getResponses();
            CertificateID rc = creatCertReq(cert, caCert);
            //ertificateID certId = creatCertReq(signersCert, caCert);
            if(m_logger.isDebugEnabled())
                m_logger.debug("Search alg: " + rc.getHashAlgOID() + " cert ser: " + cert.getSerialNumber().toString() +
            	" serial: " + rc.getSerialNumber() + " issuer: " + Base64Util.encode(rc.getIssuerKeyHash()) +
            	" subject: " + Base64Util.encode(rc.getIssuerNameHash()));
            boolean ok = false;
            for(int i=0;i < sresp.length;i++) {
            	CertificateID id = sresp[i].getCertID();
            	if(id != null) {
            		if(m_logger.isDebugEnabled())
                		m_logger.debug("Got alg: " + id.getHashAlgOID() + 
            			" serial: " + id.getSerialNumber() + 
            			" issuer: " + Base64Util.encode(id.getIssuerKeyHash()) +
            			" subject: " + Base64Util.encode(id.getIssuerNameHash()));
            		if(rc.getHashAlgOID().equals(id.getHashAlgOID()) &&
            			rc.getSerialNumber().equals(id.getSerialNumber()) &&
            			SignedDoc.compareDigests(rc.getIssuerKeyHash(), id.getIssuerKeyHash()) &&
            			SignedDoc.compareDigests(rc.getIssuerNameHash(), id.getIssuerNameHash())) {
            			if(m_logger.isDebugEnabled())
                			m_logger.debug("Found it!");
            			ok = true;
            			Object status = sresp[i].getCertStatus();
            			if(status != null) {
            				if(m_logger.isDebugEnabled())
                				m_logger.debug("CertStatus: " + status.getClass().getName());
            			   	if(status instanceof RevokedStatus) {
            			   		m_logger.error("Certificate has been revoked!");
            					throw new DigiDocException(DigiDocException.ERR_CERT_REVOKED,
                    				"Certificate has been revoked!", null);
            			   	}
            			   	if(status instanceof UnknownStatus) {
            			   		m_logger.error("Certificate status is unknown!");
            					throw new DigiDocException(DigiDocException.ERR_CERT_UNKNOWN,
                    				"Certificate status is unknown!", null);
            			   	}
            			   	   	
            			}
            			break;
            		}
            	}
            }

            if(!ok) {
            	if(m_logger.isDebugEnabled())
                	m_logger.debug("Error checkCertStatus - not found ");
                throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    "Bad OCSP response status!", null);
            }
        } catch(DigiDocException ex) {
        	throw ex;
        } catch(Exception ex) {
        	m_logger.error("Error checkCertStatus: " + ex);
        	ex.printStackTrace();
            throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    "Error checking OCSP response status!", null);
        }
    }
    
    
    /**
     * Verifies that the OCSP response is about our signers
     * cert and the response status is successfull
     * @param sig Signature object
     * @param basResp OCSP Basic response
     * @throws DigiDocException if the response is not successfull
     */
    private void checkCertStatusWithCa(X509Certificate cert, BasicOCSPResp basResp, X509Certificate caCert)
        throws DigiDocException
    {
        try {
        	if(m_logger.isDebugEnabled())
            	m_logger.debug("Checking response status, CERT: " + cert.getSubjectDN().getName() + 
            		" SEARCH: " + SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())));
            // check the response on our cert
            //DigiDocFactory ddocFac = ConfigManager.instance().getDigiDocFactory();
        	//X509Certificate caCert = (X509Certificate)m_ocspCACerts.
            //	get(SignedDoc.getCommonName(ConvertUtils.convX509Name(cert.getIssuerX500Principal())));
            if(m_logger.isDebugEnabled()) {
            	m_logger.debug("CA cert: " + ((caCert == null) ? "NULL" : "OK"));
            	m_logger.debug("RESP: " + basResp);
            	m_logger.debug("CERT: " + cert.getSubjectDN().getName() + 
            				" ISSUER: " + ConvertUtils.convX509Name(cert.getIssuerX500Principal()));
            	if(caCert != null)
            	  m_logger.debug("CA CERT: " + caCert.getSubjectDN().getName());
            }
            SingleResp[] sresp = basResp.getResponses();
            CertificateID rc = null;
            if(cert != null && caCert != null)
            rc = creatCertReq(cert, caCert);
            //ertificateID certId = creatCertReq(signersCert, caCert);
            if(m_logger.isDebugEnabled() && rc != null)
                m_logger.debug("Search alg: " + rc.getHashAlgOID() + 
            	" serial: " + rc.getSerialNumber() + " issuer: " + Base64Util.encode(rc.getIssuerKeyHash()) +
            	" subject: " + Base64Util.encode(rc.getIssuerNameHash()));
            boolean ok = false;
            for(int i=0;i < sresp.length;i++) {
            	CertificateID id = sresp[i].getCertID();
            	if(id != null) {
            		if(m_logger.isDebugEnabled())
                		m_logger.debug("Got alg: " + id.getHashAlgOID() + 
            			" serial: " + id.getSerialNumber() + 
            			" issuer: " + Base64Util.encode(id.getIssuerKeyHash()) +
            			" subject: " + Base64Util.encode(id.getIssuerNameHash()));
            		if(rc != null && rc.getHashAlgOID().equals(id.getHashAlgOID()) &&
            			rc.getSerialNumber().equals(id.getSerialNumber()) &&
            			SignedDoc.compareDigests(rc.getIssuerKeyHash(), id.getIssuerKeyHash()) &&
            			SignedDoc.compareDigests(rc.getIssuerNameHash(), id.getIssuerNameHash())) {
            			if(m_logger.isDebugEnabled())
                			m_logger.debug("Found it!");
            			ok = true;
            			Object status = sresp[i].getCertStatus();
            			if(status != null) {
            				if(m_logger.isDebugEnabled())
                				m_logger.debug("CertStatus: " + status.getClass().getName());
            			   	if(status instanceof RevokedStatus) {
            			   		m_logger.error("Certificate has been revoked!");
            					throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    				"Certificate has been revoked!", null);
            			   	}
            			   	if(status instanceof UnknownStatus) {
            			   		m_logger.error("Certificate status is unknown!");
            					throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    				"Certificate status is unknown!", null);
            			   	}
            			   	   	
            			}
            			break;
            		}
            	}
            }

            if(!ok) {
            	if(m_logger.isDebugEnabled())
                	m_logger.debug("Error checkCertStatus - not found ");
                throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    "Bad OCSP response status!", null);
            }
        } catch(DigiDocException ex) {
        	throw ex;
        } catch(Exception ex) {
        	m_logger.error("Error checkCertStatus: " + ex);
        	ex.printStackTrace();
            throw new DigiDocException(DigiDocException.ERR_OCSP_RESP_STATUS,
                    "Error checking OCSP response status!", null);
        }
    }
    
    
    /**
     * Check the response and parse it's data
     * Used by UnsignedProperties.verify()
     * @param not initial Notary object that contains only the
     * raw bytes of an OCSP response
     * @returns Notary object with data parsed from OCSP response
     */
    public Notary parseAndVerifyResponse(Signature sig, Notary not)
        throws DigiDocException
    {
        try {     
        	// DEBUG
        	//debugWriteFile("respin.resp", not.getOcspResponseData());
            OCSPResp  resp = new OCSPResp(not.getOcspResponseData());
            // now read the info from the response
            BasicOCSPResp basResp = (BasicOCSPResp)resp.getResponseObject();
            // verify the response
            X509Certificate[] lNotCerts = null;
            try {
            	String respondIDstr = responderIDtoString(basResp);
            	
            	if(m_logger.isDebugEnabled()) {
                	m_logger.debug("SIG: " + ((sig == null) ? "NULL" : sig.getId()));
                	m_logger.debug("UP: " + ((sig.getUnsignedProperties() == null) ? "NULL" : "OK: " + sig.getUnsignedProperties().getNotary().getId()));
                	m_logger.debug("RESP-CERT: " + ((sig.getUnsignedProperties().
        					getRespondersCertificate() == null) ? "NULL" : "OK"));
                	m_logger.debug("RESP-ID: " + respondIDstr);
                	ee.sk.digidoc.CertID cid = sig.getCertID(ee.sk.digidoc.CertID.CERTID_TYPE_RESPONDER);
                	if(cid != null)
                		m_logger.debug("CID: " + cid.getType() + " id: " + cid.getId() +
                				", " + cid.getSerial() + " issuer: " + cid.getIssuer());
                	m_logger.debug("RESP: " + Base64Util.encode(resp.getEncoded()));
            	}
            	if(lNotCerts == null && sig != null) {
            		String respSrch = respondIDstr;
            		if((respSrch.indexOf("CN") != -1))
            			respSrch = ConvertUtils.getCommonName(respondIDstr);
            		if(respSrch.startsWith("byKey: "))
            			respSrch = respSrch.substring("byKey: ".length());
            		int n1 = respSrch.indexOf(',');
            		if(n1 > 0)
            			respSrch = respSrch.substring(0, n1);
            		if(m_logger.isDebugEnabled())
            			m_logger.debug("Search not cert by: " + respSrch);
            		// TODO: get multiple certs
            		lNotCerts = getNotaryCerts(respSrch, null /*ddocRespCertNr*/);
            	}
            	if(lNotCerts == null || lNotCerts.length == 0)
            		throw new DigiDocException(DigiDocException.ERR_OCSP_RECPONDER_NOT_TRUSTED, 
            				"No certificate for responder: \'" + respondIDstr + "\' found in local certificate store!", null);
            	boolean bOk = false;
            	for(int j = 0; (lNotCerts != null) && (j < lNotCerts.length) && !bOk; j++) {
            		X509Certificate cert = lNotCerts[j];
            		if(m_logger.isDebugEnabled())
            			m_logger.debug("Verify using responders cert: " + 
            					((cert != null) ? ConvertUtils.getCommonName(cert.getSubjectDN().getName()) + " nr: " + cert.getSerialNumber().toString() : "NULL"));
            		if(cert != null) {
            		X509CertificateHolder ch = new X509CertificateHolder(cert.getEncoded());
            		bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
            		} else bOk = false;
            		if(m_logger.isDebugEnabled())
            			m_logger.debug("OCSP resp: " + ((basResp != null) ? responderIDtoString(basResp) : "NULL") +
                			" verify using: " + ((cert != null) ? ConvertUtils.getCommonName(cert.getSubjectDN().getName()) : "NULL") +
                			" verify: " + bOk);
            	}
            	if(bOk) {
            		CertValue cvOcsp = sig.getCertValueOfType(CertValue.CERTVAL_TYPE_RESPONDER);
            		if(cvOcsp != null) {
            		  X509Certificate rCert = cvOcsp.getCert();
            		  if(rCert != null) {
            			X509CertificateHolder ch = new X509CertificateHolder(rCert.getEncoded());
                		bOk = basResp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(ch));
                		if(m_logger.isDebugEnabled())
                			m_logger.debug("OCSP resp: " + ((basResp != null) ? responderIDtoString(basResp) : "NULL") +
                    			" verify using cert in xml: " + ConvertUtils.getCommonName(rCert.getSubjectDN().getName()) +
                    			" verify: " + bOk);
            		  }
            		}
            	}
                if(!bOk)
                  throw new DigiDocException(DigiDocException.ERR_OCSP_VERIFY, "OCSP verification error!", null);
            } catch (Exception ex) {
                m_logger.error("Signature verification error: " + ex); 
                ex.printStackTrace();
                DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_VERIFY);
            } 
            // done't care about SingleResponses because we have
            // only one response and the whole response was successfull
            // but we should verify that the nonce hasn't changed
            // calculate the nonce
            if(m_logger.isDebugEnabled()) 
            	m_logger.debug("Verif sig: " + sig.getId() + " format: " + sig.getSignedDoc().getFormat() + " nonce policy: " + sig.hasBdoc2NoncePolicy());
            boolean ok = true;
            if(sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_SK_XML) ||
               sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_DIGIDOC_XML) ||
              (sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) && sig.hasBdoc2NoncePolicy())) {
            	byte[] nonce1 = SignedDoc.digestOfType(sig.getSignatureValue().getValue(),
                		sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE);
                byte[] nonce2 = getNonce(basResp, sig.getSignedDoc());
                if(nonce1 == null || nonce2 == null || nonce1.length != nonce2.length)
                	ok = false;
                for(int i = 0; (nonce1 != null) && (nonce2 != null) && (i < nonce1.length) && (i < nonce2.length); i++)
                	if(nonce1[i] != nonce2[i])
                		ok = false;
                // TODO: investigate further
                if(!ok && sig.getSignedDoc() != null) {
            	  if(m_logger.isDebugEnabled()) {
                	m_logger.debug("SigVal\n---\n" + Base64Util.encode(sig.getSignatureValue().getValue()) +
                			"\n---\nOCSP\n---\n" + Base64Util.encode(not.getOcspResponseData()) + "\n---\n");
                	m_logger.debug("DDOC ver: " + sig.getSignedDoc().getVersion() + 
            			" SIG: " + sig.getId() + " NOT: " + not.getId() +
            			" Real nonce: " + ((nonce2 != null) ? Base64Util.encode(nonce2, 0) : "NULL") + " noncelen: " + ((nonce2 != null) ? nonce2.length : 0)
            			+ " SigVal hash: " + ((nonce1 != null) ? Base64Util.encode(nonce1, 0) : "NULL")
            			+ " SigVal hash hex: " + ((nonce1 != null) ? ConvertUtils.bin2hex(nonce1) : "NULL")
            			+ " svlen: " + ((nonce1 != null) ? nonce1.length : 0));
                	//m_logger.debug("SIG:\n---\n" + sig.toString() + "\n--\n");
            	  }
                  throw new DigiDocException(DigiDocException.ERR_OCSP_NONCE,
                    "OCSP response's nonce doesn't match the requests nonce!", null);
            	}
            }
            // bdoc 2.0 has to define compliance to nonce policy
            // separate method is used to check all aspects of nonce policy
            /*if(sig.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC) && !sig.hasBdoc2NoncePolicy()) {
            	throw new DigiDocException(DigiDocException.ERR_OCSP_NONCE,
                        "BDOC 2.0 / ASIC-E signatures have to define compliance to nonce policy!", null);
            }*/
            if(m_logger.isDebugEnabled())
            	m_logger.debug("Verify not: " + not.getId());
            checkCertStatus(sig, basResp);
            not.setProducedAt(basResp.getProducedAt());
            not.setResponderId(responderIDtoString(basResp));
        } catch(DigiDocException ex) {
            throw ex;
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_PARSE);
        }
        return not;
    }
    
    
    /**
	 * Get String represetation of ResponderID
	 * @param basResp
	 * @return stringified responder ID
	 */
	private String responderIDtoString(BasicOCSPResp basResp) {
		if(basResp != null) {
			ResponderID respid = basResp.getResponderId().toASN1Primitive();
			Object o = ((DERTaggedObject)respid.toASN1Object()).getObject();
			if(o instanceof org.bouncycastle.asn1.DEROctetString) {
				org.bouncycastle.asn1.DEROctetString oc = (org.bouncycastle.asn1.DEROctetString)o;
				return "byKey: " + SignedDoc.bin2hex(oc.getOctets()); 
			} else {
				X509Name name = new X509Name((ASN1Sequence)o);
				return "byName: " + name.toString();
			}
		}
		else
			return null;
	}
	
	private static final int V_ASN1_OCTET_STRING = 4;
	/**
	 * Method to get NONCE array from responce
	 * @param basResp
	 * @return OCSP nonce value
	 */
	private byte[] getNonce(BasicOCSPResp basResp, SignedDoc sdoc) {
		if(basResp != null) {
			try {
			byte[] nonce2 = null;
			Set extOids = basResp.getNonCriticalExtensionOIDs();
			//if(extOids.size() == 0)
			//	extOids = basResp.getCriticalExtensionOIDs();
			boolean bAsn1=false;
			String sType = null;
			if(m_logger.isDebugEnabled())
        	m_logger.debug("Nonce exts: " + extOids.size());
			if(extOids.size() >= 1) {
				Extension ext = basResp.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
				if(ext != null) {
					if(m_logger.isDebugEnabled())
	            	  m_logger.debug("Ext: " + ext.getExtnId() + " val-len: " + ((ext.getExtnValue() != null) ? ext.getExtnValue().getOctets().length : 0));
					if(ext.getExtnValue() != null && ext.getExtnValue().getOctets() != null && ext.getExtnValue().getOctets().length == 20) {
						nonce2 = ext.getExtnValue().getOctets();
						m_logger.debug("Raw nonce len: " + ((nonce2 != null) ? nonce2.length : 0));
					} else {
	            	  ASN1Encodable extObj = ext.getParsedValue();
					  nonce2 = extObj.toASN1Primitive().getEncoded();
					}
				}
			}
			boolean bCheckOcspNonce = ConfigManager.instance().getBooleanProperty("CHECK_OCSP_NONCE", false);
			if(sdoc != null && sdoc.getFormat() != null && sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) bCheckOcspNonce = true;
			if(sdoc != null && sdoc.getFormat() != null && sdoc.getFormat().equals(SignedDoc.FORMAT_SK_XML)) bCheckOcspNonce = false;
			if(m_logger.isDebugEnabled() && nonce2 != null)
            	m_logger.debug("Nonce hex: " + ConvertUtils.bin2hex(nonce2) + " b64: " + Base64Util.encode(nonce2) + " len: " + nonce2.length + " asn1: " + bAsn1);
			if(sdoc != null && sdoc.getFormat() != null && sdoc.getFormat().equals(SignedDoc.FORMAT_DIGIDOC_XML) || sdoc == null) {
            	if(nonce2 != null && nonce2.length == 22) { //  nonce2[0] == V_ASN1_OCTET_STRING
            		byte[] b = new byte[20];
            		System.arraycopy(nonce2, nonce2.length - 20, b, 0, 20);
            		nonce2 = b;
            		bAsn1=true;
            		sType = "ASN1-NONCE";
            	} 
            }
            if(sdoc != null && sdoc.getFormat() != null && sdoc.getFormat().equals(SignedDoc.FORMAT_BDOC)) {
            	if(nonce2 != null) {
            		sType = ConvertUtils.findDigType(nonce2);
            		if(sType != null) {
            		  byte[] b = ConvertUtils.removePrefix(nonce2);
            		  nonce2 = b;
            		}
            		bAsn1 = (sType != null);
            	}
            }
            if(m_logger.isDebugEnabled() && nonce2 != null)
            	m_logger.debug("Nonce hex: " + ConvertUtils.bin2hex(nonce2) + " b64: " + Base64Util.encode(nonce2) + " len: " + nonce2.length + " type: " + sType);
            else
            	m_logger.debug("No nonce");
            if(!bAsn1 && bCheckOcspNonce) {
        		throw new DigiDocException(DigiDocException.ERR_OCSP_NONCE,
                        "Invalid nonce: " + ((nonce2 != null) ? ConvertUtils.bin2hex(nonce2) + " length: " + nonce2.length : "NO-NONCE") + "!", null);
        	}
            return nonce2;
			} catch(Exception ex) {
				m_logger.error("Error reading ocsp nonce: " + ex);
				ex.printStackTrace();
				return null;
			}
		}
		else
			return null;
	}

	/**
	 * Helper method to verify response status
	 * @param resp OCSP response
	 * @throws DigiDocException if the response status is not ok
	 */
	private void verifyRespStatus(OCSPResp resp) 
		throws DigiDocException 
	{
		if(resp == null || resp.getStatus() != OCSPRespBuilder.SUCCESSFUL)
		    throw new DigiDocException(DigiDocException.ERR_OCSP_UNSUCCESSFULL,
		        "OCSP response unsuccessfull! ", null);
		int status = resp.getStatus();
			switch (status) {
				case OCSPRespBuilder.INTERNAL_ERROR: m_logger.error("An internal error occured in the OCSP Server!"); break;
				case OCSPRespBuilder.MALFORMED_REQUEST: m_logger.error("Your request did not fit the RFC 2560 syntax!"); break;
				case OCSPRespBuilder.SIG_REQUIRED: m_logger.error("Your request was not signed!"); break;
				case OCSPRespBuilder.TRY_LATER: m_logger.error("The server was too busy to answer you!"); break;
				case OCSPRespBuilder.UNAUTHORIZED: m_logger.error("The server could not authenticate you!"); break;
				case OCSPRespBuilder.SUCCESSFUL: break;
				default: m_logger.error("Unknown OCSPResponse status code! "+status);
			}
	}

    
    /**
	 * Method for creating CertificateID for OCSP request
	 * @param signersCert
	 * @param caCert
	 * @param provider
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchProviderException
	 * @throws CertificateEncodingException
	 */
	private CertificateID creatCertReq(X509Certificate signersCert, X509Certificate caCert)
		throws NoSuchAlgorithmException, NoSuchProviderException, 
		CertificateEncodingException, DigiDocException, Exception
	{
		DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().setProvider("BC").build();
		X509CertificateHolder caCertHolder = new X509CertificateHolder(caCert.getEncoded());
		return new CertificateID(dcp.get(CertificateID.HASH_SHA1), caCertHolder, signersCert.getSerialNumber());
	}

    
    
    /**
     * Creates a new OCSP request
     * @param nonce 128 byte RSA+SHA1 signatures digest
     * Use null if you want to verify only the certificate
     * and this is not related to any signature
     * @param signersCert signature owners cert
     * @param caCert CA cert for this signer
     * @param bSigned flag signed request or not
     * @param bBdoc used for BDOC signature
     */
    private OCSPReq createOCSPRequest(byte[] nonce, X509Certificate signersCert, 
    	X509Certificate caCert, boolean bSigned, boolean bBdoc)
        throws DigiDocException 
    {
    	OCSPReq req = null;
    	OCSPReqBuilder ocspRequest = new OCSPReqBuilder();
        try {
        	//Create certificate id, for OCSP request
        	if(m_logger.isDebugEnabled())
      		  m_logger.debug("Request for: " + ((signersCert != null) ? ConvertUtils.getCommonName(ConvertUtils.convX509Name(signersCert.getSubjectX500Principal())) : "NULL") +
      				  " CA: " + ((caCert != null) ? ConvertUtils.getCommonName(ConvertUtils.convX509Name(caCert.getSubjectX500Principal())) : "NULL"));
        	if(signersCert == null) 
        		throw new DigiDocException(DigiDocException.ERR_OCSP_REQ_CREATE, "Missing signers cert for ocsp request", null);
        	if(caCert == null) 
        		throw new DigiDocException(DigiDocException.ERR_OCSP_REQ_CREATE, "Missing CA cert for ocsp request", null);
        	CertificateID certId = creatCertReq(signersCert, caCert);
        	if(m_logger.isDebugEnabled())
    		  m_logger.debug("Request for: " + certId.getHashAlgOID() + 
			  " serial: " + certId.getSerialNumber() + 
			  " issuer: " + ConvertUtils.bin2hex(certId.getIssuerKeyHash()) +
			  " subject: " + ConvertUtils.bin2hex(certId.getIssuerNameHash()) + 
			  " nonce: " + ConvertUtils.bin2hex(nonce) + " len: " + nonce.length);
			ocspRequest.addRequest(certId);
			//if(m_logger.isDebugEnabled())
		    //	  m_logger.debug("Nonce in1: " + ConvertUtils.bin2hex(nonce) + " has-pref: " + ConvertUtils.findDigType(nonce) + " in-len: " + ((nonce != null) ? nonce.length : 0));
			if(nonce != null && ConvertUtils.findDigType(nonce) == null && bBdoc) {
				byte[] b = ConvertUtils.addDigestAsn1Prefix(nonce);
				if(m_logger.isDebugEnabled())
			    	  m_logger.debug("Nonce in: " + ConvertUtils.bin2hex(nonce) + " in-len: " + nonce.length +
			    			  " with-asn1: " + ConvertUtils.bin2hex(b) + " out-len: " + ((b != null) ? b.length : 0) + " out-pref: " + ConvertUtils.findDigType(b));
				nonce = b;
			}
			if(nonce != null) {
				ExtensionsGenerator extGen = new ExtensionsGenerator();
				if(bBdoc)
					extGen.addExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, nonce);
				else
					extGen.addExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false, new DEROctetString(nonce));
		        ocspRequest.setRequestExtensions(extGen.generate());
			}
			GeneralName name = null;
			if(bSigned) {
				if(m_logger.isDebugEnabled())
					m_logger.debug("SignCert: " + ((m_signCert != null) ? m_signCert.toString() : "NULL"));
				if(m_signCert == null)
					throw new DigiDocException(DigiDocException.ERR_INVALID_CONFIG, "Invalid config file! Attempting to sign ocsp request but PKCS#12 token not configured!", null);
				name = new GeneralName(PrincipalUtil.getSubjectX509Principal(m_signCert));
			} else {
				if(signersCert == null)
					throw new DigiDocException(DigiDocException.ERR_OCSP_SIGN, "Signature owners certificate is NULL!", null);
				name = new GeneralName(PrincipalUtil.getSubjectX509Principal(signersCert));
			}
    		ocspRequest.setRequestorName(name);
			if(bSigned) {
				// lets generate signed request
				if(m_logger.isDebugEnabled())
					m_logger.debug("Signing ocsp request with: " + ((m_signCert != null) ? m_signCert.getSubjectX500Principal().getName() : "NULL"));
				X509CertificateHolder[] chain = new X509CertificateHolder[1];
				chain[0] = new X509CertificateHolder(m_signCert.getEncoded());
				req = ocspRequest.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(m_signKey), chain);
				if(!req.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(chain[0]))) {
					m_logger.error("Verify failed");
				}
			} else { // unsigned request
				req = ocspRequest.build();
			}
                
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_REQ_CREATE);
        }
        return req;
    }

    
    /**
     * Sends the OCSP request to Notary and
     * retrieves the response
     * @param req OCSP request
     * @param httpFrom HTTP_FROM value (optional)
     * @returns OCSP response
     */
    private OCSPResp sendRequest(OCSPReq req, String httpFrom, String format, String formatVer)
        throws DigiDocException 
    {
    	String responderUrl = ConfigManager.instance().
        	getProperty("DIGIDOC_OCSP_RESPONDER_URL");
    	return sendRequestToUrl(req, responderUrl, httpFrom, format, formatVer);
    }
    
    private String getUserInfo(String format, String formatVer)
    {
    	StringBuffer sb = null;
    	try {
    		sb = new StringBuffer("LIB ");
    		sb.append(SignedDoc.LIB_NAME);
    		sb.append("/");
    		sb.append(SignedDoc.LIB_VERSION);
    		if(format != null && formatVer != null) {
    			sb.append(" format: ");
        		sb.append(format);
        		sb.append("/");
        		sb.append(formatVer);
    		}
    		sb.append(" Java: ");
    		sb.append(System.getProperty("java.version"));
    		sb.append("/");
    		sb.append(System.getProperty("java.vendor"));
    		sb.append(" OS: ");
    		sb.append(System.getProperty("os.name"));
    		sb.append("/");
    		sb.append(System.getProperty("os.arch"));
    		sb.append("/");
    		sb.append(System.getProperty("os.version"));
    		sb.append(" JVM: ");
    		sb.append(System.getProperty("java.vm.name"));
    		sb.append("/");
    		sb.append(System.getProperty("java.vm.vendor"));
    		sb.append("/");
    		sb.append(System.getProperty("java.vm.version"));
    	} catch(Throwable ex) {
    		m_logger.error("Error reading java system properties: " + ex);
    	}
    	return ((sb != null) ? sb.toString() : null);
    }
    
    /**
     * Sends the OCSP request to Notary and
     * retrieves the response
     * @param req OCSP request
     * @param url OCSP responder url
     * @param httpFrom HTTP_FROM value (optional)
     * @returns OCSP response
     */
    private OCSPResp sendRequestToUrl(OCSPReq req, String url, String httpFrom, String format, String formatVer)
        throws DigiDocException 
    {
        OCSPResp resp = null;
        try {
            byte[] breq = req.getEncoded();
            URL uUrl = new URL(url);
            if(m_logger.isDebugEnabled())
				m_logger.debug("Connecting to ocsp url: " + url);
            URLConnection con = uUrl.openConnection();
            int nTmout = con.getConnectTimeout();
            if(m_logger.isDebugEnabled())
				m_logger.debug("Default connection timeout: " + nTmout + " [ms]");
            int nConfTm = ConfigManager.instance().getIntProperty("OCSP_TIMEOUT", -1);
            if(nConfTm >= 0) {
            	if(m_logger.isDebugEnabled())
    				m_logger.debug("Setting connection and read timeout to: " + nConfTm + " [ms]");
            	con.setConnectTimeout(nConfTm);
            	con.setReadTimeout(nConfTm);
            }
            con.setAllowUserInteraction(false);
            con.setUseCaches(false);
            con.setDoOutput(true);
            con.setDoInput(true);
            // send the OCSP request
            con.setRequestProperty("Content-Type", "application/ocsp-request");
            String sUserInfo = getUserInfo(format, formatVer);
            if(sUserInfo != null) {
            	if(m_logger.isDebugEnabled())
					m_logger.debug("User-Agent: " + sUserInfo);
            	con.setRequestProperty("User-Agent", sUserInfo);
            }
            if(httpFrom != null && httpFrom.trim().length() > 0) {
            	if(m_logger.isDebugEnabled())
					m_logger.debug("X-Forwarded-For: " + httpFrom);
            	con.setRequestProperty("X-Forwarded-For", httpFrom);
            }
            OutputStream os = con.getOutputStream();
            os.write(breq);
            os.close();
            // read the response
            InputStream is = con.getInputStream();
            int cl = con.getContentLength();
            byte[] bresp = null;
            if(cl > 0) {
                int avail = 0;
                do {
                    avail = is.available();
                    byte[] data = new byte[avail];
                    int rc = is.read(data);
                    if(bresp == null) {
                        bresp = new byte[rc];
                        System.arraycopy(data, 0, bresp, 0, rc);
                    } else {
                        byte[] tmp = new byte[bresp.length + rc];
                        System.arraycopy(bresp, 0, tmp, 0, bresp.length);
                        System.arraycopy(data, 0, tmp, bresp.length, rc);
                        bresp = tmp;
                    }
                    cl -= rc;
                } while(cl > 0);
            }
            is.close();
            if(bresp != null) {
                resp = new OCSPResp(bresp);     
            }
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_REQ_SEND);        
        }
        return resp;
    }
    
    
    /**
     * initializes the implementation class
     */
    public void init()
        throws DigiDocException 
    {
    	FileInputStream fi = null;
        try {
            String proxyHost = ConfigManager.instance().
                getProperty("DIGIDOC_PROXY_HOST");
            String proxyPort = ConfigManager.instance().
                getProperty("DIGIDOC_PROXY_PORT");
            if(proxyHost != null && proxyPort != null) {
                System.setProperty("http.proxyHost", proxyHost);
                System.setProperty("http.proxyPort", proxyPort);
            }
            String sigFlag = ConfigManager.
                instance().getProperty("SIGN_OCSP_REQUESTS");
        	m_bSignRequests = (sigFlag != null && sigFlag.equals("true"));
        	// only need this if we must sign the requests
            Provider prv = (Provider)Class.forName(ConfigManager.
                instance().getProperty("DIGIDOC_SECURITY_PROVIDER")).newInstance();
            //prv.list(System.out);
            Security.addProvider(prv);
            
            
        	if(m_bSignRequests) {
            	// load the cert & private key for OCSP signing
            	String p12file = ConfigManager.instance().
                	getProperty("DIGIDOC_PKCS12_CONTAINER");
            	String p12paswd = ConfigManager.instance().
                	getProperty("DIGIDOC_PKCS12_PASSWD");
            	// PKCS#12 container has 2 certs
            	// so use this serial to find the necessary one
            	String p12serial = ConfigManager.instance().
                	getProperty("DIGIDOC_OCSP_SIGN_CERT_SERIAL");
            	if(p12file != null && p12paswd != null) {
                	fi = new FileInputStream(p12file);
                	KeyStore store = KeyStore.getInstance("PKCS12", "BC");
                	store.load(fi, p12paswd.toCharArray());
                	java.util.Enumeration en = store.aliases();
                	// find the key alias
            		String      pName = null;
            		while(en.hasMoreElements()) {
                		String  n = (String)en.nextElement();
                		if (store.isKeyEntry(n)) {
                    		pName = n;
                		}
            		}
					m_signKey = (PrivateKey)store.getKey(pName, null);
					java.security.cert.Certificate[] certs = store.getCertificateChain(pName);
					for(int i = 0; (certs != null) && (i < certs.length); i++) {
						java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)certs[i];
						if(m_logger.isInfoEnabled()) {
                    		m_logger.info("Cert " + i + " subject: " + ConvertUtils.convX509Name(cert.getSubjectX500Principal()));
                    		m_logger.info("Cert " + i + " issuer: " + ConvertUtils.convX509Name(cert.getIssuerX500Principal()));                    
                    		m_logger.info("Cert " + i + " serial: " + cert.getSerialNumber());
                    		m_logger.info("Cert " + i + " is-ca: " + ConvertUtils.isCACert(cert));
						}
                    	if(p12serial != null && cert != null && cert.getSerialNumber().equals(new BigInteger(p12serial)))
                        	m_signCert = (X509Certificate)certs[i];
                	}                   
            	}
        	}
        	

                     
        } catch(Exception ex) {
            DigiDocException.handleException(ex, DigiDocException.ERR_NOT_FAC_INIT);
        } finally {
        	if(fi != null) {
        		try {
        			fi.close();
        			fi = null;
        		} catch(Exception ex2) {
        			m_logger.error("Error closing input stream: " + ex2);
        		}
        	}
        }
    }
    
 
	
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy