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

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

/*
 * Signature.java
 * PROJECT: JDigiDoc
 * DESCRIPTION: Digi Doc functions for creating
 *	and reading signed documents. 
 * AUTHOR:  Veiko Sinivee, Sunset Software OÜ
 *==================================================
 * 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.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import ee.sk.digidoc.factory.NotaryFactory;
import ee.sk.digidoc.factory.TimestampFactory;
import ee.sk.digidoc.factory.DigiDocFactory;
import ee.sk.digidoc.factory.DigiDocXmlGenFactory;
import ee.sk.digidoc.factory.DigiDocGenFactory;
import ee.sk.digidoc.factory.DigiDocVerifyFactory;
import ee.sk.utils.ConfigManager;

import java.security.cert.CertStore;
import java.security.cert.X509Certificate;
import ee.sk.utils.ConvertUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.log4j.Logger;
import org.bouncycastle.tsp.TSPAlgorithms;
import org.bouncycastle.tsp.TimeStampResponse;

/**
 * Models an XML-DSIG/ETSI Signature. A signature
 * can contain references SignedInfo (truly signed data)
 * and signed and unsigned properties.
 * @author  Veiko Sinivee
 * @version 1.0
 */
public class Signature implements Serializable
{
	private static final long serialVersionUID = 1L;
    /** reference to the parent SignedDoc object */
    private SignedDoc m_sigDoc;
    /** signature id */
    private String m_id;
    /** SignedInfo object */
    private SignedInfo m_signedInfo;
    /** SignatureValue object */
    private SignatureValue m_signatureValue;
    /** container comment (bdoc2 lib ver and name) */
    private String m_comment;
    /** KeyInfo object */
    private KeyInfo m_keyInfo;
    /** SignedProperties object */
    private SignedProperties m_sigProp;
    /** QualifyingProperties object */
    private QualifyingProperties m_qualProp;
    /** UnsignedProperties object */
    private UnsignedProperties m_unsigProp;
    /** original bytes read from XML file  */
    private byte[] m_origContent;
	/** CertID elements */
	private ArrayList m_certIds;    
    /** CertValue elements */
	private ArrayList m_certValues;
    /** TimestampInfo elements */
	private ArrayList m_timestamps;
	/** cached list of errors */
	private ArrayList m_errs;
	/** path in bdoc container */
	private String m_path;
	private boolean m_bAltDigMatch;
	/** signature profile - used in bdoc */
	private String m_profile, m_httpFrom;
	private static Logger m_logger = Logger.getLogger(Signature.class);
    
    /** 
     * Creates new Signature 
     */
    public Signature(SignedDoc sigDoc) {
        m_sigDoc = sigDoc;
        m_id = null;
        m_signedInfo = null;
        m_signatureValue = null;
        m_keyInfo = null;
        m_sigProp = null;
        m_unsigProp = null;
        m_origContent = null;
        m_certIds = null;
        m_certValues = null;
        m_timestamps = null;
        m_path = null;
        m_profile = null;
        m_errs = null;
        m_httpFrom = null;
        m_bAltDigMatch = false;
        m_comment = null;
    }
    
    /**
     * Accessor for sigDoc attribute
     * @return value of sigDoc attribute
     */
    public SignedDoc getSignedDoc() {
        return m_sigDoc;
    }
    
    /**
     * Mutator for sigDoc attribute
     * @param sigDoc new value for sigDoc attribute
     */    
    public void setSignedDoc(SignedDoc sigDoc) 
    {
        m_sigDoc = sigDoc;
    }
    
    /**
     * Accessor for id attribute
     * @return value of id attribute
     */
    public String getId() {
        return m_id;
    }
    
    /**
     * Mutator for id attribute
     * @param str new value for id attribute
     * @throws DigiDocException for validation errors
     */    
    public void setId(String str) 
        throws DigiDocException
    {
        DigiDocException ex = validateId(str);
        if(ex != null)
            throw ex;
        m_id = str;
    }
    
    /**
     * Accessor for origContent attribute
     * @return value of origContent attribute
     */
    public byte[] getOrigContent() {
        return m_origContent;
    }
    
    /**
     * Mutator for origContent attribute
     * @param str new value for origContent attribute
     */    
    public void setOrigContent(byte[] data) 
    {
        m_origContent = data;
    }
    
    /**
     * Helper method to validate an id
     * @param str input data
     * @return exception or null for ok
     */
    private DigiDocException validateId(String str)
    {
        DigiDocException ex = null;
        if(str == null)
            ex = new DigiDocException(DigiDocException.ERR_SIGNATURE_ID, 
                "Id is a required attribute", null);
        return ex;
    }
    
    /**
     * Accessor for signedInfo attribute
     * @return value of signedInfo attribute
     */
    public SignedInfo getSignedInfo() {
        return m_signedInfo;
    }
    
    /**
     * Mutator for signedInfo attribute
     * @param str new value for signedInfo attribute
     * @throws DigiDocException for validation errors
     */    
    public void setSignedInfo(SignedInfo si) 
        throws DigiDocException
    {
        //ArrayList errs = si.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_signedInfo = si;
    }

    /**
     * Checks if this signature uses EC key
     * @return true if EC signature
     */
    public boolean isEllipticCurveSiganture()
    {
    	return (m_signedInfo != null) && (m_signedInfo.getSignatureMethod() != null) && 
    			(m_signedInfo.getSignatureMethod().equals(SignedDoc.ECDSA_SHA1_SIGNATURE_METHOD) ||
    					m_signedInfo.getSignatureMethod().equals(SignedDoc.ECDSA_SHA224_SIGNATURE_METHOD) ||
    					m_signedInfo.getSignatureMethod().equals(SignedDoc.ECDSA_SHA256_SIGNATURE_METHOD) ||
    					m_signedInfo.getSignatureMethod().equals(SignedDoc.ECDSA_SHA384_SIGNATURE_METHOD) ||
    					m_signedInfo.getSignatureMethod().equals(SignedDoc.ECDSA_SHA512_SIGNATURE_METHOD));
    }
    
    /**
     * Returnes true if alternate digest matches instead of the real one
     * @return true if alternate digest matches instead of the real one
     * @deprecated alternate digest is still calculated but it is no longer optional check.
     * Error is allways egenrated if real digest doesn't match.
     */
    @Deprecated
    public boolean getAltDigestMatch() { return m_bAltDigMatch; }
    
    /**
     * Set flag to indicate that alternate digest matches instead of the real one
     * @param b flag to indicate that alternate digest matches instead of the real one
     */
    public void setAltDigestMatch(boolean b) { m_bAltDigMatch = b; }

    /**
     * Calculates the SignedInfo digest
     * @return SignedInfo digest
     */
    public byte[] calculateSignedInfoDigest()
        throws DigiDocException
    {
        return m_signedInfo.calculateDigest();
    }
    
    /**
     * Calculates the SignedInfo xml to sign
     * @return SignedInfo xml
     */
    public byte[] calculateSignedInfoXML()
        throws DigiDocException
    {
    	DigiDocXmlGenFactory genFac = new DigiDocXmlGenFactory(m_sigDoc);
        return genFac.signedInfoToXML(this, m_signedInfo);
    }
    
    /**
     * Returns HTTP_FROM value. This value is used
     * as a http header during ocsp requests. It must be
     * set before calling DigiDocGenFactory.finalizeSignature()
     * @return HTTP_FROM value
     */
    public String getHttpFrom() { return m_httpFrom; }
    
    /**
     * Sets HTTP_FROM value. This value is used
     * as a http header during ocsp requests. It must be
     * set before calling DigiDocGenFactory.finalizeSignature()
     * @param s HTTP_FROM value
     */
    public void setHttpFrom(String s) { m_httpFrom = s; }
    
    /**
     * Accessor for signatureValue attribute
     * @return value of signatureValue attribute
     */
    public SignatureValue getSignatureValue() {
        return m_signatureValue;
    }
    
    /**
     * Mutator for signatureValue attribute
     * @param str new value for signatureValue attribute
     * @throws DigiDocException for validation errors
     */    
    public void setSignatureValue(SignatureValue sv) 
        throws DigiDocException
    {
        //ArrayList errs = sv.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_signatureValue = sv;
        // VS: bug fix on 14.05.2008
        m_origContent = null;
    }
    
    /**
     * Creates a new SignatureValue object
     * of this signature
     * @param sigv signatures byte data
     * @throws DigiDocException for validation errors
     */    
    public void setSignatureValue(byte[] sigv) 
        throws DigiDocException
    {
        SignatureValue sv = new SignatureValue(this, sigv);
        setSignatureValue(sv);
    }
    
    /**
     * Accessor for keyInfo attribute
     * @return value of keyInfo attribute
     */
    public KeyInfo getKeyInfo() {
        return m_keyInfo;
    }
    
    /**
     * Mutator for keyInfo attribute
     * @param str new value for keyInfo attribute
     * @throws DigiDocException for validation errors
     */    
    public void setKeyInfo(KeyInfo ki) 
        throws DigiDocException
    {
        //ArrayList errs = ki.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_keyInfo = ki;
    }
    
    /**
     * Accessor for signedProperties attribute
     * @return value of signedProperties attribute
     */
    public SignedProperties getSignedProperties() {
        return m_sigProp;
    }
    
    /**
     * Mutator for signedProperties attribute
     * @param str new value for signedProperties attribute
     * @throws DigiDocException for validation errors
     */    
    public void setSignedProperties(SignedProperties sp) 
        throws DigiDocException
    {
        //ArrayList errs = sp.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_sigProp = sp;
    }
    
    /**
     * Accessor for unsignedProperties attribute
     * @return value of unsignedProperties attribute
     */
    public UnsignedProperties getUnsignedProperties() {
        return m_unsigProp;
    }
    
    /**
     * Mutator for unsignedProperties attribute
     * @param str new value for unsignedProperties attribute
     * @throws DigiDocException for validation errors
     */    
    public void setUnsignedProperties(UnsignedProperties usp) 
        throws DigiDocException
    {
        //ArrayList errs = usp.validate();
        //if(!errs.isEmpty())
        //    throw (DigiDocException)errs.get(0);
        m_unsigProp = usp;
    }
    
    /**
     * return the count of CertID objects
     * @return count of CertID objects
     */
    public int countCertIDs()
    {
        return ((m_certIds == null) ? 0 : m_certIds.size());
    }
    
    /**
     * Adds a new CertID object
     * @param cid new object to be added
     */
    public void addCertID(CertID cid)
    {
    	if(m_certIds == null)
    		m_certIds = new ArrayList();
    	cid.setSignature(this);
    	m_certIds.add(cid);
    }
    
    /**
     * Retrieves CertID element with the desired index
     * @param idx CertID index
     * @return CertID element or null if not found
     */
    public CertID getCertID(int idx)
    {
    	if(m_certIds != null && idx < m_certIds.size()) {
    		return (CertID)m_certIds.get(idx);
    	}
    	return null; // not found
    }
    
    /**
     * Retrieves the last CertID element
     * @return CertID element or null if not found
     */
    public CertID getLastCertId()
    {
    	if(m_certIds != null && m_certIds.size() > 0) {
    		return (CertID)m_certIds.get(m_certIds.size()-1);
    	}
    	return null; // not found
    }
    
    /**
     * Retrieves CertID element with the desired type
     * @param type CertID type
     * @return CertID element or null if not found
     */
    public CertID getCertIdOfType(int type)
    {
    	for(int i = 0; (m_certIds != null) && (i < m_certIds.size()); i++) {
    		CertID cid = (CertID)m_certIds.get(i);
    		if(cid.getType() == type)
    			return cid;
    	}
    	return null; // not found
    }
    
    /**
     * Retrieves CertID element with the desired type.
     * If not found creates a new one with this type.
     * @param type CertID type
     * @return CertID element
     * @throws DigiDocException for validation errors
     */
    public CertID getOrCreateCertIdOfType(int type)
    	throws DigiDocException
    {
    	CertID cid = getCertIdOfType(type);
    	if(cid == null) {
    		cid = new CertID();
    		cid.setType(type);
    		addCertID(cid);
    	}
    	return cid; // not found
    }
    
    /**
     * return the count of CertValue objects
     * @return count of CertValues objects
     */
    public int countCertValues()
    {
        return ((m_certValues == null) ? 0 : m_certValues.size());
    }
    
    /**
     * Adds a new CertValue object
     * @param cval new object to be added
     */
    public void addCertValue(CertValue cval)
    {
    	if(m_certValues == null)
    		m_certValues = new ArrayList();
    	cval.setSignature(this);
    	m_certValues.add(cval);
    }
    
    /**
     * Retrieves CertValue element with the desired index
     * @param idx CertValue index
     * @return CertValue element or null if not found
     */
    public CertValue getCertValue(int idx)
    {
    	if(m_certValues != null && idx < m_certValues.size()) {
    		return (CertValue)m_certValues.get(idx);
    	} else
    	return null; // not found
    }
    
    /**
     * Retrieves the last CertValue element 
     * @return CertValue element or null if not found
     */
    public CertValue getLastCertValue()
    {
    	if(m_certValues != null && m_certValues.size() > 0) {
    		return (CertValue)m_certValues.get(m_certValues.size()-1);
    	} else
    		return null; // not found
    }
    
    /**
     * Retrieves CertValue element with the desired type
     * @param type CertValue type
     * @return CertValue element or null if not found
     */
    public CertValue getCertValueOfType(int type)
    {
    	for(int i = 0; (m_certValues != null) && (i < m_certValues.size()); i++) {
    		CertValue cval = (CertValue)m_certValues.get(i);
    		if(cval.getType() == type)
    			return cval;
    	}
    	return null; // not found
    }
    
    /**
     * Retrieves CertValue element with the desired type.
     * If not found creates a new one with this type.
     * @param type CertValue type
     * @return CertValue element
     * @throws DigiDocException for validation errors
     */
    public CertValue getOrCreateCertValueOfType(int type)
    	throws DigiDocException
    {
    	CertValue cval = getCertValueOfType(type);
    	if(cval == null) {
    		cval = new CertValue();
    		cval.setType(type);
    		addCertValue(cval);
    	}
    	return cval; // not found
    }
    
    /**
     * Returns the first CertValue with the given serial
     * number that has been attached to this signature in
     * digidoc document. This could be either the signers 
     * cert, OCSP responders cert or one of the TSA certs.
     * @param serNo certificates serial number
     * @return found CertValue or null
     */
    public CertValue findCertValueWithSerial(BigInteger serNo)
    {
    	for(int i = 0; (m_certValues != null) && (i < m_certValues.size()); i++) {
    		CertValue cval = (CertValue)m_certValues.get(i);
    		if(cval.getCert().getSerialNumber().equals(serNo))
    			return cval;
    	}
    	return null;
    }
	
    /**
     * Retrieves OCSP respoinders certificate
     * @return OCSP respoinders certificate
     */
    public X509Certificate findResponderCert()
    {
    	CertValue cval = getCertValueOfType(CertValue.CERTVAL_TYPE_RESPONDER);
    	if(cval != null)
    		return cval.getCert();
    	else
    		return null;
    }
    
    /**
     * Retrieves TSA certificates
     * @return TSA certificates
     */
    public ArrayList findTSACerts()
    {
    	ArrayList vec = new ArrayList();
    	for(int i = 0; (m_certValues != null) && (i < m_certValues.size()); i++) {
    		CertValue cval = (CertValue)m_certValues.get(i);
    		if(cval.getType() == CertValue.CERTVAL_TYPE_TSA)
    			vec.add(cval.getCert());
    	}
    	return vec;
    }
    
    /**
     * return the count of TimestampInfo objects
     * @return count of TimestampInfo objects
     */
    public int countTimestampInfos()
    {
        return ((m_timestamps == null) ? 0 : m_timestamps.size());
    }
    
    /**
     * Adds a new TimestampInfo object
     * @param ts new object to be added
     */
    public void addTimestampInfo(TimestampInfo ts)
    {
    	if(m_timestamps == null)
    		m_timestamps = new ArrayList();
    	ts.setSignature(this);
    	m_timestamps.add(ts);
    }
    
    /**
     * Retrieves TimestampInfo element with the desired index
     * @param idx TimestampInfo index
     * @return TimestampInfo element or null if not found
     */
    public TimestampInfo getTimestampInfo(int idx)
    {
    	if(m_timestamps != null && idx < m_timestamps.size()) {
    		return (TimestampInfo)m_timestamps.get(idx);
    	} else
    		return null; // not found
    }
    
    /**
     * Retrieves the last TimestampInfo element 
     * @return TimestampInfo element or null if not found
     */
    public TimestampInfo getLastTimestampInfo()
    {
    	if(m_timestamps != null && m_timestamps.size() > 0) {
    		return (TimestampInfo)m_timestamps.get(m_timestamps.size()-1);
    	} else
    		return null; // not found
    }
    
    /**
     * Retrieves TimestampInfo element with the desired type
     * @param type TimestampInfo type
     * @return TimestampInfo element or null if not found
     */
    public TimestampInfo getTimestampInfoOfType(int type)
    {
    	for(int i = 0; (m_timestamps != null) && (i < m_timestamps.size()); i++) {
    		TimestampInfo ts = (TimestampInfo)m_timestamps.get(i);
    		if(ts.getType() == type)
    			return ts;
    	}
    	return null; // not found
    }
    
    /**
     * Retrieves TimestampInfo element with the desired type.
     * If not found creates a new one with this type.
     * @param type TimestampInfo type
     * @return TimestampInfo element
     * @throws DigiDocException for validation errors
     */
    public TimestampInfo getOrCreateTimestampInfoOfType(int type)
    	throws DigiDocException
    {
    	TimestampInfo ts = getTimestampInfoOfType(type);
    	if(ts == null) {
    		ts = new TimestampInfo();
    		ts.setType(type);
    		addTimestampInfo(ts);
    	}
    	return ts; // not found
    }
    
    /**
     * Accessor for path attribute
     * @return value of path attribute
     */
    public String getPath()
    {
    	return m_path;
    }
    
    /**
     * Mutator for path attribute
     * @param s new value for path attribute
     */
    public void setPath(String s)
    {
    	m_path = s;
    }
    
    /**
     * Accessor for profile attribute
     * @return value of profile attribute
     */
    public String getProfile()
    {
    	return m_profile;
    }
    
    /**
     * Mutator for profile attribute
     * @param s new value for profile attribute
     */
    public void setProfile(String s)
    {
    	m_profile = s;
    }
    
    /**
     * Accessor for comment attribute
     * @return value of comment attribute
     */
    public String getComment()
    {
    	return m_comment;
    }
    
    /**
     * Mutator for comment attribute
     * @param s new value for comment attribute
     */
    public void setComment(String s)
    {
    	m_comment = s;
    }
    
    /**
     * Gets confirmation and adds the corresponding
     * members that carry the returned info to
     * this signature
     * @throws DigiDocException for all errors
     */
    public void getConfirmation()
        throws DigiDocException
    {
    	if(m_sigDoc.getFormat().equals(SignedDoc.FORMAT_DIGIDOC_XML) ||
    			m_sigDoc.getFormat().equals(SignedDoc.FORMAT_SK_XML)) {
    		if(m_profile == null || m_profile.equalsIgnoreCase(SignedDoc.BDOC_PROFILE_TM)) {
    	  DigiDocGenFactory.finalizeXadesT(m_sigDoc, this);
    	  DigiDocGenFactory.finalizeXadesC(m_sigDoc, this);
    	  DigiDocGenFactory.finalizeXadesXL_TM(m_sigDoc, this);
    		}
    	} else {
    		String profile = m_profile;
    		if(profile == null)
    			profile = m_sigDoc.getProfile();
    		if(profile == null || profile.trim().length() == 0)
				profile = ConfigManager.instance().getStringProperty("DIGIDOC_DEFAULT_PROFILE", SignedDoc.BDOC_PROFILE_TM);
    		DigiDocGenFactory.finalizeSignature(m_sigDoc, this, m_signatureValue.getValue(), profile);
    	} 
        // reset original content since we just added to confirmation
        if(m_origContent != null) {
          DigiDocXmlGenFactory genFac = new DigiDocXmlGenFactory(m_sigDoc);
	      String str = new String(m_origContent);
	      int idx1 = str.indexOf("");
	      if(idx1 != -1) {
		  try {
		    ByteArrayOutputStream bos = new ByteArrayOutputStream();
		    bos.write(m_origContent, 0, idx1);
		    bos.write("".getBytes());
		    bos.write(genFac.unsignedPropertiesToXML(this, m_unsigProp));
		    bos.write("".getBytes());
		    m_origContent = bos.toByteArray();
		  } catch(java.io.IOException ex) {
		    DigiDocException.handleException(ex, DigiDocException.ERR_OCSP_GET_CONF);
		  }
	      }	    
        }
    }
    
    /**
     * Checks if this signature defines that if complies with bdoc 2.0 nonce
     * @return true if this signature defines bdoc 2.0 nonce policy compliance
     */
    public boolean hasBdoc2NoncePolicy()
    {
    	if(m_sigProp != null &&
    	   m_sigProp.getSignaturePolicyIdentifier() != null &&
    	   m_sigProp.getSignaturePolicyIdentifier().getSignaturePolicyId() != null &&
    	   m_sigProp.getSignaturePolicyIdentifier().getSignaturePolicyId().getSigPolicyId() != null &&
    	   m_sigProp.getSignaturePolicyIdentifier().getSignaturePolicyId().getSigPolicyId().getIdentifier() != null) {
    		Identifier id = m_sigProp.getSignaturePolicyIdentifier().getSignaturePolicyId().getSigPolicyId().getIdentifier();
    		if(id.getQualifier().equals(Identifier.OIDAsURN) &&
    		   id.getUri().equals(Identifier.BDOC_210_OID))
    		  return true;
    	}
    	return false;
    }
    
    /** 
     * Verifies and validates this signature. Returns a list of both
     * validation and verification errors.
     * @param lerrs list to be filled with DigiDocException objects
     * @return true if signature is ok
     */
    public boolean verify(SignedDoc sdoc, ArrayList lerrs)
    {
    	boolean bOk = true;
    	// validation
    	ArrayList lerrs1 = validate();
    	if(lerrs1 != null && lerrs1.size() > 0) {
    		bOk = false;
    		if(lerrs != null)
    			lerrs.addAll(lerrs1);
    	}
    	// verification
    	lerrs1 = new ArrayList();
    	boolean bOk1 = DigiDocVerifyFactory.verifySignature(sdoc, this, lerrs1);
    	if(!bOk1) bOk = false;
    	if(lerrs1 != null && lerrs1.size() > 0) {
    		bOk = false;
    		if(lerrs != null)
    			lerrs.addAll(lerrs1);
    	}
        return bOk;
    }
    
    /** 
     * Verifies this signature
     * @param sdoc parent doc object
     * @param checkDate Date on which to check the signature validity
     * @param demandConfirmation true if you demand OCSP confirmation from
     * every signature
     * @return a possibly empty list of DigiDocException objects
     */
    public ArrayList verify(SignedDoc sdoc, boolean checkDate, boolean demandConfirmation)
    {
    	Date do1 = null, dt1 = null, dt2 = null;
        ArrayList lerrs = new ArrayList();
        boolean bOk = DigiDocVerifyFactory.verifySignature(sdoc, this, lerrs);
        return lerrs;
    }


    /**
     * Helper method to validate the whole
     * Signature object
     * @return a possibly empty list of DigiDocException objects
     */
    public ArrayList validate()
    {
        ArrayList errs = new ArrayList();
        DigiDocException ex = validateId(m_id);
        if(ex != null)
            errs.add(ex);
        ArrayList e = null;
        if(m_signedInfo != null) {
        	e = m_signedInfo.validate();
        } else {
        	errs.add(new DigiDocException(DigiDocException.ERR_PARSE_XML, "Missing SignedInfo element", null));
        }
        if(e != null && !e.isEmpty())
            errs.addAll(e);
        if(m_signatureValue != null)
          e = m_signatureValue.validate();
        if(e != null && !e.isEmpty())
            errs.addAll(e);
        if(m_keyInfo != null) {
        	e = m_keyInfo.validate();
        } else {
        	errs.add(new DigiDocException(DigiDocException.ERR_PARSE_XML, "Missing KeyInfo element", null));
        }
        if(e != null && !e.isEmpty())
            errs.addAll(e);
        if(m_sigProp != null) {
          e = m_sigProp.validate();
          if(!e.isEmpty())
            errs.addAll(e);
        }
        if(m_unsigProp != null) {
            e = m_unsigProp.validate();
            if(!e.isEmpty())
                errs.addAll(e);
        }
        return errs;
    }
    

    /** returns QualifyingProperties object */
	public QualifyingProperties getQualifyingProperties() {
		return m_qualProp;
	}
	
	/** sets QualifyingProperties object */
	public void setQualifyingProperties(QualifyingProperties prop) {
		m_qualProp = prop;
	}
	
	/**
     * Accessor for signedInfo attribute
     * @return value of signedInfo attribute
     */
    public String getSubject() {
        return m_keyInfo.getSubjectFirstName() + " " + m_keyInfo.getSubjectLastName() + " " + m_keyInfo.getSubjectPersonalCode();
    }
    
    public ArrayList getErrors() { return m_errs; }
    public void setErrors(ArrayList l) { m_errs = l; }
    
    public String getStatus() {
    	if(m_errs == null || m_errs.size() == 0) {
    		if(m_signatureValue != null && m_signatureValue.getValue() != null)
    		   return "OK";
    		else
    			return "INCOMPLETE";
    	} else
    		return "ERROR";
    }
    
    /**
     * Retrieves the signature production timestamp from first ocsp response
     * @return ocsp response produced-at time if exists
     */
    public Date getSignatureProducedAtTime()
    {
    	if(m_unsigProp != null) {
    		Notary not = m_unsigProp.getNotary();
    		if(not != null)
    			return not.getProducedAt();
    	}
    	return null;
    }
    
    /**
     * Converts Signature object to String representation 
     * mainly for debugging purposes
     */
    public String toString()
    {
    	try {
    		DigiDocXmlGenFactory genFac = new DigiDocXmlGenFactory(m_sigDoc);
    		return new String(genFac.signatureToXML(this), "UTF-8");
    	} catch(Exception ex) {
    		m_logger.error("Error converting Signature to string: " + ex);
    	}
    	return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy