/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. * * $Id: SignatureObject.java,v 1.7 2006/10/31 08:18:56 wprinz Exp $ */ package at.knowcenter.wag.egov.egiz.sig; import iaik.asn1.structures.Name; import iaik.asn1.structures.RDN; import iaik.utils.RFC2253NameParser; import iaik.utils.RFC2253NameParserException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import java.util.Vector; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException; import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIException; import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIFactory; import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter; import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper; import at.knowcenter.wag.egov.egiz.table.Entry; import at.knowcenter.wag.egov.egiz.table.Style; import at.knowcenter.wag.egov.egiz.table.Table; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; import at.knowcenter.wag.egov.egiz.tools.Normalizer; /** * This class represents the abstract signature object. It contains all methods * reading the definitions from the settings file, analyse them and build the * abstract signature table.
* All values that build or used by the signation creation process, call the * external services, can read or set separately. All other values are defined * in the settings file. * * @author wlackner * @author modified by Thomas Knall */ public class SignatureObject implements Serializable { // 03.11.2010 changed by exthex - added default for defaultValueStyle_.hAlign since we had to remove the hardcoded default in Style // 04.11.2010 changed by exthex - setSigValue no longer removes multiple newlines from value /** * SVUID. */ private static final long serialVersionUID = -3535189232362254713L; /** * The system file separator char */ private static final String FILE_SEP = System.getProperty("file.separator"); /** * The certificate extension */ private static final String CERT_FILE_EXTENSION = ".der"; /** * certificate import dir */ private static final String CERT_ADD_DIR = "tobeadded"; /** * The default style definition for images. */ private Style defaultImageStyle_ = new Style(); /** * The default style definition for captions. */ private Style defaultCaptionStyle_ = new Style(); /** * The default style definition for values. */ private Style defaultValueStyle_ = new Style(); /** * Standard key get/set the signature meta informations */ public static final String SIG_META = "SIG_META"; /** * Standard key get/set the certification value */ public static final String SIG_CER = "SIG_CER"; /** * Standard key get/set the certification digest value */ public static final String SIG_CER_DIG = "SIG_CER_DIG"; private X509Cert x509Cert_ = null; private String timeStamp = null; // public static final String SIG_RES = "SIG_RES"; // dummy value for debugging only private String sigResponse_ = null; /** * The logger definition. */ private static final Logger logger_ = ConfigLogger.getLogger(SignatureObject.class); /** * The normalizer reference */ private Normalizer normalizer_ = null; /** * The settings reader reference */ private SettingsReader settings_ = null; // /** // * The reference to the settings property tree // */ // private PropertyTree pTree_ = null; /** * The current signature type used reading and analysing the property tree */ private String sigType_ = null; /** * Reference from signature key to there corresponding value */ private Hashtable sigEntries_ = new Hashtable(8); /** * The abstract table representation */ private Table sigTable_ = null; // private HashMap sigIndexMap_ = new HashMap(); /** * Path value storing and fetching the certificates */ private String certPath_ = null; /** * the signature definition object */ private SignatureTypeDefinition signatureDefinition_ = null; /** * The raw xml response from the connector that was used to set the values in * this SignatureObject. * *

* This is set by the Connector so that signing Applications can use the * returned XML values. *

*/ protected String raw_signature_response = null; /** * Filters the issuer name in order to find matches. * @author tknall * @see #normalizeIssuer */ private LDAPIssuerNameFilter issuerNameFilter = new LDAPIssuerNameFilter() { public Name applyFilter(Name name) { RFC2253NameParser parser = new RFC2253NameParser(normalizeIssuer(name.getName())); try { name = parser.parse(); } catch (RFC2253NameParserException e) { logger_.error(e.getMessage(), e); } return name; } }; /** * The empty constructor. It initilize the normlizer, load the settings and * set the default styles. * * @throws SignatureException * ErrorCode:101, 400 */ public SignatureObject() throws SignatureException { initNormalizer(); loadSettings(); setDefaultStyles(); } /** * This method initialize the normalizer * * @throws SignatureException * ErrorCode:400 */ private void initNormalizer() throws SignatureException { try { normalizer_ = new Normalizer(); } catch (NormalizeException e) { SignatureException se = new SignatureException(400, "Normalizer can not be initialized", e); throw se; } } /** * This method load the signature definitions * * @throws SignatureException * ErrorCode:101 */ private void loadSettings() throws SignatureException { if (settings_ == null) { try { settings_ = SettingsReader.getInstance(); } catch (SettingsException e) { String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage(); logger_.error(log_message); throw new SignatureException(101, log_message, e); } } // pTree_ = settings_.getPTree(); certPath_ = SettingsReader.CERT_PATH; } /** * This method set the default styles for images, captions and values. */ private void setDefaultStyles() { defaultImageStyle_.setPadding(3); defaultImageStyle_.setHAlign(Style.CENTER); defaultImageStyle_.setVAlign(Style.MIDDLE); defaultCaptionStyle_.setHAlign(Style.CENTER); defaultCaptionStyle_.setVAlign(Style.MIDDLE); defaultValueStyle_.setHAlign(Style.LEFT); defaultValueStyle_.setVAlign(Style.MIDDLE); } /** * Dummy getter Method for debugging only * * @return response string */ public String getSigResponse() { return sigResponse_; } /** * Dummy setter Method for debugging only * * @param sigRespone * store the response string */ public void setSigResponse(String sigRespone) { sigResponse_ = sigRespone; } /** * This method set the signature type. * * @param sigType * the signature type to be set * @throws SignatureTypesException */ public void setSigType(String sigType) throws SignatureTypesException { SignatureTypes sig_types = SignatureTypes.getInstance(); signatureDefinition_ = sig_types.getSignatureTypeDefinition(sigType_); sigType_ = sigType; } /** * Returns the default signation type * * @return the key for the default signature definition, if the key is not * found it returns null */ private String getDefaultSigType() { return settings_.getSetting(SignatureTypes.DEFAULT_TYPE, null); } /** * This method checks if a given signature key is realy a defined signature * key. * * @param sigKey * the key to check * @return true if the key is correct, false if the given key is not defined */ public boolean isSigKey(String sigKey) { return signatureDefinition_.contains(sigKey); } /** * This method adds an sig value to the entry cache. If a key is not in * the cache a new signature entry is created. Therefore the method return * true.
* The value that has to be set would be normalized!
* If the key equals to SIG_VALUE all whitespaces are * removed!
* * @param key * the key to be set * @param value * the value to be set * @return true if a new signature value is created, * false otherwise */ public boolean setSigValue(String key, String value) { return setSigValue(key, value, false); } public boolean setSigValue(String key, String value, boolean placeholder) { SignatureEntry sig_entry = null; boolean is_new = false; if (sigEntries_.containsKey(key)) { sig_entry = (SignatureEntry) sigEntries_.get(key); } else { sig_entry = new SignatureEntry(key); sigEntries_.put(key, sig_entry); is_new = true; } value = normalizer_.normalize(value, true); if (SignatureTypes.SIG_VALUE.equals(key) || SignatureTypes.SIG_ID.equals(key) || SignatureTypes.SIG_NUMBER.equals(key)) { value = removeAllWhiteSpaces(value); } sig_entry.setValue(value); sig_entry.isPlaceholder = placeholder; return is_new; } public boolean setValueBruteForce(String key, String value) { SignatureEntry sig_entry = null; boolean is_new = false; if (sigEntries_.containsKey(key)) { sig_entry = (SignatureEntry) sigEntries_.get(key); } else { sig_entry = new SignatureEntry(key); sigEntries_.put(key, sig_entry); is_new = true; } sig_entry.setValue(value); return is_new; } /** * Set the value and the caption to given key. * * @param key * the key of the signature object * @param value * the value of the given key * @param caption * the caption of the given key */ public void setSigValueCaption(String key, String value, String caption) { setSigValue(key, value); SignatureEntry sig_entry = (SignatureEntry) sigEntries_.get(key); sig_entry.setCaption(caption); } /** * This method returns a value for a given signature key. If the key equals to * SIG_NORM and the value is null the version * string of the current normalizer is returned! * * @param key * the key to get the value for * @return a value for the given key */ public String getSigValue(String key) { String value = null; SignatureEntry sigEntry = null; if (sigEntries_.containsKey(key)) { sigEntry = (SignatureEntry) sigEntries_.get(key); value = sigEntry.getValue(); } if (value == null && SignatureTypes.SIG_NORM.equals(key)) { value = normalizer_.getVersion(); } String overrideVal = OverridePropertyHolder.getProperty(key); if (value != null && sigEntry != null && !sigEntry.isPlaceholder && overrideVal != null) { // TODO this!! SignatureEntry.isPlaceholder value = overrideVal; if (logger_.isDebugEnabled()) { logger_.debug("Using override property for key '" + key + "' = " + value); } } return value; } /** * Sets the "Kennzeichnung". * * @param kz * The "Kennzeichnung" to be set. */ public void setKZ(PdfASID kz) { setSigValue(SignatureTypes.SIG_KZ, kz.toString()); } /** * Returns the "Kennzeichnung" of this signature. * * @return Returns the "Kennzeichnung" of this signature. Returns null if * there is no "Kennzeichnung" or it is not recognized by this * application. */ public PdfASID getKZ() throws InvalidIDException { String kz_string = getSigValue(SignatureTypes.SIG_KZ); if (kz_string == null) { return null; } PdfASID kz = null; try { kz = new PdfASID(kz_string); } catch (InvalidIDException e) { logger_.error(e.getMessage(), e); } return kz; } /** * This method returns a caption for a given signature key. If the key exists * and the coresponding value is null the key itself is * returned as caption! If the key does not exist the method returns * null. * * @param key * the key to get the caption for * @return a caption for the given key */ private String getSigCaption(String key) { String caption = null; if (sigEntries_.containsKey(key)) { caption = ((SignatureEntry) sigEntries_.get(key)).getCaption(); if (caption == null) { caption = key; } } return caption; } /** * @return Returns the SignationType. */ public String getSignationType() { if (sigType_ == null) { sigType_ = getDefaultSigType(); } return sigType_; } /** * @return Returns the SignationDate. */ public String getSignationDate() { return getSigValue(SignatureTypes.SIG_DATE); } /** * @param sigDate * The SignationDate to set. */ public void setSignationDate(String sigDate) { setSigValue(SignatureTypes.SIG_DATE, sigDate); } /** * @return Returns the SignationName. */ public String getSignationName() { return getSigValue(SignatureTypes.SIG_NAME); } /** * @param sigName * The SignationName to set. */ public void setSignationName(String sigName) { setSigValue(SignatureTypes.SIG_NAME, sigName); } /** * @return Returns the SignationNormVersion. */ public String getSignationNormVersion() { return getSigValue(SignatureTypes.SIG_NORM); } /** * @param sigNormVersion * The SignationNormVersion to set. */ public void setSignationNormVersion(String sigNormVersion) { setSigValue(SignatureTypes.SIG_NORM, sigNormVersion); } /** * This method removes whitespaces around RDNs. Whitespaces may be assumed by the algorithm that * re-merges multiple lines from a binary signature when line breaks occur after commas. Without * correction this will result in broken signatures.
* e.g this * invalid IssuerName (note the space before the second RND CN): * serialNumber=863532247989, CN=BMUKK - Amtssignatur Schulen,OU=Abt. IT/2,O=Bundesministerium für Unterricht, Kunst und Kultur,C=AT * will be normalized to: * serialNumber=863532247989,CN=BMUKK - Amtssignatur Schulen,OU=Abt. IT/2,O=Bundesministerium für Unterricht, Kunst und Kultur,C=AT * @param The invalid RFC2253 name as string. * @return The normalized RFC2253 name without spaces prior to RDNs. */ public static String prepareRFC2253Name(String name) { if (name == null) { return null; } StringTokenizer tokenizer = new StringTokenizer(name, ",", false); StringBuffer result = new StringBuffer(); // iterate over all alleged RND=value-pairs while (tokenizer.hasMoreTokens()) { String rdnExpression = tokenizer.nextToken(); try { // try to parse RDN=value new RFC2253NameParser(rdnExpression.trim()).parse(); // rdnExpression is a RDN=value pair -> remove whitespaces before and after RDN=value rdnExpression = rdnExpression.trim(); } catch (RFC2253NameParserException e) { // this is not a RDN=value pair // e.g. " Kunst und Kultur" from the javadoc example // do not trim, otherwise resulting RFC2253Name will be invalid } // re-insert delimiter if (result.length() > 0) { result.append(","); } // add token (either trimmed RND=value pair, or not trimmed text token) result.append(rdnExpression); } String cleanedName = result.toString(); if (logger_.isDebugEnabled()) { logger_.debug("Cleaning RFC2253 name: \"" + name + "\" -> \"" + cleanedName + "\"."); } return cleanedName; } /** * This method depicts a workaround for a bug with RFC2253 names with RDNs that have not been * resolved from ObjectID at signing time (this results from a BKU that could not resolve * the respective OID).
* e.g. 2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE
* The example above shows a RDN "2.5.4.5" which should have been resolved to "serialNumber" at * signing time. We also recognize that the name shows spaces prior to RDNs and that the space * which between "Foreigner" and "CA" is missing due to text extraction/reconstruction. * The naive approach would be to take the complete RFC2253 name from the certificate, since that * name has also been used for signature. But this does not work in some cases because while * the bku was not able to resolve 2.5.4.5 on signing time, the entity invoking pdfas for * verification might be, so that taking the name from certificate on verification time, may not * result in the name we had at signing time.
* e.g. at signing time: 2.5.4.5=#1306323030383034,CN=Foreigner CA,C=BE
* after text extraction: 2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE
* from certificate: serialNumber=863532247989,CN=Foreigner CA,C=BE
* This method provides a workaround for that problem, by merging information from text extraction * with information from the certificate. The method takes all RDNs from the extracted text and * merges them with the values from the certificate (considering the case where the textual * version shows BER encoded values (e.g. #1306323030383034). * @param nameFromText The extracted RFC2253 name from the text (e.g. 2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE). * @param nameFromCertificate The RFC2253 name from the certificate (e.g. serialNumber=863532247989,CN=Foreigner CA,C=BE) * @return The RFC2253 name that was used for signature (e.g. 2.5.4.5=#1306323030383034,CN=Foreigner CA,C=BE). */ public static String prepareRFC2253Name(String nameFromText, String nameFromCertificate) { // do not invoke the workaround for performance reasons when both the extracted name and the // name from certificate are equal if (StringUtils.equals(nameFromText, nameFromCertificate)) { return nameFromText; } logger_.debug("Checking RFC2253 name."); // if we do not have a name from certificate just return the name from text if (nameFromCertificate == null) { logger_.debug("No certificate RFC2253 name provided. Applying less sophisticated workaround (does not cover all cases) without certificate usage."); return prepareRFC2253Name(nameFromText); } // no name from text extraction available, just return name from certificate if (nameFromText == null) { logger_.debug("No extracted/reconstructed name available. Just returning the name from certificate: \"" + nameFromCertificate + "\"."); return nameFromCertificate; } // helper class final class RDNValuePair { private String rdn; private String value; public RDNValuePair(String rdn, String value) { this.rdn = rdn; this.value = value; } public String getRdn() { return this.rdn; } public String getValue() { return this.value; } public String toString() { return rdn + "=" + value; } } // retrieve RDNs from text based name List rdnList = new ArrayList(); StringTokenizer tokenizer = new StringTokenizer(nameFromText, ",", false); while (tokenizer.hasMoreTokens()) { String rdnExpression = tokenizer.nextToken().trim(); try { new RFC2253NameParser(rdnExpression).parse(); // token is RDN=value pair // split RDN from value String[] split = rdnExpression.split("=", 2); rdnList.add(new RDNValuePair(split[0].trim(), split[1].trim())); } catch (RFC2253NameParserException e) { // no RDN in token } } // get values from certificate name Name nCert; try { nCert = new RFC2253NameParser(nameFromCertificate).parse(); } catch (RFC2253NameParserException e) { // should never happen logger_.warn("Unable to parse RFC2253 name \"" + nameFromCertificate + "\". Applying less sophisticated workaround (does not cover all cases) without certificate usage."); return prepareRFC2253Name(nameFromText); } RDN[] values = nCert.getRDNs(); // check if results are mergeable if (values.length != rdnList.size()) { // unable to merge names; returning nameFromCertificate (since this should be normal // behavior) logger_.warn("Number of parsed text based RDNs from \"" + nameFromText + "\" does not fit the number of RDN values from certificate name \"" + nameFromCertificate + "\". Returning name from certificate."); return nameFromCertificate; } // merge textual based RDNs with values from certificate StringBuffer result = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) { result.append(","); } // take rdn from textual representation RDNValuePair rdnVP = (RDNValuePair) rdnList.get(i); // Note: Do not take RDN from extraction but from certificate // (Bug-Fix for EMAIL/EMAILADDRESS problem in ZID documents) // take value from certificate but make sure that we do not have a // BER encoding if (rdnVP.getValue().startsWith("#")) { // take rdn from textual representation result.append(rdnVP.getRdn()).append("="); // BER encoding -> take value from text representation result.append(rdnVP.getValue()); } else { // no BER encoding -> take value from certificate // also take RDN from certificate if possible String certValue = values[values.length - 1 - i].getAVA() .getValueAsString(); String rdn = resolveRDN(nameFromCertificate, certValue, rdnVP.getRdn()); result.append(rdn + "=").append(certValue); } } String merged = result.toString(); if (logger_.isDebugEnabled()) { if (merged.equals(nameFromText)) { logger_.debug("Taking name from text: \"" + nameFromText + "\""); } else if (merged.equals(nameFromCertificate)) { logger_.debug("Taking name from certificate: \"" + nameFromText + "\""); } else { logger_.debug("Name has been fixed."); logger_.debug("Name from text : \"" + nameFromText + "\""); logger_.debug("Name from certificate : \"" + nameFromCertificate + "\""); logger_.debug("Fixed name : \"" + merged + "\""); } } return merged; } /** * This method tries to resolve the RDN corresponding to a given value from the certificate String. * As values might occur multiple times for different RDNs, an unambiguous resolving cannot be assured. * In case of ambiguity, the RDN extracted from text is returned by default. * * This method is a bug fix for a problem that caused the verification of ZID documents to fail as the RDN * from the extracted text ("EMAILADDRESS") was different to the RDN in the certificate ("EMAIL") * * @param certString * The String obtained from the certificate * @param value * The RDN's value * @param extractedRDN * The RDN extracted from the given text * @return * The resolved RDN from the certificate, or the RDN from text extraction */ private static String resolveRDN(String certString, String value, String extractedRDN) { if (!certString.contains(value)) { // given value cannot be found in certificate string return extractedRDN; } if (certString.indexOf(value) != certString.lastIndexOf(value)) { // given value is ambiguous - cannot resolve RDN from certificate string return extractedRDN; } String[] parts = certString.split(",|;"); String val = value.trim(); for (int i = 0; i < parts.length; i++) { String part = parts[i].trim(); if (part.endsWith(val)) { // found entry - extract RDN String[] components = part.split("="); if (components.length != 2) { // unexpected format - return default return extractedRDN; } String rdn = components[0].trim(); return rdn; } } // default return extractedRDN; } /** * @return Returns the SignationIssuer. */ public String getSignationIssuer() { String issuer = getSigValue(SignatureTypes.SIG_ISSUER); X509Cert cert = loadCertificate(getSigValue(SignatureTypes.SIG_NUMBER), issuer); if (cert != null) { // merge RDNs from file with values from certificate if (getSigValue(SignatureTypes.SIG_ISSUER) != null) { this.setSignationIssuer(prepareRFC2253Name(getSigValue(SignatureTypes.SIG_ISSUER), cert.getIssuerName())); } else { this.setSignationIssuer(cert.getIssuerName()); } /* if (getSigValue(SignatureTypes.SIG_ISSUER) == null) { this.setSignationIssuer(cert.getIssuerName()); } */ setSigValue(SIG_CER, cert.getCertString()); // setSigValue(SIG_CER_DIG, cert.getCertDigest()); x509Cert_ = cert; } issuer = getSigValue(SignatureTypes.SIG_ISSUER); return issuer; } /** * @param sigIssuer * The SignationIssuer to set. */ public void setSignationIssuer(String sigIssuer) { setSigValue(SignatureTypes.SIG_ISSUER, sigIssuer); } /** * @return Returns the SignationValue. */ public String getSignationValue() { return getSigValue(SignatureTypes.SIG_VALUE); } /** * @param sigValue * The SignationValue to set. */ public void setSignationValue(String sigValue) { setSigValue(SignatureTypes.SIG_VALUE, sigValue); } /** * @return the reference to the signature label */ public String getOfficialSeal() { return getSigValue(SignatureTypes.SIG_LABEL); } /** * @param serialNumber * The serial number of the signature to set */ public void setSignationSerialNumber(String serialNumber) { setSigValue(SignatureTypes.SIG_NUMBER, serialNumber); } /** * @return sigNumber the serial number of the signature */ public String getSignationSerialNumber() { return getSigValue(SignatureTypes.SIG_NUMBER); } // dferbas baik /** * signature algorithm if embedded * @param sigAlg */ public void setSigAlg(String sigAlg) { setSigValue(SignatureTypes.SIG_ALG, sigAlg); } /** * signature algorithm if embedded * @return */ public String getSigAlg() { return getSigValue(SignatureTypes.SIG_ALG); } /** * @param certDigest * set the digest value for the X509Certificate */ public void setX509CertificateDigest(String certDigest) { setSigValue(SIG_CER_DIG, certDigest); } /** * This method load the current certificate getting the current SerialNumber * and the current SignationIssuer.
* It stores back the SignationIssuer, X509Certificate and * X509CertificateDigest */ private void loadCurrentCert() { X509Cert cert = loadCertificate(getSignationSerialNumber(), getSignationIssuer()); if (cert != null) { // merge RDNs from file with values from certificate if (getSigValue(SignatureTypes.SIG_ISSUER) != null) { this.setSignationIssuer(prepareRFC2253Name(getSigValue(SignatureTypes.SIG_ISSUER), cert.getIssuerName())); } else { this.setSignationIssuer(cert.getIssuerName()); } /* if (getSigValue(SignatureTypes.SIG_ISSUER) == null) { this.setSignationIssuer(cert.getIssuerName()); } */ setSigValue(SIG_CER, cert.getCertString()); // setSigValue(SIG_CER_DIG, cert.getCertDigest()); x509Cert_ = cert; } } /** * @return the current X509CertificateDigest value (as SHA1 digest). */ public String getX509CertificateDigest() { String dig = getSigValue(SIG_CER_DIG); if (dig == null) { loadCurrentCert(); byte[] cert_b64 = CodingHelper.decodeBase64(x509Cert_.getCertString()); byte[] cert_hash = CodingHelper.buildDigest(cert_b64, "SHA"); dig = new String(CodingHelper.encodeBase64(cert_hash)); setSigValue(SIG_CER_DIG, dig); } return dig; } /** * @return the current X509v3 certificate string */ public String getX509CertificateString() { String cert = getSigValue(SIG_CER); if (cert == null) { loadCurrentCert(); cert = getSigValue(SIG_CER); } return cert; } /** * @param x509Certificate * The X509v3 certificate of the signature to set */ public void setX509Certificate(String x509Certificate) { setSigValue(SIG_CER, x509Certificate); storeCertificate(getSignationSerialNumber(), getSignationIssuer(), x509Certificate); } public void setX509Certificate(X509Certificate cert) { try { // byte [] der = cert.getEncoded(); // String certStr = CodingHelper.encodeBase64(der); // setX509Certificate(certStr); X509Cert knowcenterCert = X509Cert.initByX509Certificate(cert); setSigValue(SIG_CER, knowcenterCert.getCertString()); storeCertificate(cert.getSerialNumber().toString(), knowcenterCert.getIssuerName(), knowcenterCert.getCertString()); } catch (CertificateEncodingException e) { logger_.error(e.getMessage(), e); } } /** * return the 509v3 certificate of the given serialNumber and the given issuer * string * * @param serialNumber * the serialNumber which the certificates should load * @param issuer * the issuer which the certificates should load * @return the X509v3 certificate string */ public String getX509CertificateString(String serialNumber, String issuer) { X509Cert cert = loadCertificate(serialNumber, issuer); if (cert != null) { return cert.getCertString(); } return null; } public X509Cert getX509Cert(String serialNumber, String issuer) { return loadCertificate(serialNumber, issuer); } public X509Cert getX509Cert() { if (x509Cert_ == null) { loadCurrentCert(); } return x509Cert_; } /** * Set the signation id's build by a BKU signated SignatureObject. * * @param sigIds * the string to store. */ public void setSignationIDs(String sigIds) { if (sigIds != null) { setSigValue(SignatureTypes.SIG_ID, sigIds); } } // /** // * Set the signation id's build by a BKU signated SignatureObject. // * // * @param sigIds // * The sination id's are defined into five parts, that have the same // * base as prefix. Therefore the ids's are reduced by the base prefix // * and stored in the SignatureObject. // */ // public void setSignationIDs(String[] sigIds) // { // String join = ""; // String base = null; // for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++) // { // String id = sigIds[arr_idx]; // if (logger_.isDebugEnabled()) // { // logger_.debug("Set BKU id:" + id); // } // int id_idx = id.lastIndexOf("-"); // if (arr_idx == 0) // { // base = id.substring(0, id_idx); // } // String cur_id = id.substring(id_idx + 1); // join += "-" + cur_id; // } // setSignationIDs(base + "@" + join.substring(1)); // } // TODO hotfix public static String formatSigIds(Properties response_properties, String[] sigIds) throws SignatureException { // ids algorithm: String join = ""; String base = null; for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++) { String id = sigIds[arr_idx]; if (logger_.isDebugEnabled()) { logger_.debug("Set BKU id:" + id); } int id_idx = id.lastIndexOf("-"); if (arr_idx == 0) { base = id.substring(0, id_idx); } String cur_id = id.substring(id_idx + 1); join += "-" + cur_id; } // setSignationIDs(base + "@" + join.substring(1)); String ids = base + "@" + join.substring(1); // :ids algorithm String productName = response_properties.getProperty("productName"); logger_.debug("productName = " + productName); // if (!productName.equals("trustDeskbasic")) // modified by tknall if (!productName.startsWith("trustDeskbasic")) { final String msg = "The BKU environment " + productName + " is not trustDeskbasic and therefore the productVersion cannot be decided."; logger_.error(msg); // uncomment the following line in order to check new bkus throw new SignatureException(0, msg); } String productVersion = response_properties.getProperty("productVersion"); logger_.debug("productVersion = " + productVersion); boolean new_etsi = decideNewEtsiByBKUVersion(productVersion); logger_.debug("verwende neue etsi properties = " + new_etsi); String etsi_prefix = ""; if (new_etsi) { // TODO hotfix etsi_prefix = "etsi-bka-1.0@"; } String final_ids = etsi_prefix + ids; logger_.debug("final_ids = " + final_ids); return final_ids; } // TODO hotfix public static boolean decideNewEtsiByBKUVersion(String productVersion) { boolean new_etsi = true; // TODO hotfix if (productVersion.startsWith("2.5") || productVersion.startsWith("2.4") || productVersion.startsWith("2.3") || productVersion.startsWith("2.2") || productVersion.startsWith("2.1") || productVersion.startsWith("1") || productVersion.startsWith("0")) { new_etsi = false; } return new_etsi; } /** * Checks if the current SignatureObject is siganted by MOA. It checks if the * current SignatureObject has a signation id value. * * @return true if no signation id value is found, false otherwise */ public boolean isMOASigned() { try { PdfASID sig_kz = getKZ(); String sig_id = getSignationIds(); return SigKZIDHelper.isMOASigned(sig_kz, sig_id); //return getSignationIds() == null; } catch (InvalidIDException e) { logger_.error(e.getMessage(), e); return false; } } /** * Tells if this SignatureObject is textual. * * @return Returns true, if it is textual. */ public boolean isTextual() { PdfASID kz = null; try { kz = getKZ(); } catch (InvalidIDException e) { logger_.error(e.getMessage(), e); } return SigKZIDHelper.isTextual(kz); } /** * Tells, if this SignatureObject is binary. * * @return Returns true, if it is binary. */ public boolean isBinary() { PdfASID kz = null; try { kz = getKZ(); } catch (InvalidIDException e) { logger_.error(e.getMessage(), e); } return SigKZIDHelper.isBinary(kz); } /** * Takes the signation id value of the current SignatureObject and split them * into the corresponding id array added with the id-base. * * @return the id array */ // TODO hotifx public String getSignationIds() { String sig_ids = getSigValue(SignatureTypes.SIG_ID); return sig_ids; // if (sig_ids == null || sig_ids.length() == 0) // { // return null; // } // // // int index = sig_ids.indexOf(PdfAS.IDS); // // if (index < 0) // // { // // return null; // // } // // sig_ids = sig_ids.substring(index + PdfAS.IDS.length()); // // // // if (sig_ids == null || sig_ids.length() == 0) // // { // // return null; // // } // // String[] ids_str = sig_ids.split("@"); // String base = ids_str[0]; // String[] ids = ids_str[1].split("-"); // String[] real_ids = new String[5]; // real_ids[0] = base + "-" + ids[0]; // real_ids[1] = "0-" + base + "-" + ids[1]; // real_ids[2] = "0-" + base + "-" + ids[2]; // real_ids[3] = "0-" + base + "-" + ids[3]; // real_ids[4] = "0-" + base + "-" + ids[4]; // if (logger_.isDebugEnabled()) // { // for (int id_idx = 0; id_idx < real_ids.length; id_idx++) // { // logger_.debug("Set BKU id:" + real_ids[id_idx]); // } // } // return real_ids; } // TODO hotfix public static String[] parseSigIds(String sig_ids) { if (sig_ids == null || sig_ids.length() == 0) { return null; } // int index = sig_ids.indexOf(PdfAS.IDS); // if (index < 0) // { // return null; // } // sig_ids = sig_ids.substring(index + PdfAS.IDS.length()); // // if (sig_ids == null || sig_ids.length() == 0) // { // return null; // } String[] ids_str = sig_ids.split("@"); String etsi_string = null; if (ids_str.length == 3) { etsi_string = ids_str[0]; String[] rest_ids = new String[] { ids_str[1], ids_str[2] }; ids_str = rest_ids; } String base = ids_str[0]; String[] ids = ids_str[1].split("-"); String[] real_ids = new String[6]; // the last one contains the etsi string real_ids[0] = base + "-" + ids[0]; real_ids[1] = "0-" + base + "-" + ids[1]; real_ids[2] = "0-" + base + "-" + ids[2]; real_ids[3] = "0-" + base + "-" + ids[3]; real_ids[4] = "0-" + base + "-" + ids[4]; real_ids[5] = etsi_string; if (logger_.isDebugEnabled()) { for (int id_idx = 0; id_idx < real_ids.length; id_idx++) { logger_.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]); } } return real_ids; } /** * This method normalizes the issuer string to support unique issuer string * for equition. Used to store and find corresponting certificates. * Normalzing: normalizing the string using the normalizer, remove all white * spaces, encode as base64 and replace all "/" chars with "_". * * @param issuer * the issuer string to normalize * @return the normalized issuer string * @author modified by tknall */ private String getIssuerFileHash(String issuer) { try { if (issuer != null) { // use explicit method for normalization issuer = normalizeIssuer(issuer); /* this block may be used to enhance normalization (tknall) try { Name issuerName = new RFC2253NameParser(issuer).parse(); issuer = issuerName.getRFC2253String(); } catch (RFC2253NameParserException e) { logger_.error(e); } */ // added the ("UTF-8") issuer = CodingHelper.encodeBase64(CodingHelper.buildDigest(issuer.getBytes("UTF-8"), "sha1")); issuer = issuer.replaceAll("/", "_"); } return issuer; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Prepares issuer for further processing (e.g. calculation of certificate store location or * comparison with registered ldap mappings.) * @param issuer The issuer. * @return normalized issuer * @see #issuerNameFilter * @author tknall */ private String normalizeIssuer(String issuer) { issuer = normalizer_.normalize(issuer, false); issuer = removeAllWhiteSpaces(issuer); return issuer; } /** * This method imports new certificates into the certstore path. */ private void addNewCertificates() { String cert_add_path = certPath_ + CERT_ADD_DIR; File cert_add_dir = new File(cert_add_path); if (cert_add_dir.isDirectory()) { File[] cert_files = cert_add_dir.listFiles(); for (int cert_file_idx = 0; cert_file_idx < cert_files.length; cert_file_idx++) { File cert_file = cert_files[cert_file_idx]; if (cert_file.isFile() && cert_file.canRead()) { X509Cert cert = X509Cert.initByFile(cert_file); // System.err.println("isCert:" + cert.isX509Cert() + ":" + // cert_file.getAbsolutePath()); if (cert.isX509Cert()) { String issuer = cert.getIssuerName(); String serial_number = cert.getSerialNumber(); String iss_hash = getIssuerFileHash(issuer); String cert_store_path = certPath_ + iss_hash; File cert_store_dir = new File(cert_store_path); if (!cert_store_dir.exists()) { cert_store_dir.mkdir(); } if (cert_store_dir.isDirectory()) { String cert_file_name = cert_store_path + FILE_SEP + serial_number + CERT_FILE_EXTENSION; logger_.debug("Adding cert (issuer=\"" + cert.getIssuerName() + "\", sn=\"" + cert.getSerialNumber() + "\") to certstore: \"" + cert_file_name + "\"."); // boolean store = FileHelper.writeToFile(cert_file_name, cert.getCertString()); // System.err.println("store:" + store + ":" + // cert_file.getAbsolutePath()); } } boolean deleted = cert_file.delete(); if (deleted == false) { logger_.error("couldn't delete:" + cert_file.getAbsolutePath()); } } } } } private X509Cert loadCertificateFromCertstore(String serialNumber, String issuer) { String iss_hash = getIssuerFileHash(issuer); String cert_store_path = certPath_ + iss_hash; String cert_file_name = cert_store_path + FILE_SEP + serialNumber + CERT_FILE_EXTENSION; if (logger_.isDebugEnabled()) { logger_.debug("Trying to load cert (issuer=\"" + (issuer != null ? normalizeIssuer(issuer) : issuer) + "\", sn=\"" + serialNumber + "\") from certstore: \"" + cert_file_name + "\"."); } return X509Cert.initByFilePath(cert_file_name); } /** * This method load a X509v3 certificate from the filesystem. The reference to * the stored certificate is build by the serialNumber and the issuer string. * The issuer string is normalized because if getting this value from a pdf * extraction it can be splited into more sections or necessary spaces are * removed. The real issuer value is stored in the certificates meta file. The * certficate is devided into two files: certificate.der (the binary value) * and the meta information used in SignatureObjects as well in * SignatureImages of a signed pdf-document. The storing path of the * certificate is build by: *
    *
  1. normalize the issuer string
  2. *
  3. reduce all white spaces in the normalized issuer string
  4. *
  5. build a hash value of this reduced string
  6. *
  7. code this hash value as base64 value
  8. *
  9. add the base64 normalized issuer hash value to the certificate base * store path
  10. *
  11. add the serialNumber to the cert path
  12. *
  13. add the .der extension to get the certificate binary
  14. *
  15. add the .txt extension to get the meta information of * the certificate
  16. *
* * The certificate meta file is build by the base64 coded issuer string and * the cert digest value devided by the @ char. * * @param serialNumber * the file name of the certificate .der|.txt * @param issuer * the file path value of the certificate * @return String array: [0]--> issuer string; [1]-->certificate binary; * [2]--> cert digest value */ private X509Cert loadCertificate(String serialNumber, String issuer) { addNewCertificates(); X509Cert cert = null; if (issuer != null && serialNumber != null) { cert = loadCertificateFromCertstore(serialNumber, issuer); if (cert == null) { logger_.debug("Certificate not found. Trying alternative normalization method."); try { Name issuerName = new RFC2253NameParser(issuer).parse(); cert = loadCertificateFromCertstore(serialNumber, issuerName.getRFC2253String(false)); } catch (RFC2253NameParserException e) { logger_.error(e.getMessage(), e); } } if (cert == null) { logger_.info("The certificate '" + issuer + "', '" + serialNumber + "' wasn't found in the local certificate store - connecting to LDAP."); // the certificate wasn't found in the local store // - load it from the LDAP server. byte[] cert_data = loadCertificateFromLDAP(serialNumber, issuer); if (cert_data == null) { logger_.info("The certificate '" + issuer + "', '" + serialNumber + "' wasn't found on the LDAP server either."); return null; } storeNewCertificateInLocalStore(cert_data); cert = X509Cert.initByByteArray(cert_data); if (cert == null) { logger_.debug("The certificate should be loaded here, but is null - something's wrong."); } } } else { logger_.warn("loadCertificate(\"" + serialNumber + "\", \"" + issuer + "\")"); } return cert; } /** * This is an internal counter for added certificates. */ protected static int new_cert_num = 0; /** * Writes the certificate data to a file and stores the file in the local * certificate store. * * @param cert_data * The binary certificate data. */ public void storeNewCertificateInLocalStore(byte[] cert_data) { // write the loaded certificate to the add directory String cert_add_path = certPath_ + CERT_ADD_DIR; File cert_add_dir = new File(cert_add_path); if (!cert_add_dir.exists()) { cert_add_dir.mkdirs(); } File save_file = new File(cert_add_dir, "newcert_" + new_cert_num + ".der"); new_cert_num++; try { FileOutputStream fos = new FileOutputStream(save_file); fos.write(cert_data); fos.close(); // fixed by tknall: if serialnumber or issuername is omitted (binary signature) the // certificate could not be found in the certstore. The fix sets the issuername and // serialnumber as long the are known. X509Cert cert = X509Cert.initByByteArray(cert_data); if (cert.isX509Cert()) { this.setSignationSerialNumber(cert.getSerialNumber()); this.setSignationIssuer(cert.getIssuerName()); } } catch (IOException e) { logger_.error(e.getMessage(), e); return; } // add the new certificate to the local store addNewCertificates(); } /** * Connects to the LDAP server to look for the certificate. * * @param serialNumber * The serial number String of the certificate being sought. E.g. * "123455676744123432". * @param issuer * The issuer String of the certificate being sought. * * @return Returns the DER certificate file as can be stored in the local * repository. Returns null, if the document wasn't found on the * server. * @throws ClassNotFoundException */ protected byte[] loadCertificateFromLDAP(String serialNumber, String issuer) { // START modification by TK String implClassURI = System.getProperty(LDAPAPI.SYS_PROP_IMPLEMENTATION); LDAPAPI ldapAPIImpl; try { // note: in case of implClassURI==null the default implementation // at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIImpl is used ldapAPIImpl = LDAPAPIFactory.getInstance(issuerNameFilter).createLDAPAPI(implClassURI); } catch (LDAPAPIException e) { throw new RuntimeException(e); } return ldapAPIImpl.loadBase64CertificateFromLDAP(serialNumber, issuer); // STOP modification by TK } /** * This method stores a X509v3 certificate to the filesystem. The reference to * the stored certificate is build by the serialNumber and the issuer string. * The issuer string is normalized because if getting this value from a pdf * extraction it can be splited into more sections or necessary spaces are * removed. The real issuer value is stored in the certificates meta file. The * certficate is devided into two files: certificate.der (the binary value) * and the meta information used in SignatureObjects as well in * SignatureImages of a signed pdf-document. The storing path of the * certificate is build by: *
    *
  1. normalize the issuer string
  2. *
  3. reduce all white spaces in the normalized issuer string
  4. *
  5. build a hash value of this reduced string
  6. *
  7. code this hash value as base64 value
  8. *
  9. add the base64 normalized issuer hash value to the certificate base * store path
  10. *
  11. add the serialNumber to the cert path
  12. *
  13. add the .der extension to get the certificate binary
  14. *
  15. add the .txt extension to get the meta information of * the certificate
  16. *
* * The certificate meta file is build by the base64 coded issuer string and * the cert digest value devided by the @ char. * * @param serialNumber * the file name of the certificate .der|.txt * @param issuer * the issuer string for the file path value of the certificate and * for metainformation * @param x509Certificate * the x509v3 binary string * @param x509Digest * the digest value of the given x509Certificate * @return true the certificate is stored completely, false otherwise * @deprecated Use {@link #storeCertificate(String, String, String)} instead. */ private boolean storeCertificate(String serialNumber, String issuer, String x509Certificate, String x509Digest) { return storeCertificate(serialNumber, issuer, x509Certificate); } /** * This method stores a X509v3 certificate to the filesystem. The reference to * the stored certificate is build by the serialNumber and the issuer string. * The issuer string is normalized because if getting this value from a pdf * extraction it can be splited into more sections or necessary spaces are * removed. The real issuer value is stored in the certificates meta file. The * certficate is devided into two files: certificate.der (the binary value) * and the meta information used in SignatureObjects as well in * SignatureImages of a signed pdf-document. The storing path of the * certificate is build by: *
    *
  1. normalize the issuer string
  2. *
  3. reduce all white spaces in the normalized issuer string
  4. *
  5. build a hash value of this reduced string
  6. *
  7. code this hash value as base64 value
  8. *
  9. add the base64 normalized issuer hash value to the certificate base * store path
  10. *
  11. add the serialNumber to the cert path
  12. *
  13. add the .der extension to get the certificate binary
  14. *
  15. add the .txt extension to get the meta information of * the certificate
  16. *
* * The certificate meta file is build by the base64 coded issuer string and * the cert digest value devided by the @ char. * * @param serialNumber * the file name of the certificate .der|.txt * @param issuer * the issuer string for the file path value of the certificate and * for metainformation * @param x509Certificate * the x509v3 binary string * @return true the certificate is stored completely, false otherwise */ private boolean storeCertificate(String serialNumber, String issuer, String x509Certificate) { boolean store_complete = false; if (issuer != null && serialNumber != null) { logger_.debug("Storing certificate."); // String issuer_b64 = CodingHelper.encodeBase64(issuer.getBytes()); String iss_hash = getIssuerFileHash(issuer); File cert_path_dir = new File(certPath_); if (!cert_path_dir.exists()) { logger_.debug("Certstore path \"" + cert_path_dir + "\" does not exist. Creating."); cert_path_dir.mkdir(); } String cert_store_path = certPath_ + iss_hash; File cert_store_dir = new File(cert_store_path); if (!cert_store_dir.exists()) { logger_.debug("Certstore dir \"" + cert_store_dir + "\" does not exist. Creating."); cert_store_dir.mkdir(); } if (cert_store_dir.isDirectory()) { String cert_file_name = cert_store_path + FILE_SEP + serialNumber + CERT_FILE_EXTENSION; if (logger_.isInfoEnabled()) { logger_.debug("store certificate:" + cert_file_name); } boolean store_cert_file = FileHelper.writeToFile(cert_file_name, x509Certificate); store_complete = store_cert_file;// && store_cert_meta; } else { logger_.warn("Certstore dir \"" + cert_store_dir + "\" is not a directory. Skipping storage."); } } return store_complete; } /** * @return Returns the AbstractTable. * @see at.knowcenter.wag.egov.egiz.table.Table */ public Table getAbstractTable() { if (sigTable_ == null) { sigTable_ = createSigTable(SignatureTypes.MAIN_TABLE); } return sigTable_; } /** * This method read the style definitions from the settings file. * * @param styleKey * the key to read the style definitions * @return the defined style informations * @see at.knowcenter.wag.egov.egiz.table.Style */ private Style readStyle(String styleKey) { ArrayList styles = settings_.getKeys(styleKey); Style style = new Style(); for (int style_idx = 0; style_idx < styles.size(); style_idx++) { String style_id = (String) styles.get(style_idx); String style_val = settings_.getSetting(styleKey + "." + style_id, null); style.setStyle(style_id, style_val); } return style; } /** * This method creates an abstract signature table object. It takes all keys * and values set by the signature object to create the corresponding abstract * table object. The table definition is read from the settings file. * * @param tableKey * is the name of the table definition in the settings file * @return a new abstract signature table * @see at.knowcenter.wag.egov.egiz.table.Style * @see at.knowcenter.wag.egov.egiz.table.Table * @see at.knowcenter.wag.egov.egiz.table.Entry */ private Table createSigTable(String tableKey) { String table_key_prefix = SignatureTypes.SIG_OBJ + getSignationType() + "." + SignatureTypes.TABLE; String table_key = table_key_prefix + tableKey; // String caption_prefix = SignatureTypes.SIG_OBJ + getSignationType() + // ".key."; // String value_prefix = SignatureTypes.SIG_OBJ + getSignationType() + // ".value."; // ArrayList table_def_keys = settings_.getKeys(table_key); Vector table_def_keys = settings_.getSettingKeys(table_key); if (table_def_keys == null) { return null; } Table sig_table = new Table(tableKey); boolean found_style = false; for (int table_key_idx = table_def_keys.size() - 1; table_key_idx >= 0; table_key_idx--) { String table_def = (String) table_def_keys.get(table_key_idx); int dot_idx = (table_def.indexOf(".") > 0 ? table_def.indexOf(".") : table_def.length()); table_def = table_def.substring(0, dot_idx); String table_def_keys_prefix = table_key + "." + table_def; String table_def_string = settings_.getSetting(table_def_keys_prefix, null); if (table_def.matches("\\D*")) { // if the table key is not a number (row number index) if (SignatureTypes.COLS_WITH.equals(table_def)) { String[] cols_s = table_def_string.split(" "); float[] cols_f = new float[cols_s.length]; for (int i = 0; i < cols_s.length; i++) { cols_f[i] = Float.parseFloat(cols_s[i]); } sig_table.setColsRelativeWith(cols_f); } if (SignatureTypes.STYLE.equals(table_def) && !found_style) { Style style = readStyle(table_def_keys_prefix); sig_table.setStyle(style); found_style = true; } continue; } if (table_def_string != null) { // analyse the row definition String[] elems = table_def_string.split("\\|"); ArrayList row = new ArrayList(); for (int elem_idx = 0; elem_idx < elems.length; elem_idx++) { String elem = elems[elem_idx]; String[] key_type = elem.split("-"); if (key_type.length < 2) { return null; } String key = key_type[0]; String type = key_type[1]; if (SignatureTypes.TYPE_TABLE.equals(key)) { // add a table entry Table table = createSigTable(type); if (table != null) { Entry entry = new Entry(Entry.TYPE_TABLE, table, key); row.add(entry); } } if (SignatureTypes.TYPE_IMAGE.equals(type)) { // add an image entry String value = getSigValue(key); if (value != null) { Entry entry = new Entry(Entry.TYPE_IMAGE, value, key); entry.setStyle(defaultImageStyle_); row.add(entry); } } if (SignatureTypes.TYPE_VALUE.equals(type)) { // add a single value entry String value = getSigValue(key); Entry entry = new Entry(Entry.TYPE_VALUE, value, key); if (entry != null) { entry.setColSpan(2); entry.setStyle(defaultValueStyle_); row.add(entry); } } if ((SignatureTypes.TYPE_VALUE + SignatureTypes.TYPE_CAPTION).equals(type) || (SignatureTypes.TYPE_CAPTION + SignatureTypes.TYPE_VALUE).equals(type)) { // add a caption value pair String caption = getSigCaption(key); String value = getSigValue(key); if (value != null) { Entry c_entry = new Entry(Entry.TYPE_CAPTION, caption, key); c_entry.setNoWrap(true); // dferbas fix bug #331 c_entry.setStyle(defaultCaptionStyle_); Entry v_entry = new Entry(Entry.TYPE_VALUE, value, key); v_entry.setStyle(defaultValueStyle_); if (c_entry != null && v_entry != null) { row.add(c_entry); row.add(v_entry); } } } } sig_table.addRow(table_def, row); } } return sig_table; } /** * This method inits the signature object by the given type. It loads the * configured values and captions from the config.properties file. */ public void initByType() throws SignatureTypesException { if (sigType_ == null) { sigType_ = getDefaultSigType(); } SignatureTypes sig_types = SignatureTypes.getInstance(); signatureDefinition_ = sig_types.getSignatureTypeDefinition(sigType_); if (signatureDefinition_ == null) { final String msg = "The SignatureObject's sigType '" + sigType_ + "' wasn't found in the configuration file's specified signature profiles. This usually happens if the sig_obj.type.default object has been turned off or is misspelled."; logger_.error(msg); throw new SignatureTypesException(msg); } Map key_cap_map = signatureDefinition_.getKeyCaptionMap(); if (key_cap_map != null) { Iterator key_cap = key_cap_map.entrySet().iterator(); while (key_cap.hasNext()) { Map.Entry entry = (Map.Entry) key_cap.next(); String key = (String) entry.getKey(); String caption = (String) entry.getValue(); SignatureEntry sig_entry = null; if (sigEntries_.containsKey(key)) { sig_entry = (SignatureEntry) sigEntries_.get(key); } else { sig_entry = new SignatureEntry(key); sigEntries_.put(key, sig_entry); } sig_entry.setCaption(caption); } } Map key_val_map = signatureDefinition_.getKeyValueMap(); if (key_val_map != null) { Set key_val_set = key_val_map.entrySet(); Iterator key_val = key_val_set.iterator(); while (key_val.hasNext()) { Map.Entry entry = (Map.Entry) key_val.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); if (SignatureTypes.SIG_NORM.equals(key)) { try { normalizer_.setVersion(value); } catch (NormalizeException e) { throw new SignatureTypesException(e); } } // value = new String(CodingHelper.encodeUTF8(value)); // if (logger_.isDebugEnabled()) // { // logger_.debug("key:" + key + " value:" + value); // } setSigValue(key, value); } } } /** * This method returns a signature entry object. * * @param key * the corresponding key * @return the signature entry object of the given key, null if the key does * not exist */ public SignatureEntry getSigEntry(String key) { return (SignatureEntry) sigEntries_.get(key); } /** * This method is a helper function to remove all white spaces from a text. * * @param text * the white spaces should remove from * @return a text without white spaces */ private static String removeAllWhiteSpaces(String text) { return text.replaceAll("\\s", ""); } public SignatureTypeDefinition getSignatureTypeDefinition() { return this.signatureDefinition_; } /** * * @param placeholder * @return Returns the list of SignatureFieldDefinitions that's values in the * SignatureObject have been filled out with placeholders. */ public List fillValues(final char placeholder, boolean has_SIG_ID, boolean baikEnabled) { List variable_fields = new ArrayList(); List field_definitions = this.signatureDefinition_.getFieldDefinitions(); Iterator it = field_definitions.iterator(); while (it.hasNext()) { SignatureFieldDefinition sfd = (SignatureFieldDefinition) it.next(); String value_string = null; if (sfd.placeholder_length > 0) { if (sfd.field_name.equals(SignatureTypes.SIG_ID) && has_SIG_ID == false) { setValueBruteForce(SignatureTypes.SIG_ID, null); continue; } if (sfd.field_name.equals(SignatureTypes.SIG_ALG) && !baikEnabled) { setValueBruteForce(SignatureTypes.SIG_ID, null); continue; } char[] placeholder_chars = new char[sfd.placeholder_length]; for (int i = 0; i < placeholder_chars.length; i++) { placeholder_chars[i] = placeholder; } value_string = new String(placeholder_chars); variable_fields.add(sfd); setSigValue(sfd.field_name, value_string, true); } } return variable_fields; } /** * Returns the raw signature response XML string as set by the signing * Connector. * * @return Returns the XML response String. */ public String getRawSignatureResponse() { return this.raw_signature_response; } /** * Sets the raw signature response XML string. * *

* This should be used by the Connector to pass the response String to the * signer. *

* * @param raw_response_string * The new raw signature response string. */ public void setRawSignatureResponse(String raw_response_string) { this.raw_signature_response = raw_response_string; } /** * get timestamp if available * @return */ public String getTimeStamp() { return this.timeStamp; } /** * set timestamp * @param timeStamp */ public void setTimeStamp(String timeStamp) { this.timeStamp = timeStamp; } /** * The toString method, used for tests or debugging. */ public String toString() { String strg = ""; Iterator it = sigEntries_.values().iterator(); while (it.hasNext()) { SignatureEntry sig_entry = (SignatureEntry) it.next(); String key = sig_entry.getKey(); String caption = sig_entry.getCaption(); String value = sig_entry.getValue(); strg += key + "=" + caption + ":" + value + "\n"; } strg += "Signation Type:" + getSignationType() + "\n"; return strg; } public Map getSigEntries() { return sigEntries_; } }