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

ee.sk.digidoc.UnsignedProperties Maven / Gradle / Ivy

/*
 * UnsignedProperties.java
 * PROJECT: JDigiDoc
 * DESCRIPTION: Digi Doc functions for creating
 *	and reading signed documents. 
 * AUTHOR:  Veiko Sinivee, S|E|B IT Partner Estonia
 *==================================================
 * 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;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Vector;
import java.security.cert.X509Certificate;
import ee.sk.utils.ConvertUtils;
import ee.sk.utils.ConfigManager;
import ee.sk.digidoc.factory.BouncyCastleNotaryFactory;
import ee.sk.digidoc.factory.NotaryFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.log4j.Logger;


/**
 * Models the unsigned properties of
 * a signature.
 * @author  Veiko Sinivee
 * @version 1.0
 */
public class UnsignedProperties implements Serializable
{
	private static final long serialVersionUID = 1L;
    /** signature reference */
    private Signature m_signature;
    /** CompleteCertificateRefs object */
    private CompleteCertificateRefs m_certRefs;
    /** CompleteRevocationRefs object */
    private CompleteRevocationRefs m_revRefs;
    /** Notary object */
    private Vector m_notaries;
    private static Logger m_logger = Logger.getLogger(UnsignedProperties.class);
    /** 
     * Creates new UsignedProperties 
     * Initializes everything to null
     * @param sig signature reference
     */
    public UnsignedProperties(Signature sig) {
        m_signature = sig;
        m_certRefs = null;
        m_revRefs = null;
        m_notaries = null;
    }
    
    /** 
     * Creates new UsignedProperties 
     * @param sig signature reference
     * @param crefs responders cert digest & info
     * @param rrefs OCSP response digest & info
     */
    public UnsignedProperties(Signature sig, CompleteCertificateRefs crefs,
        CompleteRevocationRefs rrefs) 
        throws DigiDocException
    {
        m_signature = sig;
        setCompleteCertificateRefs(crefs);
        setCompleteRevocationRefs(rrefs);
   }
    
    /**
     * Accessor for completeCertificateRefs attribute
     * @return value of completeCertificateRefs attribute
     */
    public CompleteCertificateRefs getCompleteCertificateRefs() {
        return m_certRefs;
    }
    
    /**
     * Accessor for signature attribute
     * @return value of signature attribute
     */
    public Signature getSignature()
    {
    	return m_signature;
    }
    
    /**
     * Mutator for completeCertificateRefs attribute
     * @param str new value for completeCertificateRefs attribute
     * @throws DigiDocException for validation errors
     */    
    public void setCompleteCertificateRefs(CompleteCertificateRefs crefs) 
        throws DigiDocException
    {
        //ArrayList errs = crefs.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_certRefs = crefs;
    }
    
    /**
     * Accessor for completeRevocationRefs attribute
     * @return value of completeRevocationRefs attribute
     */
    public CompleteRevocationRefs getCompleteRevocationRefs() {
        return m_revRefs;
    }
    
    /**
     * Mutator for completeRevocationRefs attribute
     * @param str new value for completeRevocationRefs attribute
     * @throws DigiDocException for validation errors
     */    
    public void setCompleteRevocationRefs(CompleteRevocationRefs refs) 
        throws DigiDocException
    {
        //ArrayList errs = refs.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_revRefs = refs;
    }
    
    /**
     * Accessor for respondersCertificate attribute
     * @return value of respondersCertificate attribute
     */
    public X509Certificate getRespondersCertificate() {
    	X509Certificate cert = null;
    	if(m_signature != null) {
    		CertValue cval = m_signature.getCertValueOfType(CertValue.CERTVAL_TYPE_RESPONDER);
        	if(cval != null)
    			cert = cval.getCert();
    	}
        return cert;
    }
    
    /**
     * Mutator for respondersCertificate attribute
     * @param cert new value for respondersCertificate attribute
     * @throws DigiDocException for validation errors
     */    
    public void setRespondersCertificate(X509Certificate cert) 
        throws DigiDocException
    {
    	
       if(m_signature != null && cert != null) {
    		CertValue cval = m_signature.getOrCreateCertValueOfType(CertValue.CERTVAL_TYPE_RESPONDER);
    		cval.setId(m_signature.getId() + "-RESPONDER_CERT");
    		cval.setCert(cert);
    	}
    }
    
    /**
     * Helper method to validate a responders cert
     * @param cert input data
     * @return exception or null for ok
     */
    private DigiDocException validateRespondersCertificate(X509Certificate cert)
    {
        DigiDocException ex = null;
        return ex;
    }
    
    /**
     * Get the n-th Notary object
     * @param nIdx Notary index
     * @return Notary object
     */
    public Notary getNotaryById(int nIdx)
    {
    	if(m_notaries != null && nIdx < m_notaries.size())
    		return (Notary)m_notaries.elementAt(nIdx);
    	else
    		return null;
    }
    
    /**
     * Add a new Notary
     * @param not Notary object
     */
    public void addNotary(Notary not)
    {
    	if(m_notaries == null)
        	m_notaries = new Vector();
    	m_notaries.add(not);
    }
    
    /**
     * Count the number of Notary objects
     * @return number of Notary objects
     */
    public int countNotaries() { return (m_notaries != null) ? m_notaries.size() : 0; }
    
    /**
     * Accessor for notary attribute
     * @return value of notary attribute
     */
    public Notary getNotary() {
    	return getNotaryById(0);
    }
    
    /**
     * Accessor for notary attribute
     * @return value of notary attribute
     */
    public Notary getLastNotary() {
    	return getNotaryById(countNotaries()-1);
    }
    
    /**
     * Mutator for notary attribute
     * @param str new value for notary attribute
     * @throws DigiDocException for validation errors
     */    
    public void setNotary(Notary not) 
        throws DigiDocException
    {
        addNotary(not);
    }
    

    /** 
     * Verifies this confirmation
     * @param sdoc parent doc object
     * @return a possibly empty list of DigiDocException objects
     */
    public ArrayList verify(SignedDoc sdoc)
    {
        ArrayList errs = new ArrayList();
        // verify notary certs serial number using CompleteCertificateRefs        
        X509Certificate cert = getRespondersCertificate();
        if(m_logger.isDebugEnabled())
        	m_logger.debug("Responders cert: " + cert.getSerialNumber() + " - " + cert.getSubjectDN().getName() + 
            	           " complete cert refs nr: " + m_certRefs.getCertSerial() + " - " + m_certRefs.getCertIssuer());
        if(cert == null) {
        	errs.add(new DigiDocException(DigiDocException.ERR_RESPONDERS_CERT, 
                    "No notarys certificate!", null));
        	return errs;
        }
        if(cert != null && !cert.getSerialNumber().equals(m_certRefs.getCertSerial()) &&
        		!m_signature.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC)) {
            errs.add(new DigiDocException(DigiDocException.ERR_RESPONDERS_CERT, 
                "Wrong notarys certificate: " + cert.getSerialNumber() + " ref: " + m_certRefs.getCertSerial(), null));
        }
        // verify notary certs digest using CompleteCertificateRefs
        try {
        	if(!m_signature.getSignedDoc().getFormat().equals(SignedDoc.FORMAT_BDOC)) {
        	byte[] digest = SignedDoc.digestOfType(cert.getEncoded(), (m_signature.getSignedDoc().getFormat().
                	equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE));
        	if(m_logger.isDebugEnabled())
            	m_logger.debug("Not cert calc hash: " + Base64Util.encode(digest, 0) + 
            	" cert-ref hash: " + Base64Util.encode(m_certRefs.getCertDigestValue(), 0));
            if(!SignedDoc.compareDigests(digest, m_certRefs.getCertDigestValue())) {
                errs.add(new DigiDocException(DigiDocException.ERR_RESPONDERS_CERT, 
                "Notary certificates digest doesn't match!", null));
                m_logger.error("Notary certificates digest doesn't match!");
            }
        	}
        } catch(DigiDocException ex) {
            errs.add(ex);
        } catch(Exception ex) {
            errs.add(new DigiDocException(DigiDocException.ERR_RESPONDERS_CERT, 
                "Error calculating notary certificate digest!", null));
        }
        // verify notarys digest using CompleteRevocationRefs
        try {
        	for(int i = 0; i < countNotaries(); i++) {
        		Notary not = getNotaryById(i);
        		byte[] ocspData = not.getOcspResponseData();
        		if(m_logger.isDebugEnabled())
        			m_logger.debug("OCSP value: " + not.getId() + " data: " + ((ocspData != null) ? ocspData.length : 0) + " bytes");
        		if(ocspData == null || ocspData.length == 0) {
        			errs.add(new DigiDocException(DigiDocException.ERR_NOTARY_DIGEST, "OCSP value is empty!", null));
        			continue;
        		}
        		OcspRef orf = m_revRefs.getOcspRefByUri("#" + not.getId());
        		if(m_logger.isDebugEnabled())
        			m_logger.debug("OCSP ref: " + ((orf != null) ? orf.getUri() : "NULL"));
        		if(orf == null) {
        			errs.add(new DigiDocException(DigiDocException.ERR_NOTARY_DIGEST, "No OCSP ref for uri: #" + not.getId(), null));
        			continue;
        		}
        		byte[] digest1 = SignedDoc.digestOfType(ocspData, (m_signature.getSignedDoc().getFormat().
            	  equals(SignedDoc.FORMAT_BDOC) ? SignedDoc.SHA256_DIGEST_TYPE : SignedDoc.SHA1_DIGEST_TYPE));
                byte[] digest2 = orf.getDigestValue();
                if(m_logger.isDebugEnabled())
            	  m_logger.debug("Check ocsp: " + not.getId() + 
            	    " calc hash: " + Base64Util.encode(digest1, 0) + 
            	    " refs-hash: " + Base64Util.encode(digest2, 0));
               if(!SignedDoc.compareDigests(digest1, digest2)) {
                errs.add(new DigiDocException(DigiDocException.ERR_NOTARY_DIGEST, 
                "Notarys digest doesn't match!", null));
                m_logger.error("Notarys digest doesn't match!");
               }
        	}
        } catch(DigiDocException ex) {
            errs.add(ex);
        } 
        // verify notary status
        try {
            NotaryFactory notFac = ConfigManager.instance().getNotaryFactory();
            for(int i = 0; i < countNotaries(); i++) {
        	  Notary not = getNotaryById(i);
        	  if(m_logger.isDebugEnabled())
            	  m_logger.debug("Verify notray: " + not.getId() + " ocsp: " + 
            			  ((not.getOcspResponseData() != null) ? not.getOcspResponseData().length : 0) + 
            			  " responder: " + not.getResponderId());
              notFac.parseAndVerifyResponse(m_signature, not);
            }
        } catch(DigiDocException ex) {
            errs.add(ex);
        } 
        return errs;
    }
    
    
    /**
     * Helper method to validate the whole
     * UnsignedProperties object
     * @return a possibly empty list of DigiDocException objects
     */
    public ArrayList validate()
    {
        ArrayList errs = new ArrayList();
        DigiDocException ex = null;
        X509Certificate cert = getRespondersCertificate();
        if(cert == null) 
        	ex = validateRespondersCertificate(cert);
        if(ex != null)
            errs.add(ex);        
        ArrayList e = null;
        if(m_certRefs != null) {
            e = m_certRefs.validate();
            if(!e.isEmpty())
                errs.addAll(e);
        }
        if(m_revRefs != null) {
            e = m_revRefs.validate();
            if(!e.isEmpty())
                errs.addAll(e);
        }
        // notary ???
        
        return errs;
    }
    

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy