aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors')
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java63
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java896
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java157
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java77
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java353
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java55
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java52
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java91
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java921
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java172
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java695
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java179
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java823
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java666
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java46
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java135
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java272
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java76
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java661
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java638
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java152
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java228
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java277
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java745
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java79
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java189
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java623
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java223
29 files changed, 9586 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java
new file mode 100644
index 0000000..aab8e6b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java
@@ -0,0 +1,63 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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: A1Connector.java,v 1.2 2006/08/25 17:09:17 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+
+/**
+ * @author wprinz
+ */
+public class A1Connector extends BKUConnector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("a1", "A-1");
+
+ /**
+ * Constructor.
+ *
+ * @throws SignatureException
+ * F.e.
+ */
+ public A1Connector() throws SignatureException
+ {
+ super();
+ }
+
+ /**
+ * Overrides the type of the BKUConnector to use the A1 settings.
+ */
+ protected String getType()
+ {
+ return CONNECTOR_INFORMATION.getIdentifier();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
new file mode 100644
index 0000000..c3b6421
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
@@ -0,0 +1,896 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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: BKUConnector.java,v 1.5 2006/10/31 08:18:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+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.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector for communicating with BKU.
+ *
+ * @deprecated use the new connectors.
+ *
+ * @author wlackner
+ * @author wprinz
+ */
+public class BKUConnector implements LocalConnector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("bku", "BKU");
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(BKUConnector.class);
+
+ /**
+ * The empty constructor
+ */
+ public BKUConnector() //throws SignatureException
+ {
+ //loadSettings();
+ }
+
+ /**
+ * load the inital signature settings
+ *
+ * @see SettingsReader
+ */
+ public void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method calls the BKU signing a given text. The signaton type is to
+ * used initializing the corresponding SigantureObject. The initialized
+ * SignatureObject is filled out by the parsed BKU-Response. <br>
+ * If an error request is send back from BKU, an error message is generated an
+ * an exception is thrown.
+ *
+ * @param sigType
+ * the type of the SignatureObject that should be returned
+ * @param userName
+ * the name of the user calling this method
+ * @param signText
+ * the text that shoulf be signed from BKU
+ * @return the complete SingatureObject of the given type filled by values
+ * from the BKU-Request
+ * @throws SignatureException
+ * @see SignatureObject
+ */
+ public SignatureObject doSign(String sigType, String userName, String signText) throws SignatureException
+ {
+ String request_string = prepareSignRequest(userName, signText, sigType);
+
+ String sign_url = getSignURL(sigType);
+ Properties response_properties = sendRequest(sign_url, request_string);
+
+ return analyzeSignResponse(response_properties, sigType);
+ }
+
+ /**
+ * This method generates the BKU verify prozess. It checks if the given
+ * SignatureObject is signed by MOA or BKU. The verify template string is
+ * filled out by the corresponding method.
+ *
+ * @param normalizedText
+ * the normalized text to verify
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return a SignatureResponse object if the verify prozess does not fails
+ * @throws SignatureException
+ * @see SignatureResponse
+ */
+ public SignatureResponse doVerify(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String request_string = prepareVerifyRequest(normalizedText, sigObject);
+
+ String verify_url = getVerifyURL(sigObject.getSignationType());
+ Properties response_properties = sendRequest(verify_url, request_string);
+
+ return analyzeVerifyResponse(response_properties);
+ }
+
+ /**
+ * This method parses the BKU-Response string. It separates the
+ * SignatureValue, X509IssuerName, SigningTime, X509SerialNumber,
+ * X509Certificate, CertDigest, DigestValue and the signation id-s. If the
+ * X509Certificate is extracted it would be stored in the certificates
+ * directory.
+ *
+ * @param xmlResponse
+ * the response string from the BKU sign-request
+ * @param sigObj
+ * the SignatureObject that should be filled
+ * @throws SignatureException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ private void parseCreateXMLResponse(Properties response_properties, SignatureObject sigObj) throws SignatureException
+ {
+ String xmlResponse = response_properties.getProperty("response_string");
+
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>");
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>");
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+
+ String sig_val = "";
+ String iss_nam = "";
+ String ser_num = "";
+ String sig_tim = "";
+ String sig_cer = "";
+ String sig_dig = "";
+
+ // SignatureValue
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start());
+ sig_val = sig_val.replaceAll("\\s", "");
+ sigObj.setSignationValue(sig_val);
+ }
+ // X509IssuerName
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sigObj.setSignationIssuer(iss_nam);
+ }
+ // X509SerialNumber
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sigObj.setSignationSerialNumber(ser_num);
+ }
+ // SigningTime
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ sigObj.setSignationDate(sig_tim);
+ }
+ // CertDigest
+ if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ {
+ String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), sig_cer_d_m_e.start());
+ Matcher dig_val_m_s = dig_val_p_s.matcher(cert_digest);
+ Matcher dig_val_m_e = dig_val_p_e.matcher(cert_digest);
+ if (dig_val_m_s.find() && dig_val_m_e.find())
+ {
+ sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ sigObj.setX509CertificateDigest(sig_dig);
+ }
+ }
+ // extract Subject Name from X509Certificate
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ sig_cer = sig_cer.replaceAll("\\s", "");
+ sigObj.setX509Certificate(sig_cer);
+ X509Cert cert = X509Cert.initByString(sig_cer);
+ if (cert.isX509Cert())
+ {
+ sigObj.setX509Certificate(cert.getCertString());
+ String serial_num = cert.getSerialNumber();
+ String subject_name = cert.getSubjectName();
+ if (!ser_num.equals(serial_num))
+ {
+ SignatureException se = new SignatureException(303, "Serialnumber of certificate and tag X509SerialNumber differs!");
+ throw se;
+ }
+ sigObj.setSignationName(subject_name);
+ }
+ }
+
+ // extract Signature Id's
+ String[] ids = new String[5];
+ ids[0] = extractId(xmlResponse, "signature-");
+ ids[1] = extractId(xmlResponse, "signed-data-reference-");
+ ids[2] = extractId(xmlResponse, "signed-data-object-");
+ ids[3] = extractId(xmlResponse, "etsi-data-reference-");
+ ids[4] = extractId(xmlResponse, "etsi-data-object-");
+
+ //TODO hotfix - already deprecated
+ String final_ids =SignatureObject.formatSigIds(response_properties, ids);
+ //sigObj.setSignationIDs(ids);
+ sigObj.setSignationIDs(final_ids);
+ }
+
+ /**
+ * This emthod extracts id-values from a text. The id is given by the name.
+ *
+ * @param text
+ * the id-value that should extract from
+ * @param name
+ * the id-key
+ * @return the value of the given key in the text
+ */
+ private String extractId(String text, String name)
+ {
+ String id = null;
+ int start_idx = text.indexOf(name) + name.length();
+ int end_idx = text.indexOf("\"", start_idx);
+
+ // TODO hotfix! - already deprecated
+ final int quot_end_idx = end_idx;
+ final int squot_end_idx = text.indexOf("'", start_idx);
+ end_idx = Math.min(quot_end_idx, squot_end_idx);
+ // TODO hotfix end! - already deprecated
+
+ id = text.substring(start_idx, end_idx);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("extract id:" + name + id);
+ }
+ return id;
+ }
+
+ /**
+ * This method reads the verify template from the file system and fills out
+ * the template with the SignatureObject values.
+ *
+ * @param normalizedText
+ * the normalized text to veryfied
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return the filled verify template string
+ * @throws SignatureException
+ * ErrorCode (311, 312, 313)
+ * @see SignatureObject
+ * @see CodingHelper
+ */
+ public String getVerifyTemplate(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ try
+ {
+ if (normalizedText == null || normalizedText.length() == 0)
+ {
+ SignatureException se = new SignatureException(311, "Document can not be verified because normalized text is empty.");
+ throw se;
+ }
+ if (sigObject == null)
+ {
+ SignatureException se = new SignatureException(312, "Document can not be verified because no signature object are set.");
+ throw se;
+ }
+
+ String verify_template = getVerifyTemplateFileName(sigObject.getSignationType());
+ String sig_prop_filename = getSigPropFileName(sigObject.getSignationType());
+
+ String ids_string = sigObject.getSignationIds();
+ logger_.debug("ids_string = " + ids_string);
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ // TODO hotfix - already deprecated
+ final boolean neue_bku = ids[5] != null;
+ logger_.debug("ids[5] = " + ids[5]);
+ logger_.debug("neue_bku = " + neue_bku);
+ if (neue_bku)
+ {
+ verify_template = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2"); //"./templates/BKUVerifyTemplateB64_neueBKU.xml";
+ sig_prop_filename = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2.SP"); //"./templates/BKUVerifyTemplateSP_neueBKU.xml";
+ }
+
+
+ //String ver_temp_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
+ String ver_temp_str = this.settings_.readInternalResourceAsString(verify_template);
+ //String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_filename));
+ String sig_prop_str = this.settings_.readInternalResourceAsString(sig_prop_filename);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_template);
+ logger_.debug(sig_prop_filename);
+ }
+
+ String x509_cert_string = sigObject.getX509CertificateString();
+ if (x509_cert_string == null)
+ {
+ SignatureException se = new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ throw se;
+ }
+ String cert_alg = settings_.getValueFromKey("cert.alg.ecdsa");
+ X509Cert x509_cert = sigObject.getX509Cert();
+ if (x509_cert.isRSA())
+ {
+ cert_alg = settings_.getValueFromKey("cert.alg.rsa");
+ }
+
+ sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate());
+
+ String issuer_name = sigObject.getSignationIssuer();
+ // The issuer is already unicode, so it mustn't be encoded again.
+ //byte[] issuer_name = CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
+ // new String(issuer_name); // this would double encode the String, not to mention the missing encoding
+ sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", issuer_name);
+
+ sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
+ sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
+ sig_prop_str = sig_prop_str.replaceFirst("SigIdReplace", ids[0]);
+ sig_prop_str = sig_prop_str.replaceFirst("SigDataRefReplace", ids[1]);
+
+ ver_temp_str = ver_temp_str.replaceFirst("CertAlgReplace", cert_alg);
+ ver_temp_str = ver_temp_str.replaceFirst("TemplateQualifyingPropertiesReplace", sig_prop_str);
+ byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1");
+
+ // TODO hotfix - already deprecated
+ if (neue_bku)
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; // xml name spaces follow, so this is not a complete tag...
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>";
+
+ final int hash_start = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = sig_prop_str.substring(hash_start, hash_end);
+ logger_.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed);
+
+ logger_.debug("\n--------------------- ETSI properties string to be hashed: start ---------------------");
+ logger_.debug(string_to_be_hashed);
+ logger_.debug("\n--------------------- ETSI properties string to be hashed: stop ---------------------");
+
+ final byte [] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8");
+ sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, "sha1");
+ }
+
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+ ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from QualifyingProperties:start");
+ //logger_.debug("DATA :" + sig_prop_str);
+ logger_.debug("DIGEST:" + sig_prop_hash);
+ logger_.debug("build digest from QualifyingProperties:end");
+ }
+
+ ver_temp_str = ver_temp_str.replaceFirst("SignatureValueReplace", sigObject.getSignationValue());
+ ver_temp_str = ver_temp_str.replaceFirst("X509CertificateReplace", x509_cert_string);
+ byte[] data_value = normalizedText.getBytes("UTF-8");
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, "sha1");
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+ // String object_data = new String(data_value);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from data object:start");
+ //logger_.debug("DATA :" + normalizedText);
+ logger_.debug("DIGEST:" + object_data_hash);
+ logger_.debug("build digest from data object:end");
+ }
+
+ //String raw_b64 = CodingHelper.encodeUTF8AsBase64(normalizedText);
+ String raw_b64 = CodingHelper.encodeBase64(data_value);
+
+ ver_temp_str = ver_temp_str.replaceFirst("Base64ContentReplace", raw_b64);
+ ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedDataReplace", object_data_hash);
+
+ ver_temp_str = ver_temp_str.replaceAll("SigIdReplace", ids[0]);
+ ver_temp_str = ver_temp_str.replaceAll("SigDataRefReplace", ids[1]);
+ ver_temp_str = ver_temp_str.replaceAll("SigDataObjURIReplace", ids[2]);
+ ver_temp_str = ver_temp_str.replaceAll("EtsiDataRefReplace", ids[3]);
+ ver_temp_str = ver_temp_str.replaceAll("EtsiDataObjURIReplace", ids[4]);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("VERIFY REQUEST:" + ver_temp_str);
+ }
+
+ return ver_temp_str;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new SignatureException(310, e);
+ }
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the BKU-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ private SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Try parsing the verify response");
+ }
+
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>");
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>");
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>");
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>");
+
+ Pattern sig_chk_p_s = Pattern.compile("<sl:SignatureCheck>");
+ Pattern sig_chk_p_e = Pattern.compile("</sl:SignatureCheck>");
+ Pattern man_chk_p_s = Pattern.compile("<sl:SignatureManifestCheck>");
+ Pattern man_chk_p_e = Pattern.compile("</sl:SignatureManifestCheck>");
+ Pattern cer_chk_p_s = Pattern.compile("<sl:CertificateCheck>");
+ Pattern cer_chk_p_e = Pattern.compile("</sl:CertificateCheck>");
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<sl:QualifiedCertificate/>");
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern code_p_s = Pattern.compile("<sl:Code>");
+ Pattern code_p_e = Pattern.compile("</sl:Code>");
+ Pattern info_p_s = Pattern.compile("<sl:Info>");
+ Pattern info_p_e = Pattern.compile("</sl:Info>");
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>");
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>");
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ Matcher info_m_s = info_p_s.matcher(sig_chk);
+ Matcher info_m_e = info_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = sig_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureCheckInfo(info);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ Matcher info_m_s = info_p_s.matcher(man_chk);
+ Matcher info_m_e = info_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = man_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureManifestCheckInfo(info);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ Matcher info_m_s = info_p_s.matcher(cer_chk);
+ Matcher info_m_e = info_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = cer_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setCertificateCheckInfo(info);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ return sig_res;
+ }
+
+
+
+ public String prepareSignRequest(String userName, String signText,
+ String signType) throws SignatureException
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Call " + getType() + " connector from user:" + userName);
+ }
+ String keybox_identifier = getSignKeyboxIdentifier(signType);
+ String sign_request_filename = getSignRequestTemplateFileName(signType);
+
+ //String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ String sign_req_str = this.settings_.readInternalResourceAsString(sign_request_filename);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_request_filename + "_signText.xml :" + signText);
+ }
+ String raw_b64 = CodingHelper.encodeUTF8AsBase64(signText);
+ if (sign_req_str == null || raw_b64 == null)
+ {
+ throw new SignatureException(300, "Can not read the create xml request template");
+ }
+ sign_req_str = sign_req_str.replaceFirst("KeyboxIdentifierReplace", keybox_identifier);
+ sign_req_str = sign_req_str.replaceFirst("Base64ContentReplace", raw_b64);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_request_filename + "_request.xml :"+ sign_req_str);
+ }
+
+ return sign_req_str;
+ }
+
+ public String prepareVerifyRequest(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_request);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_request);
+ }
+
+ String verify_template_str = null;
+ if (sigObject.isMOASigned())
+ {
+ MOAConnector moa_conn = new MOAConnector();
+ // get the MOA-template
+ verify_template_str = moa_conn.getVerifyTemplate(normalizedText, sigObject);
+ }
+ else
+ {
+ // get the BKU-template
+ verify_template_str = getVerifyTemplate(normalizedText, sigObject);
+ }
+ verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("verify_req_str.xml : " + verify_req_str);
+ }
+
+ return verify_req_str;
+ }
+
+ /**
+ * Sends the request to the given URL.
+ *
+ * @param url
+ * The URL.
+ * @param request_string
+ * The request string.
+ * @return Returns the response string.
+ * @throws SignatureException
+ * F.e.
+ */
+ protected Properties sendRequest(String url, String request_string) throws SignatureException
+ {
+ try
+ {
+ Properties response_properties = BKUPostConnection.doPostRequest(url, request_string);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ SignatureException se = new SignatureException(320, e);
+ throw se;
+ }
+ }
+
+ public SignatureObject analyzeSignResponse(Properties response_properties,
+ String sigType) throws SignatureException
+ {
+ //String sign_request_filename = getSignRequestTemplateFileName(sigType);
+
+ // TODO hotfix - already deprecated
+ String response_string = response_properties.getProperty("response_string");
+
+ SignatureObject sig_obj = new SignatureObject();
+ sig_obj.setRawSignatureResponse(response_string);
+ try
+ {
+ sig_obj.setSigType(sigType);
+ sig_obj.initByType();
+ }
+ catch (SignatureTypesException e)
+ {
+ SignatureException se = new SignatureException(300, "Cannot init signature object with type:" + sigType, e);
+ throw se;
+ }
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Signature Type is:" + sig_obj.getSignationType());
+ }
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+ // System.err.println(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(sign_request_filename + "_response.xml : " + response_string);
+ logger_.error("BKU Error response: " + response_string);
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("signature_response_string: " + response_string);
+ }
+ parseCreateXMLResponse(response_properties, sig_obj);
+ }
+ }
+ sig_obj.setSigResponse(response_string);
+ return sig_obj;
+ }
+
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException
+ {
+ String response_string = response_properties.getProperty("response_string");
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(getType() + "_response.xml : " + response_string);
+ logger_.error(getType() + "_response.xml : " + response_string);
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = null;
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ }
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(getType() + "_response.xml : " + response_string);
+ }
+ return parseVerifyXMLResponse(response_string);
+ }
+ }
+ return null;
+ }
+
+ protected String getConnectorValueFromProfile(String profile, String key)
+ {
+ String value = settings_.getValueFromKey("sig_obj." + profile + "." + key);
+ if (value == null)
+ {
+ value = settings_.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ public String getSignURL(String profile)
+ {
+ final String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignRequestTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignKeyboxIdentifier(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".KeyboxIdentifier";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ public String getVerifyURL(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyRequestTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSigPropFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template.SP";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ /**
+ * Returns the type of this BKU-like connector.
+ *
+ * <p>
+ * All settings keys will be prefixed by this type. So to reuse the BKU
+ * connector, a deriving class has to implement this method specifying an own
+ * type.
+ * </p>
+ *
+ * @return Returns the type of this BKU-like connector.
+ */
+ protected String getType()
+ {
+ return CONNECTOR_INFORMATION.getIdentifier();
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java
new file mode 100644
index 0000000..b676ed8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java
@@ -0,0 +1,157 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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: BKUPostConnection.java,v 1.3 2006/10/11 07:56:10 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.IOException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+
+/**
+ * @author wprinz
+ */
+public abstract class BKUPostConnection
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(BKUPostConnection.class);
+
+ /**
+ * This method connects the BKU server getting the request and the url. The
+ * request is an XML Message send and recieve by the HttpClient module. The
+ * Response message of the BKU server is is send back to the calling method.
+ *
+ * @param url
+ * the URL which the BKU server is running
+ * @param request
+ * the request string (XML) to send.
+ * @return the response string (XML) of the BKU server
+ * @throws IOException
+ * @throws HttpException
+ * ErrorCode:320
+ */
+ public static Properties doPostRequest(String url, String request) throws HttpException, IOException
+ {
+
+ PostMethod post_method = new PostMethod(url);
+
+ // It is very important to specify the charset of the content (the request)
+ // as UTF-8 this way.
+ // The HttpClient will then perform the URL encoding assuming that the
+ // request is UTF-8 as the BKU expects.
+ // If the MethodParams are omitted, the HttpClient will assume that the
+ // request is ISO-8859-1 and thereby the BKU cannot properly decode it.
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8");
+ post_method.setParams(method_params);
+
+ // This is just a hint: do not set the content-type this way or the BKU will
+ // assume it as text/XML, but the HttpClient sends it as URL-encoded.
+ // The HttpClient will automatically generate the proper Content-Type:
+ // application/x-www-form-urlencoded
+ // post.addRequestHeader(new Header("Content-Type",
+ // "text/xml;charset=UTF-8"));
+
+ NameValuePair[] data = { new NameValuePair("XMLRequest", request) };
+ post_method.setRequestBody(data);
+
+ HttpClient http_client = new HttpClient();
+ int method_response = http_client.executeMethod(post_method);
+ logger_.debug("method_response = " + method_response);
+
+ Properties response_properties = new Properties();
+
+ if (logger_.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ logger_.debug("#" + response_headers.length + " headers in response:");
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ logger_.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue());
+ }
+ }
+
+ Header server_header = post_method.getResponseHeader("Server");
+ logger_.debug("server_header: name = " + server_header.getName() + ", value = " + server_header.getValue());
+
+ parseBKUVersion(server_header.getValue(), response_properties);
+
+
+ byte[] response_body = post_method.getResponseBody();
+ String response_string = new String(response_body, "UTF-8");
+
+ // Alternatively this could be used.
+ // The HttpClient is assumed to use the Content-Type provided by the
+ // response.
+ // String response_string = post.getResponseBodyAsString();
+
+ response_properties.setProperty("response_string", response_string);
+
+ return response_properties;
+ }
+
+ // TODO hotfix
+ public static void parseBKUVersion(String header_value, Properties properties)
+ {
+ // dummy bku header starts with Apache Coyote...
+ //Pattern pattern = Pattern.compile("^citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)$");
+ //Pattern pattern = Pattern.compile("^.*citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)$");
+ Pattern pattern = Pattern.compile("^.*citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)(.*)$");
+ Matcher m = pattern.matcher(header_value);
+
+ m.matches();
+
+ logger_.debug("group count = " + m.groupCount());
+
+ for (int i = 0; i <= m.groupCount(); i++)
+ {
+ logger_.debug(" group[" + i + "] = " + m.group(i));
+ }
+
+ final String cceVersion = m.group(1);
+ final String productName = m.group(2);
+ final String productVersion = m.group(3);
+
+ logger_.debug("cceVersion = " + cceVersion);
+ logger_.debug("productName = " + productName);
+ logger_.debug("productVersion = " + productVersion);
+
+ properties.setProperty("cceVersion", cceVersion);
+ properties.setProperty("productName", productName);
+ properties.setProperty("productVersion", productVersion);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java
new file mode 100644
index 0000000..24dd728
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java
@@ -0,0 +1,77 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * @author wprinz
+ *
+ */
+public interface Connector
+{
+//23.11.2010 changed by exthex - added reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+
+ /**
+ * Performs a sign.
+ *
+ * @param data
+ * The data to be signed.
+ * @return Returns the signature object containing the signature data.
+ * @throws ConnectorException
+ * Thrown if something goes wrong.
+ */
+
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException;
+
+ /**
+ * Performs a verification.
+ *
+ * @param data
+ * The data to be verified.
+ * @param so
+ * The signature object with the signature information.
+ * @param dsig
+ * The xmldsig info which will be enveloped in the verify request.
+ * @return Returns the SignatureResponse with the result of the verification.
+ * @throws ConnectorException
+ * Thrown if something goes wrong.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException;
+
+ /**
+ * Reconstruct the xmldsig info of the given {@link SignSignatureObject}
+ *
+ * @param data
+ * @param so
+ * @return
+ * @throws ConnectorException
+ */
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
new file mode 100644
index 0000000..2fee4da
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
@@ -0,0 +1,353 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.LocRefDetachedBKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.MultipartDetachedBKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.OldEnvelopingBase64BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.EnvelopingBase64MOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter;
+
+/**
+ * Helper class that provides static methods that help the application to
+ * "choose" the right connector for a given task.
+ *
+ * @deprecated functionality split to ConnectorChooser implementations in framework commandline and web
+ *
+ * @author wprinz
+ */
+public final class ConnectorChooser
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(ConnectorChooser.class);
+
+ public static LocalConnector chooseLocalConnectorForSign(String connector,
+ String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing LocalConnector for signation...");
+
+ log.debug("connector type = " + connector);
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+
+ if (Constants.SIGNATURE_DEVICE_MOC.equals(connector)) {
+
+ return new LocRefDetachedMOCCAConnector(cp, loc_ref_url);
+
+ } else if (Constants.SIGNATURE_DEVICE_BKU.equals(connector)){
+
+ return new LocRefDetachedBKUConnector(cp, loc_ref_url);
+
+ }
+
+ log.error("Currently only the BKU connector is fully implemented.");
+ return new LocRefDetachedBKUConnector(cp, loc_ref_url);
+ }
+
+ public static Connector chooseWebConnectorForSign(String connector,
+ String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing Connector for WEB signation...");
+
+ log.debug("connector type = " + connector);
+
+ if (!connector.equals(Constants.SIGNATURE_DEVICE_MOA))
+ {
+ log.error("Currently only the MOA connector is available for non local WEB signation.");
+ }
+
+ log.debug("choosing locref detached MOA connector.");
+
+ //TODO TR: Hier umschalten, um von SwA-Requests zurueckzuwechseln.
+ // Loc_Ref-Connector
+// return new DetachedLocRefMOAConnector(profile, loc_ref_url);
+ // SwA-Connector
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MOASoapWithAttachmentConnector(cp);
+ }
+
+// public static Connector chooseCommandlineConnectorForSign(String connector,
+// String profile) throws ConnectorException
+// {
+// log.debug("Choosing Connector for commandline signation...");
+//
+// log.debug("connector type = " + connector);
+//
+// if (connector.equals(BKU))
+// {
+// log.debug("sig_app is BKU ==> MultipartDetachedBKUConnector"); //$NON-NLS-1$
+//
+// return new MultipartDetachedBKUConnector(profile);
+// }
+// if (connector.equals(MOA))
+// {
+// // TODO MOA detached signing is not allowed at the commandline
+// log.warn("Detached MOA is not supported on the commandline. -> choosing Base64 temporarily.");
+// return new EnvelopingBase64MOAConnector(profile);
+// }
+//
+// throw new ConnectorException(300, "Unknown connector type '" + connector + "' specified.");
+// }
+
+ public static LocalConnector chooseLocalConnectorForVerify(String connector,
+ PdfASID sig_kz, String sig_id, String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing LocalConnector for verification...");
+
+ log.debug("connector type = " + connector);
+ log.debug("sig_kz = " + sig_kz);
+ log.debug("sig_id = " + sig_id);
+
+ if (!connector.equals("bku"))
+ {
+ log.error("Currently only the BKU connector is fully implemented.");
+ }
+
+ if (sig_kz == null)
+ {
+ log.debug("sig_kz is null -> must be old signature -> choosing old Base64 connector.");
+
+ return new OldEnvelopingBase64BKUConnector(profile);
+ }
+
+ log.debug("sig_kz is not null -> must be one of the newer ... base64, base64 hotfix, or detached");
+
+ if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ log.debug("sig_kz version is 1.0.0 -> choosing base64 (old or hotfix)");
+
+ if (sig_id == null)
+ {
+ log.debug("sig_id is null, which means that it is a MOA signature -> choose a hotfix base64 connector (thus it is moa - it doesn't matter).");
+
+ return new EnvelopedBase64BKUConnector(profile);
+ }
+
+ String[] sig_id_parts = sig_id.split("@");
+ if (sig_id_parts.length == 2)
+ {
+ log.debug("sig_id has 2 @-separated parts -> choosing old base64 connector");
+
+ return new OldEnvelopingBase64BKUConnector(profile);
+ }
+ if (sig_id_parts[0].equals(HotfixIdFormatter.SIG_ID_PREFIX))
+ {
+ log.debug("sig_id prefix is hotfix -> choosing hotfix base64 connector");
+
+ return new EnvelopedBase64BKUConnector(profile);
+ }
+
+ throw new ConnectorException(300, "The SIG_KZ version is 1.0.0, but SIG_ID is neither MOA nor Old base64 nor Hotfix base64 ???'");
+ }
+ if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_1_0) || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_2_0))
+ {
+ log.debug("sig_kz version is 1.1.0/1.2.0 -> choosing detached (loc ref) connector.");
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new LocRefDetachedBKUConnector(cp, loc_ref_url);
+ }
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown. Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+ }
+
+ public static Connector chooseWebConnectorForVerify(String connector,
+ PdfASID sig_kz, String sig_id, String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing Connector for WEB verification...");
+
+ log.debug("connector type = " + connector);
+ log.debug("sig_kz = " + sig_kz);
+ log.debug("sig_id = " + sig_id);
+
+ if (!connector.equals("moa"))
+ {
+ log.error("Currently only the MOA connector is available for non local WEB signation.");
+ }
+
+ if (sig_kz == null || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ log.debug("sig_kz is null or sig_kz version is 1.0.0 -> choosing Base64 connector.");
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+
+ if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_1_0) || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_2_0))
+ {
+ log.debug("sig_kz version is 1.1.0/1.2.0 -> choosing detached (loc ref) connector.");
+
+ //throw new ConnectorException(ErrorCode.DETACHED_SIGNATURE_NOT_SUPPORTED, "The MOA detached connector is not suitable for verification.");
+ // TODO TR: Switch her for SwA or Detached-URL Connector
+ // the following line is used in connection with LocRef-Connector
+// return new DetachedLocRefMOAConnector(profile, loc_ref_url);
+ // the following line is uesed in connection with SwA-Connector
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MOASoapWithAttachmentConnector(cp);
+ }
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown. Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+ }
+
+// public static Connector chooseCommandlineConnectorForVerify(String connector,
+// PdfASID sig_kz, String sig_id, String profile) throws ConnectorException
+// {
+// log.debug("Choosing Connector for Commandline verification...");
+//
+// log.debug("connector type = " + connector);
+// log.debug("sig_kz = " + sig_kz); //$NON-NLS-1$
+// log.debug("sig_id = " + sig_id); //$NON-NLS-1$
+//
+// if (sig_kz == null)
+// {
+// log.debug("sig_kz is null -> chose an old enveloped base64 connector"); //$NON-NLS-1$
+//
+// return chooseEnvelopedBase64ConnectorOld(profile, connector);
+// }
+//
+// log.debug("sig_kz is not null -> one of the newer signatures");
+//
+// if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+// {
+// log.debug("Version is 1.0.0 -> Base64 Signatur (old or Hotfix).");
+//
+// if (sig_id == null)
+// {
+// log.debug("sig_id is null, which means that it is a MOA signature -> choose a hotfix base64 connector (thus it is moa - it doesn't matter).");
+//
+// return chooseEnvelopedBase64ConnectorHotfix(profile, connector);
+// }
+//
+// String[] sig_id_parts = sig_id.split("@");
+// if (sig_id_parts.length == 2)
+// {
+// log.debug("sig_id has 2 @-separated parts -> choosing old base64 connector");
+//
+// return chooseEnvelopedBase64ConnectorOld(profile, connector);
+// }
+// if (sig_id_parts[0].equals(HotfixIdFormatter.SIG_ID_PREFIX))
+// {
+// log.debug("sig_id prefix is hotfix -> choosing hotfix base64 connector");
+//
+// return chooseEnvelopedBase64ConnectorHotfix(profile, connector);
+// }
+//
+// throw new ConnectorException(300, "The SIG_KZ version is 1.0.0, but SIG_ID is neither MOA nor Old base64 nor Hotfix base64 ???'");
+// }
+// if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_1_0))
+// {
+// log.debug("Version is 1.1.0 -> chose a detached connector.");
+//
+// return chooseDetachedMultipartConnector(profile, connector);
+// }
+//
+// throw new ConnectorException(310, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown.");
+// }
+
+ protected static final String BKU = "bku"; //$NON-NLS-1$
+
+ protected static final String MOA = "moa"; //$NON-NLS-1$
+
+ protected static Connector chooseEnvelopedBase64ConnectorOld(String profile,
+ String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> OldEnvelopingBase64BKUConnector"); //$NON-NLS-1$
+
+ return new OldEnvelopingBase64BKUConnector(profile);
+ }
+ if (sig_app.equals(MOA))
+ {
+ log.debug("sig_app is MOA ==> EnvelopingBase64MOAConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+ throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ protected static Connector chooseEnvelopedBase64ConnectorHotfix(
+ String profile, String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> EnvelopedBase64BKUConnector"); //$NON-NLS-1$
+
+ return new EnvelopedBase64BKUConnector(profile);
+ }
+ if (sig_app.equals(MOA))
+ {
+ log.debug("sig_app is MOA ==> EnvelopedBase64MOAConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+ throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ protected static Connector chooseDetachedMultipartConnector(String profile,
+ String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> DetachedMultipartBKUConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MultipartDetachedBKUConnector(cp);
+ }
+ if (sig_app.equals(MOA))
+ {
+ log.debug("sig_app is MOA ==> DetachedMOAConnector"); //$NON-NLS-1$
+
+ String msg = "A Detached signature cannot be verified with the MOA connector (yet)."; //$NON-NLS-1$
+ log.error(msg);
+ throw new ConnectorException(ErrorCode.DETACHED_SIGNATURE_NOT_SUPPORTED, msg);
+ }
+ throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java
new file mode 100644
index 0000000..fa340cd
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java
@@ -0,0 +1,55 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+/**
+ * This class contains the key constants used by the Connectors to retrieve
+ * templates etc. from the Configuration.
+ *
+ * @author wprinz
+ */
+public abstract class ConnectorConfigurationKeys
+{
+
+ /**
+ * The application mode sign
+ */
+ public static final String VALUE_MODE_SIGN = "sign";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_MODE_VERIFY = "verify";
+
+ /**
+ * The key used to read out the available for web property.
+ */
+ public static final String AVAILABLE_FOR_WEB = "available_for_web";
+
+ /**
+ * The key used to read out the available for commandline property.
+ */
+ public static final String AVAILABLE_FOR_COMMANDLINE = "available_for_commandline";
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java
new file mode 100644
index 0000000..451f367
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java
@@ -0,0 +1,52 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Base class for connector environments
+ *
+ * @author dferbas
+ *
+ */
+public abstract class ConnectorEnvironment {
+
+ public abstract String getCertAlgEcdsa();
+
+ public abstract String getCertAlgRsa();
+
+ public abstract String getVerifyTemplate();
+
+ public String getDefaultAlgForCert(X509Certificate cert) {
+ String cert_alg;
+ cert_alg = getCertAlgEcdsa();
+ if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$
+ {
+ cert_alg = getCertAlgRsa();
+ }
+ return cert_alg;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java
new file mode 100644
index 0000000..5279a03
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java
@@ -0,0 +1,91 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.util.Properties;
+
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * @author wprinz
+ */
+public interface LocalConnector
+{
+//23.11.2010 changed by exthex - added XMLDsigData parameter to prepareVerifyRequest to allow reuse
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException;
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException;
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @param dsigData
+ * The previously recreated xmldsig block of the signature
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException;
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
new file mode 100644
index 0000000..ef355a0
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
@@ -0,0 +1,921 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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: MOAConnector.java,v 1.5 2006/10/31 08:18:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+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.exceptions.WebException;
+import at.knowcenter.wag.egov.egiz.sig.Connector;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector to access the MOA service.
+ *
+ * @deprecated
+ * @author wlackner
+ * @author wprinz
+ */
+public class MOAConnector implements Connector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("moa", "MOA");
+
+ /**
+ * The class type value.
+ *
+ * <p>
+ * Just for convenience.
+ * </p>
+ */
+ private static final String TYPE = CONNECTOR_INFORMATION.getIdentifier();
+
+ /**
+ * The connector description.
+ */
+ public static final String DESCRIPTION = "MOA";
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * MOA siganture verification mode
+ */
+ public static final String SERVICE_VERIFY = "SignatureVerification";
+
+ /**
+ * MOA siganture creation mode
+ */
+ public static final String SERVICE_SIGN = "SignatureCreation";
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(MOAConnector.class);
+
+ /**
+ * The empty constructor
+ */
+ public MOAConnector() throws SignatureException
+ {
+ loadSettings();
+ }
+
+ /**
+ * load the inital signature settings
+ *
+ * @see SettingsReader
+ */
+ private void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method calls the MOA signing a given text. The signaton type is to
+ * used initializing the corresponding SigantureObject. The initialized
+ * SignatureObject is filled out by the parsed MOA-Response. <br>
+ * If an error request is send back from MOA, an error message is generated an
+ * an exception is thrown.
+ *
+ * @param sigType
+ * the type of the SignatureObject that should be returned
+ * @param userName
+ * the name of the user calling this method
+ * @param signText
+ * the text that shoulf be signed from MOA
+ * @return the complete SingatureObject of the given type filled by values
+ * from the MOA-Request
+ * @throws SignatureException
+ * ErrorCode 300
+ * @see SignatureObject
+ */
+ public SignatureObject doSign(String sigType, String userName, String signText) throws SignatureException
+ {
+ SignatureObject sig_obj = new SignatureObject();
+ try
+ {
+ sig_obj.setSigType(sigType);
+ sig_obj.initByType();
+ }
+ catch (SignatureTypesException e)
+ {
+ SignatureException se = new SignatureException(300, "Can ot init signature object with type:" + sigType, e);
+ throw se;
+ }
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Signature Type is:" + sig_obj.getSignationType());
+ }
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Call " + TYPE + " from user:" + userName);
+ }
+
+ String url = getSignURL(sigType);
+
+ String sign_request_filename = getSignRequestTemplateFileName(sigType);
+ String key_ident = getSignKeyIdentifier(sigType);
+
+ //String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ String sign_req_str = this.settings_.readInternalResourceAsString(sign_request_filename);
+ if (sign_req_str == null)
+ {
+ SignatureException se = new SignatureException(300, "File not found:" + sign_request_filename);
+ throw se;
+ }
+
+ sign_req_str = sign_req_str.replaceFirst("KeyIdentifierReplace", key_ident);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("error_signature_response = " + sign_req_str);
+ // FileHelper.writeToFile(sign_request_filename + "_signText.xml",
+ // signText);
+ }
+ // sign_req_str = sign_req_str.replaceFirst("XMLContentReplace", signText);
+ // now use the the base64 Template
+ signText = CodingHelper.encodeUTF8AsBase64(signText);
+ sign_req_str = sign_req_str.replaceFirst("Base64ContentReplace", signText);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_req_str);
+ // FileHelper.writeToFile(sign_request_filename + "_request.xml",
+ // sign_req_str);
+ }
+
+ String response_string = "";
+ try
+ {
+ response_string = MOAConnector.connectMOA(sign_req_str, MOAConnector.SERVICE_SIGN, url);
+ sig_obj.setRawSignatureResponse(response_string);
+ }
+ catch (WebException we)
+ {
+ SignatureException se = new SignatureException(we.getErrorCode(), we);
+ throw se;
+ }
+
+ if (!response_string.equals(""))
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("get MOA response");
+ }
+ Pattern erc_p_s = Pattern.compile("<ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+ // System.err.println(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("error_signature_response = " + response_string);
+ // FileHelper.writeToFile(sign_request_filename + "_response.xml",
+ // response_string);
+ //logger_.error("Write error response to file:" + sign_request_filename + "_response.xml");
+ }
+ Pattern erm_p_s = Pattern.compile("<Info>");
+ Pattern erm_p_e = Pattern.compile("</Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ logger_.debug("error_code = " + error_code);
+ String error_mess = "";
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ logger_.debug(error_mess);
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("response_string = " + response_string);
+ // FileHelper.writeToFile(sign_request_filename + "_response.xml",
+ // response_string);
+ }
+ parseCreateXMLResponse(response_string, sig_obj);
+ }
+ }
+ sig_obj.setSigResponse(response_string);
+ return sig_obj;
+ }
+
+ /**
+ * This method parses the MOA-Response string. It separates the
+ * SignatureValue, X509IssuerName, SigningTime, X509SerialNumber,
+ * X509Certificate, CertDigest and DigestValues. If the X509Certificate is
+ * extracted it would be stored in the certificates directory.
+ *
+ * @param xmlResponse
+ * the response string from the MOA sign-request
+ * @param sigObj
+ * the SignatureObject that should be filled
+ * @throws SignatureException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ private void parseCreateXMLResponse(String xmlResponse, SignatureObject sigObj) throws SignatureException
+ {
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>");
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>");
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+
+ String sig_val = "";
+ String iss_nam = "";
+ String ser_num = "";
+ String sig_tim = "";
+ String sig_cer = "";
+ String sig_dig = "";
+
+ // SignatureValue
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start());
+ sig_val = sig_val.replaceAll("\\s", "");
+ sigObj.setSignationValue(sig_val);
+ }
+ // X509IssuerName
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sigObj.setSignationIssuer(iss_nam);
+ }
+ // X509SerialNumber
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sigObj.setSignationSerialNumber(ser_num);
+ }
+ // SigningTime
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ sigObj.setSignationDate(sig_tim);
+ }
+ // CertDigest
+ if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ {
+ String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), sig_cer_d_m_e.start());
+ Matcher dig_val_m_s = dig_val_p_s.matcher(cert_digest);
+ Matcher dig_val_m_e = dig_val_p_e.matcher(cert_digest);
+ if (dig_val_m_s.find() && dig_val_m_e.find())
+ {
+ sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ sigObj.setX509CertificateDigest(sig_dig);
+ }
+ }
+ // extract Subject Name from X509Certificate
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ sig_cer = sig_cer.replaceAll("\\s", "");
+ X509Cert cert = X509Cert.initByString(sig_cer);
+ if (cert.isX509Cert())
+ {
+ sigObj.setX509Certificate(cert.getCertString());
+ String serial_num = cert.getSerialNumber();
+ String subject_name = cert.getSubjectName();
+ if (!ser_num.equals(serial_num))
+ {
+ SignatureException se = new SignatureException(303, "Serialnumber of certificate and tag X509SerialNumber differs!");
+ throw se;
+ }
+ sigObj.setSignationName(subject_name);
+ }
+ }
+ }
+
+ /**
+ * This method reads the verify template from the file system and fills out
+ * the template with the SignatureObject values.
+ *
+ * @param normalizedText
+ * the normalized text to veryfied
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return the filled verify template string
+ * @throws SignatureException
+ * ErrorCode (311, 312, 313)
+ * @see SignatureObject
+ * @see CodingHelper
+ */
+ public String getVerifyTemplate(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ try
+ {
+ if (normalizedText == null || normalizedText.length() == 0)
+ {
+ SignatureException se = new SignatureException(311, "Document can not be verified because normalized text is empty.");
+ throw se;
+ }
+ if (sigObject == null)
+ {
+ SignatureException se = new SignatureException(312, "Document can not be verified because no signature object are set.");
+ throw se;
+ }
+ String verify_template = getVerifyTemplateFileName(sigObject.getSignationType());
+ String sig_prop_template = getSigPropFileName(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_template);
+
+ //String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_template));
+ String sig_prop_str = this.settings_.readInternalResourceAsString(sig_prop_template);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_template);
+ //logger_.debug(sig_prop_template);
+ }
+
+ String x509Certificate = sigObject.getX509CertificateString();
+ if (x509Certificate == null)
+ {
+ SignatureException se = new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ throw se;
+ }
+ String cert_alg = settings_.getValueFromKey("cert.alg.ecdsa");
+ X509Cert x509_cert = sigObject.getX509Cert();
+ if (x509_cert.isRSA())
+ {
+ cert_alg = settings_.getValueFromKey("cert.alg.rsa");
+ }
+
+ sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate());
+ // The issuer is already a valid Unicode String.
+ // No need to convert it - not to mention the missing encoding.
+ // byte[] issuer_name =
+ // CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
+ // new String(issuer_name)
+ sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", sigObject.getSignationIssuer());
+ sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
+ sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
+
+ verify_req_str = verify_req_str.replaceFirst("CertAlgReplace", cert_alg);
+ verify_req_str = verify_req_str.replaceFirst("TemplateSignedPropertiesReplace", sig_prop_str);
+ byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1"); // added
+ // the
+ // ("UTF-8")
+ // encoding
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+ verify_req_str = verify_req_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from SignedProperties:start");
+ //logger_.debug("DATA :" + sig_prop_str);
+ logger_.debug("DIGEST:" + sig_prop_hash);
+ logger_.debug("build digest from SignedProperties:end");
+ }
+
+ verify_req_str = verify_req_str.replaceFirst("SignatureValueReplace", sigObject.getSignationValue());
+ verify_req_str = verify_req_str.replaceFirst("X509CertificateReplace", x509Certificate);
+ byte[] data_value = normalizedText.getBytes("UTF-8");
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, "sha1");
+ // byte[] data_value_hash =
+ // CodingHelper.buildDigest(normalizedText.getBytes());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+ //String object_data = normalizedText; // new String(data_value);
+ // System.err.println(object_data_hash);
+ // very_req_str = very_req_str.replaceFirst("ObjectDataReplace",
+ // object_data);
+ String raw_b64 = CodingHelper.encodeBase64(data_value);
+ verify_req_str = verify_req_str.replaceFirst("Base64ContentReplace", raw_b64);
+
+ verify_req_str = verify_req_str.replaceFirst("DigestValueSignedDataReplace", object_data_hash);
+ if (logger_.isDebugEnabled())
+ {
+ // FileHelper.writeToFile(verify_template + "_verifyText.xml",
+ // normalizedText);
+ logger_.debug("build digest from data object:start");
+ //logger_.debug("DATA :" + object_data);
+ logger_.debug("DIGEST:" + object_data_hash);
+ logger_.debug("build digest from data object:end");
+ }
+ return verify_req_str;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new SignatureException(310, e);
+ }
+ }
+
+ /**
+ * This method generates the MOA verify prozess. It checks if the given
+ * SignatureObject is signed by MOA or BKU. The verify template string is
+ * filled out by the corresponding method.
+ *
+ * @param normalizedText
+ * the normalized text to verify
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return a SignatureResponse object if the verify prozess does not fails
+ * @throws SignatureException
+ * @see SignatureResponse
+ */
+ public SignatureResponse doVerify(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String verify_url = getVerifyURL(sigObject.getSignationType()); // settings_.getValueFromKey(TYPE
+ // + "." +
+ // Signature.VALUE_MODE_VERIFY
+ // +
+ // ".url");
+ String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType()); // settings_.getValueFromKey(TYPE
+ // +
+ // "."
+ // +
+ // Signature.VALUE_MODE_VERIFY
+ // +
+ // ".request");
+ String trust_profile = getVerifyTrustProfileID(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_request);
+
+ String verify_template_str = null;
+ if (sigObject.isMOASigned())
+ {
+ verify_template_str = getVerifyTemplate(normalizedText, sigObject);
+ }
+ else
+ {
+ BKUConnector bku_conn = new BKUConnector();
+ verify_template_str = bku_conn.getVerifyTemplate(normalizedText, sigObject);
+ }
+ verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ verify_req_str = verify_req_str.replaceFirst("TrustProfileIDReplace", trust_profile);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_req_str);
+ // FileHelper.writeToFile(verify_request + "_request.xml",
+ // verify_req_str);
+ }
+ String response_string = "";
+ try
+ {
+ response_string = MOAConnector.connectMOA(verify_req_str, MOAConnector.SERVICE_VERIFY, verify_url);
+ }
+ catch (WebException we)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ we.printStackTrace();
+ }
+ SignatureException se = new SignatureException(we.getErrorCode(), we);
+ throw se;
+ }
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(response_string);
+ // FileHelper.writeToFile(verify_request + "_response.xml",
+ // response_string);
+ logger_.error("Write error response to file:" + verify_request + "_response.xml");
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_request + "_response.xml " + response_string);
+ }
+ return parseVerifyXMLResponse(response_string);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the MOA-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ private SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Try parsing the verify response");
+ }
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>");
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>");
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>");
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>");
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<QualifiedCertificate/>");
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern sig_chk_p_s = Pattern.compile("<SignatureCheck>");
+ Pattern sig_chk_p_e = Pattern.compile("</SignatureCheck>");
+ Pattern man_chk_p_s = Pattern.compile("<SignatureManifestCheck>");
+ Pattern man_chk_p_e = Pattern.compile("</SignatureManifestCheck>");
+ Pattern cer_chk_p_s = Pattern.compile("<CertificateCheck>");
+ Pattern cer_chk_p_e = Pattern.compile("</CertificateCheck>");
+
+ Pattern code_p_s = Pattern.compile("<Code>");
+ Pattern code_p_e = Pattern.compile("</Code>");
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>");
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>");
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ // public authority
+ Pattern publicAuthority_p = Pattern.compile("<PublicAuthority/>");
+ Matcher publicAuthority_m = publicAuthority_p.matcher(xmlResponse);
+ sig_res.setPublicAuthority(false);
+ sig_res.setPublicAuthorityCode(null);
+ if (publicAuthority_m.find()) {
+ sig_res.setPublicAuthority(true);
+ } else {
+ Matcher publicAuthority_m_s = Pattern.compile("<PublicAuthority>").matcher(xmlResponse);
+ Matcher publicAuthority_m_e = Pattern.compile("</PublicAuthority>").matcher(xmlResponse);
+ if (publicAuthority_m_s.find() && publicAuthority_m_e.find()) {
+ sig_res.setPublicAuthority(true);
+ String codePart = xmlResponse.substring(publicAuthority_m_s.end(), publicAuthority_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(codePart);
+ Matcher code_m_e = code_p_e.matcher(codePart);
+ if (code_m_s.find() && code_m_e.find()) {
+ String code = codePart.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setPublicAuthorityCode(code);
+ }
+ }
+ }
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ return sig_res;
+ }
+
+ protected String getConnectorValueFromProfile(String profile, String key)
+ {
+ String value = settings_.getValueFromKey("sig_obj." + profile + "." + key);
+ if (value == null)
+ {
+ value = settings_.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ public String getSignURL(String profile)
+ {
+ final String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignRequestTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignKeyIdentifier(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".KeyIdentifier";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ public String getVerifyURL(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyRequestTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSigPropFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template.SP";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTrustProfileID(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".TrustProfileID";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ /**
+ * This method connects the moa server getting the requestString, the given
+ * serviseMode and the endpointUrl. The requestString is the envelope of the
+ * SOAP Message send and recieve by the AXIS module. The Response SOAP message
+ * of the MOA server is parsed by AXIS and the message envelope is send back
+ * to the calling method.
+ *
+ * @param requestString
+ * the request string (XML) to send.
+ * @param serviceMode
+ * the mode which connect to MOA
+ * @param endpointURL
+ * the URL which the MOA server is running
+ * @return the response string (XML) of the MOA server
+ * @throws WebException
+ */
+ public static String connectMOA(String requestString, String serviceMode,
+ String endpointURL) throws WebException
+ {
+ try
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info(serviceMode);
+ logger_.info(endpointURL);
+ }
+ // Parser/DOMBuilder instanzieren
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ // XML Datei in einen DOM-Baum umwandeln
+ ByteArrayInputStream bais = new ByteArrayInputStream(requestString.getBytes("UTF-8"));
+ Document xmlRequest = builder.parse(bais);
+
+ // Call oeffnen
+ Call call = null;
+
+ // Neues BodyElement anlegen und mit dem DOM-Baum fuellen
+ SOAPBodyElement body = new SOAPBodyElement(xmlRequest.getDocumentElement());
+ SOAPBodyElement[] params = new SOAPBodyElement[] { body };
+
+ // AXIS-Server instanzieren
+ Service service = ServiceFactory.newInstance().createService(new QName(serviceMode));
+ call = service.createCall();
+ call.setTargetEndpointAddress(endpointURL);
+
+ // Call ausloesen und die Antworten speichern
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Calling MOA:" + endpointURL);
+ }
+ Vector responses = (Vector) call.invoke(params);
+
+ // Erstes Body Element auslesen
+ SOAPBodyElement response = (SOAPBodyElement) responses.get(0);
+
+ // Aus der Response den DOM-Baum lesen
+ Document root_response = response.getAsDocument();
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Return from MOA:" + serviceMode);
+ }
+
+ // XML-Formatierung konfiguieren
+ OutputFormat format = new OutputFormat((Document) root_response);
+ format.setLineSeparator("\n");
+ format.setIndenting(false);
+ format.setPreserveSpace(true);
+ format.setOmitXMLDeclaration(false);
+ format.setEncoding("UTF-8");
+
+ // Ausgabe der Webservice-Antwort auf die Konsole
+ // XMLSerializer conSerializer = new XMLSerializer(System.out, format);
+ // conSerializer.serialize(root_response);
+
+ // Ausgabe der Webservice-Antwort in Datei
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer response_serializer = new XMLSerializer(baos, format);
+ response_serializer.serialize(root_response);
+ return baos.toString("UTF-8");
+ }
+ catch (Exception e)
+ {
+ throw new WebException(e);
+ }
+ // serialize signature only
+
+ // if
+ // (root_response.getDocumentElement().getLocalName().equals("CreateXMLSignatureResponse"))
+ // {
+ // Element signature = (Element)
+ // root_response.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#",
+ // "Signature").item(0);
+ // String signatureFile = getProperty(mode + "Request").substring(0,
+ // getProperty(mode +
+ // "Request").lastIndexOf('.')) + ".Signature.xml";
+ // fileSerializer = new XMLSerializer(new FileOutputStream(signatureFile),
+ // format);
+ // fileSerializer.serialize(signature);
+ // }
+
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
new file mode 100644
index 0000000..7caf422
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
@@ -0,0 +1,172 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+/**
+ * This class contains String constants that are frequently used in various
+ * connector templates to fill in the data into the templates.
+ *
+ * @author wprinz
+ */
+public final class TemplateReplaces
+{
+ /**
+ * The placeholder text in the template to be replaced by the keybox
+ * identifier.
+ */
+ public static final String KEYBOX_IDENTIFIER_REPLACE = "KeyboxIdentifierReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the mime type.
+ */
+ public static final String MIME_TYPE_REPLACE = "MimeTypeReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the XML content of
+ * another template.
+ */
+ public static final String XML_CONTENT_REPLACE = "XMLContentReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the cert alg.
+ */
+ public static final String CERT_ALG_REPLACE = "CertAlgReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest value of
+ * the signed data.
+ */
+ public static final String DIGEST_VALUE_SIGNED_DATA_REPLACE = "DigestValueSignedDataReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signature value.
+ */
+ public static final String SIGNATURE_VALUE_REPLACE = "SignatureValueReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the X.509
+ * certificate.
+ */
+ public static final String X509_CERTIFICATE_REPLACE = "X509CertificateReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signing time.
+ */
+ public static final String SIGNING_TIME_REPLACE = "SigningTimeReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the certificate
+ * digest.
+ */
+ public static final String DIGEST_VALUE_CERTIFICATE_REPLACE = "DigestValueX509CertificateReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the issuer name.
+ */
+ public static final String X509_ISSUER_NAME_REPLACE = "X509IssuerNameReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the serial number.
+ */
+ public static final String X509_SERIAL_NUMBER_REPLACE = "X509SerialNumberReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signed
+ * properties digest.
+ */
+ public static final String DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE = "DigestValueSignedPropertiesReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigDataRef.
+ */
+ public static final String SIG_DATA_REF_REPLACE = "SigDataRefReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the EtsiDataRef.
+ */
+ public static final String ETSI_DATA_REF_REPLACE = "EtsiDataRefReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigDataObjURI.
+ */
+ public static final String SIG_DATA_OBJ_URI_REPLACE = "SigDataObjURIReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the EtsiDataObjURI.
+ */
+ public static final String ETSI_DATA_OBJ_URI_REPLACE = "EtsiDataObjURIReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigId.
+ */
+ public static final String SIG_ID_REPLACE = "SigIdReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the key identifier.
+ */
+ public static final String KEY_IDENTIFIER_REPLACE = "KeyIdentifierReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the LocRefContent
+ * URL.
+ */
+ public static final String LOC_REF_CONTENT_REPLACE = "LocRefContentReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the trust profile ID.
+ */
+ public static final String TRUST_PROFILE_ID_REPLACE = "TrustProfileIDReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the return hash input data element.
+ */
+ public static final String RETURN_HASH_INPUT_DATA_REPLACE = "ReturnHashInputDataReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the dateTime element.
+ */
+ public static final String DATE_TIME_REPLACE = "DateTimeReplace"; // $NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the Base64 content.
+ */
+ public static final String BASE64_CONTENT_REPLACE = "Base64ContentReplace"; //$NON-NLS-1$
+
+//dferbas
+ /**
+ * The placeholder text in the template to be replaced by the digest method for data.
+ */
+ public static final String DATA_DIGEST_REPLACE = "DataDigestReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest method for properties.
+ */
+ public static final String PROPERTIES_DIGEST_REPLACE = "PropertiesDigestReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest method for cert.
+ */
+ public static final String CERT_DIGEST_REPLACE = "CertDigestReplace"; //$NON-NLS-1$
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
new file mode 100644
index 0000000..64306ab
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
@@ -0,0 +1,695 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.internal.LocalBKUParams;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Contains static helper methods used by the BKU Connectors.
+ *
+ * @author wprinz
+ */
+public final class BKUHelper
+{
+
+ private static final Pattern ALLOWED_SL_RESPONSE_PATTERN = Pattern.compile("^.*<[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)[^>]*>(.*)</[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)>.*$", Pattern.DOTALL);
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(BKUHelper.class);
+
+ /**
+ * Encodes the given SignatureData to a valid Base64Content.
+ *
+ * <p>
+ * The data is Base64 encoded. If the mime-type suggests that the data is
+ * binary, it is Base64 encoded for a second time.
+ * </p>
+ *
+ * @param data
+ * The data to be converted to a valid Base64 content.
+ * @return Returns the Base64 content.
+ */
+ public static String prepareBase64Content(SignatureData data)
+ {
+ // PERF: base64 encoding needs byte array
+ byte [] d = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource());
+
+ String base64 = CodingHelper.encodeBase64(d);
+ if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$
+ {
+ log.debug("The data is application/pdf - so the binary data is Base64 encoded."); //$NON-NLS-1$
+ base64 = CodingHelper.encodeUTF8AsBase64(base64);
+ }
+ return base64;
+
+ }
+
+ /**
+ * Prepares the enveloping data.
+ * <p>
+ * This is useful for building the hash.
+ * </p>
+ *
+ * @param data
+ * The data to be prepared.
+ * @return Returns the prepared data.
+ */
+ public static byte[] prepareEnvelopingData(SignatureData data)
+ {
+ // PERF: prepareEnvelopingData needs byte array
+ byte[] enc = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource());
+
+ if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$
+ {
+ log.debug("The data is application/pdf - so the binary data is Base64 encoded."); //$NON-NLS-1$
+ String base64 = CodingHelper.encodeBase64(enc);
+ try
+ {
+ enc = base64.getBytes("US-ASCII"); //$NON-NLS-1$
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e); //$NON-NLS-1$
+ }
+ }
+ return enc;
+ }
+
+ /**
+ * Checks the response xml for an error description and if found throws an
+ * appropriate exception.
+ *
+ * @param response_string
+ * The response xml.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public static void checkResponseForError(String response_string) throws ConnectorException
+ {
+ if (StringUtils.isEmpty(response_string)) {
+ throw new ConnectorException(ErrorCode.UNABLE_TO_RECEIVE_SUITABLE_RESPONSE, "No suitable response received.");
+ }
+ log.debug("Checking response for error: " + response_string);
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>"); //$NON-NLS-1$
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>"); //$NON-NLS-1$
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ log.error("Found error in response: " + response_string); //$NON-NLS-1$
+
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>"); //$NON-NLS-1$
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new ExternalErrorException(error_code, error_mess);
+ }
+ log.debug("No error found. Assuring that CreateXMLSignatureResponse or VerifyXMLSignatureResponse elements are available.");
+
+ // assure that a CreateXMLSignatureResponse or a VerifyXMLSignatureResponse is available
+ Matcher slMatcher = ALLOWED_SL_RESPONSE_PATTERN.matcher(response_string);
+ if (!slMatcher.matches()) {
+ throw new ConnectorException(ErrorCode.UNABLE_TO_RECEIVE_SUITABLE_RESPONSE, "No suitable response received: " + response_string);
+ }
+
+ }
+
+ /**
+ * This method parses the BKU-Response string.
+ *
+ * <p>
+ * It separates the SignatureValue, X509IssuerName, SigningTime,
+ * X509SerialNumber, X509Certificate, CertDigest, DigestValue and the
+ * signation id-s. If the X509Certificate is extracted it would be stored in
+ * the certificates directory.
+ * </p>
+ *
+ * @param xmlResponse
+ * The response string.
+ * @return Returns the parsed signature object holding the data.
+ *
+ * @throws ConnectorException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public static SignSignatureObject parseCreateXMLResponse(String xmlResponse,
+ IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException
+ {
+ if (log.isDebugEnabled()) {
+ log.debug("xmlResponse = " + xmlResponse);
+ }
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+
+ // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+ // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse);
+ // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start()));
+ }
+ log.debug("sig_val = " + sig_val); //$NON-NLS-1$
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num); //$NON-NLS-1$
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$
+
+ // CertDigest
+ // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ // {
+ // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(),
+ // sig_cer_d_m_e.start());
+ // if (dig_val_m_s.find() && dig_val_m_e.find())
+ // {
+ // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ // //sigObj.setX509CertificateDigest(sig_dig);
+ // }
+ // }
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ String sig_cer = removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try
+ {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (CertificateException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (IOException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert); //$NON-NLS-1$
+
+ if (log.isDebugEnabled())
+ {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$
+ log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$
+ }
+
+ // extract Subject Name from X509Certificate
+ // if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ // {
+ // sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ // sig_cer = sig_cer.replaceAll("\\s", "");
+ // //sigObj.setX509Certificate(sig_cer);
+ // X509Cert cert = X509Cert.initByString(sig_cer);
+ // if (cert.isX509Cert())
+ // {
+ // //sigObj.setX509Certificate(cert.getCertString());
+ // String serial_num = cert.getSerialNumber();
+ // String subject_name = cert.getSubjectName();
+ // if (!ser_num.equals(serial_num))
+ // {
+ // ConnectorException se = new ConnectorException(303, "Serialnumber of
+ // certificate and tag X509SerialNumber differs!");
+ // throw se;
+ // }
+ // //sigObj.setSignationName(subject_name);
+ // }
+ // }
+
+ // extract Signature Id's
+ String[] ids = new String[5];
+ ids[0] = extractId(xmlResponse, "signature-"); //$NON-NLS-1$
+ ids[1] = extractId(xmlResponse, "signed-data-reference-"); //$NON-NLS-1$
+ ids[2] = extractId(xmlResponse, "signed-data-object-"); //$NON-NLS-1$
+ ids[3] = extractId(xmlResponse, "etsi-data-reference-"); //$NON-NLS-1$
+ ids[4] = extractId(xmlResponse, "etsi-data-object-"); //$NON-NLS-1$
+
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ SignSignatureObject so = new SignSignatureObject();
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+ String final_ids = id_formatter.formatIds(ids, algs);
+ so.id = final_ids;
+
+ return so;
+ }
+
+ /**
+ * Removes all whitespaces ("\\s") from the String.
+ *
+ * @param str
+ * The String.
+ * @return The String with all whitespaces removed.
+ */
+ public static String removeAllWhitespace(String str)
+ {
+ return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * This emthod extracts id-values from a text. The id is given by the name.
+ *
+ * @param text
+ * the id-value that should extract from
+ * @param name
+ * the id-key
+ * @return the value of the given key in the text
+ */
+ private static String extractId(String text, String name)
+ {
+ String id = null;
+ // fatal bug; fixed by tknall (start)
+ int startOfName = text.indexOf(name);
+ if (startOfName == -1) {
+ log.debug("No id for name \"" + name + "\" extracted. Probably detached signature. Returning empty id: \"\""); //$NON-NLS-1$
+ return "";
+ }
+ // stop
+
+ int start_idx = startOfName + name.length();
+ int end_idx = text.indexOf("\"", start_idx); //$NON-NLS-1$
+
+ final int quot_end_idx = end_idx;
+ final int squot_end_idx = text.indexOf("'", start_idx); //$NON-NLS-1$
+ end_idx = Math.min(quot_end_idx, squot_end_idx);
+ id = text.substring(start_idx, end_idx);
+ if (log.isDebugEnabled())
+ {
+ log.debug("extract id:" + name + id); //$NON-NLS-1$
+ }
+ return id;
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the BKU-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ public static SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ log.debug("parseVerifyXMLResponse:"); //$NON-NLS-1$
+
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>"); //$NON-NLS-1$
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>"); //$NON-NLS-1$
+
+ Pattern sig_chk_p_s = Pattern.compile("<[\\w]*:?SignatureCheck>"); //$NON-NLS-1$
+ Pattern sig_chk_p_e = Pattern.compile("</[\\w]*:?SignatureCheck>"); //$NON-NLS-1$
+ Pattern man_chk_p_s = Pattern.compile("<[\\w]*:?SignatureManifestCheck>"); //$NON-NLS-1$
+ Pattern man_chk_p_e = Pattern.compile("</[\\w]*:?SignatureManifestCheck>"); //$NON-NLS-1$
+ Pattern cer_chk_p_s = Pattern.compile("<[\\w]*:?CertificateCheck>"); //$NON-NLS-1$
+ Pattern cer_chk_p_e = Pattern.compile("</[\\w]*:?CertificateCheck>"); //$NON-NLS-1$
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<[\\w]*:?QualifiedCertificate/>"); //$NON-NLS-1$
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern code_p_s = Pattern.compile("<[\\w]*:?Code>"); //$NON-NLS-1$
+ Pattern code_p_e = Pattern.compile("</[\\w]*:?Code>"); //$NON-NLS-1$
+ Pattern info_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$
+ Pattern info_p_e = Pattern.compile("</[\\w]*:?Info>"); //$NON-NLS-1$
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>"); //$NON-NLS-1$
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>"); //$NON-NLS-1$
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ Pattern hash_data_p_s = Pattern.compile("<HashInputData PartOf=\"SignedInfo\">"); //$NON-NLS-1$
+ Pattern hash_data_p_e = Pattern.compile("</HashInputData>"); //$NON-NLS-1$
+ Matcher hash_data_m_s = hash_data_p_s.matcher(xmlResponse);
+ Matcher hash_data_m_e = hash_data_p_e.matcher(xmlResponse);
+
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // public authority (tknall)
+ Pattern publicAuthority_p = Pattern.compile("<PublicAuthority/>");
+ Matcher publicAuthority_m = publicAuthority_p.matcher(xmlResponse);
+ sig_res.setPublicAuthority(false);
+ sig_res.setPublicAuthorityCode(null);
+ if (publicAuthority_m.find()) {
+ sig_res.setPublicAuthority(true);
+ } else {
+ Matcher publicAuthority_m_s = Pattern.compile("<PublicAuthority>").matcher(xmlResponse);
+ Matcher publicAuthority_m_e = Pattern.compile("</PublicAuthority>").matcher(xmlResponse);
+ if (publicAuthority_m_s.find() && publicAuthority_m_e.find()) {
+ sig_res.setPublicAuthority(true);
+ String codePart = xmlResponse.substring(publicAuthority_m_s.end(), publicAuthority_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(codePart);
+ Matcher code_m_e = code_p_e.matcher(codePart);
+ if (code_m_s.find() && code_m_e.find()) {
+ String code = codePart.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setPublicAuthorityCode(code);
+ }
+ }
+ }
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ if (hash_data_m_s.find() && hash_data_m_e.find())
+ {
+ String hashInputData = xmlResponse.substring(hash_data_m_s.end(), hash_data_m_e.start());
+
+ Pattern b64_p_s = Pattern.compile("<Base64Content>"); //$NON-NLS-1$
+ Pattern b64_p_e = Pattern.compile("</Base64Content>"); //$NON-NLS-1$
+ Matcher b64_m_s = b64_p_s.matcher(hashInputData);
+ Matcher b64_m_e = b64_p_e.matcher(hashInputData);
+
+ boolean hashInputDataFound = b64_m_s.find() && b64_m_e.find();
+
+ String b64 = hashInputDataFound ? hashInputData.substring(b64_m_s.end(), b64_m_e.start()) : "";
+
+ sig_res.setHashInputData(b64);
+ }
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ Matcher info_m_s = info_p_s.matcher(sig_chk);
+ Matcher info_m_e = info_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = sig_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureCheckInfo(info);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ Matcher info_m_s = info_p_s.matcher(man_chk);
+ Matcher info_m_e = info_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = man_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureManifestCheckInfo(info);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ Matcher info_m_s = info_p_s.matcher(cer_chk);
+ Matcher info_m_e = info_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = cer_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setCertificateCheckInfo(info);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ log.debug("parseVerifyXMLResponse finished."); //$NON-NLS-1$
+ return sig_res;
+ }
+
+ public static String formDateTimeElement(Date verificationTime)
+ {
+ return formDateTimeElement(verificationTime, null);
+ }
+
+ public static String formDateTimeElement(Date verificationTime, String namespace)
+ {
+ String nsPrefix = StringUtils.isBlank(namespace) ? "" : (namespace + ":");
+
+ String dateTimeElement = "";
+ if (verificationTime != null)
+ {
+ log.debug("VerificationTime = " + verificationTime);
+
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String dateTime = df.format(verificationTime) + "Z";
+ log.debug("DateTime (VerificationTime in UTC) = " + dateTime);
+
+ dateTimeElement = "<" + nsPrefix + "DateTime>" + dateTime + "</" + nsPrefix + "DateTime>";
+ };
+ return dateTimeElement;
+ }
+
+ public static String getBKUIdentifier(Properties parsedResponseProperties) {
+
+ // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
+ String bkuServerHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
+
+ // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
+ String bkuUserAgentHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
+
+ String bkuSignatureLayout = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY);
+
+ return getBKUIdentifier(bkuServerHeader, bkuUserAgentHeader, bkuSignatureLayout);
+ }
+
+ public static String getBKUIdentifier(String bkuServerHeader, String bkuUserAgentHeader, String bkuSignatureLayout) {
+
+ log.debug("BKU response header \"user-agent\": " + bkuUserAgentHeader);
+ log.debug("BKU response header \"server\": " + bkuServerHeader);
+ log.trace("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\": " + bkuSignatureLayout);
+
+ String result = null;
+
+ if (bkuServerHeader != null) {
+ result = bkuServerHeader;
+ } else if (bkuUserAgentHeader != null) {
+ result = bkuUserAgentHeader;
+ } else {
+ log.warn("Unable to find any BKU identifier (neither header value \"user-agent\" nor \"server\".)");
+ }
+
+ if (bkuSignatureLayout != null && result != null) {
+ log.debug("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\" found.");
+ String signatureLayoutData = " " + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "/" + bkuSignatureLayout;
+ if (!result.endsWith(signatureLayoutData)) {
+ log.debug("Appending signature layout value \"" + bkuSignatureLayout + "\" to bku identifier.");
+ result += signatureLayoutData;
+ } else {
+ log.debug("Signature layout already encoded in server/user-agent header.");
+ }
+ }
+
+ if (result != null) {
+ log.debug("Returning BKU identifier \"" + result + "\"");
+ } else {
+ log.debug("Returning null BKU identifier.");
+ }
+
+ return result;
+ }
+
+ public static String getBKUIdentifier(LocalBKUParams bkuParams) {
+ return getBKUIdentifier(bkuParams.getServer(), bkuParams.getUserAgent(), bkuParams.getSignatureLayout());
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
new file mode 100644
index 0000000..04b817f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
@@ -0,0 +1,179 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+
+/**
+ * Helper class with methods that use the Apache Https Client to send HTTP
+ * requests.
+ *
+ * @author wprinz
+ */
+public final class BKUPostConnection
+{
+ /**
+ * The response Properties key that identifies the response string.
+ */
+ public static final String RESPONSE_STRING_KEY = "response_string"; //$NON-NLS-1$
+
+ /**
+ * The response Properties key that identifies the BKU Server header.
+ */
+ public static final String BKU_SERVER_HEADER_KEY = "BKU-Server-Header"; //$NON-NLS-1$
+
+ /**
+ * The response property that declares the signature layout being applied.
+ */
+ public static final String BKU_SIGNATURE_LAYOUT_HEADER_KEY = "BKU-Signature-Layout"; //$NON-NLS-1$
+
+ /**
+ * The response Properties key that identifies the BKU User-Agent header.
+ */
+ public static final String BKU_USER_AGENT_HEADER_KEY = "BKU-User-Agent-Header"; //$NON-NLS-1$
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(BKUPostConnection.class);
+
+ /**
+ * Sends a multipart/form-data HTTP Post request to the given URL.
+ *
+ * @param url The url the request is directed to.
+ * @param request The request XML, which will be the UTF-8 text/xml first part of the message.
+ * @param data The binary second part of the message.
+ * @return Returns the response properties which, among others, contain the response String.
+ * @throws HttpException
+ * @throws IOException
+ */
+ public static Properties doPostRequestMultipart(String url, String request,
+ final SignatureData data) throws HttpException, IOException
+ {
+ log.debug("doPostRequestMultipart:"); //$NON-NLS-1$
+
+ StringPart xmlpart = new StringPart("XMLRequest", request, "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
+
+ // TODO this is a BUG in BKU that doesn't allow the Content-Type header
+ xmlpart.setContentType(null);
+ xmlpart.setTransferEncoding(null);
+ // BKU 2.7.4 can't handle the Content-Type Header for the XML
+ // xmlpart.setContentType("text/xml");
+ // xmlpart.setTransferEncoding(null);
+
+ final String filename = data.getMimeType().equals("application/pdf") ? "myfile.pdf" : "myfile.txt"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ PartSource ps = new PartSource() {
+ public InputStream createInputStream() throws IOException
+ {
+ return data.getDataSource().createInputStream();
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public long getLength()
+ {
+ return data.getDataSource().getLength();
+ }
+ };
+ //ByteArrayPartSource baps = new ByteArrayPartSource(filename, data.getData());
+ FilePart filepart = new FilePart("fileupload", ps); //$NON-NLS-1$
+ filepart.setContentType(data.getMimeType());
+
+ // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+ // digest calculation, so neither content type nor charset is relevant
+ filepart.setCharSet(data.getCharacterEncoding());
+
+ Part[] parts = { xmlpart, filepart };
+
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8"); //$NON-NLS-1$
+
+ PostMethod post_method = new PostMethod(url);
+ post_method.setParams(method_params);
+
+ MultipartRequestEntity mprqe = new MultipartRequestEntity(parts, post_method.getParams());
+ post_method.setRequestEntity(mprqe);
+
+ HttpClient http_client = new HttpClient();
+
+ int method_response = http_client.executeMethod(post_method);
+ log.debug("method_response = " + method_response); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+
+ if (log.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ log.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ Header server_header = post_method.getResponseHeader("Server"); //$NON-NLS-1$
+ if (server_header != null) {
+ response_properties.setProperty(BKU_SERVER_HEADER_KEY, server_header.getValue());
+ } else {
+ log.warn("BKU response header \"Server\" is empty.");
+ }
+
+ Header signatureLayoutHeader = post_method.getResponseHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT); //$NON-NLS-1$
+ if (signatureLayoutHeader != null) {
+ response_properties.setProperty(BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayoutHeader.getValue());
+ }
+
+ String responseCharSet = post_method.getResponseCharSet();
+ if (!"UTF8".equalsIgnoreCase(responseCharSet) && !"UTF-8".equalsIgnoreCase(responseCharSet)) {
+ log.warn("BKU response charset is not UTF-8!"); //$NON-NLS-1$
+ }
+ String response_string = post_method.getResponseBodyAsString();
+
+ response_properties.setProperty(RESPONSE_STRING_KEY, response_string);
+
+ log.debug("doPostRequestMultipart finished."); //$NON-NLS-1$
+
+ return response_properties;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
new file mode 100644
index 0000000..a8de41e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
@@ -0,0 +1,823 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.DetachedLocRefMOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connects to the BKU using the detached multipart/formdata requests.
+ *
+ * <p>
+ * This feature is available since BKU version 2.7.4.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class DetachedBKUConnector implements Connector, LocalConnector
+{
+//23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedBKUConnector.class);
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param connectorParameters
+ * The connectot parameters.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public DetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), loc_ref_content);
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String mime_type = data.getMimeType();
+ String loc_ref_content = this.environment.getLocRefContent();
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_keybox_identifier); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ log.debug("loc_ref_content = " + loc_ref_content); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+
+ log.debug("sign_request_xml = " + sign_request_xml);
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: " + (bkuIdentifier != null ? ("\"" + bkuIdentifier + "\"") : "n/a"));
+
+ SignatureLayoutHandler sigLayout;
+ try {
+ sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
+ } catch (SettingsException e) {
+ throw new ConnectorException(e.getErrorCode(), e.getMessage());
+ }
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment);
+
+ so.response_properties = response_properties;
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ 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 (log.isDebugEnabled())
+ {
+ for (int id_idx = 0; id_idx < real_ids.length; id_idx++)
+ {
+ log.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]);
+ }
+ }
+
+ return real_ids;
+ }
+
+ /**
+ * Sends the request and data to the given URL.
+ *
+ * <p>
+ * This method mainly handles communication exceptions. The actual send work
+ * is done by doPostRequestMultipart.
+ * </p>
+ *
+ * @see BKUPostConnection#doPostRequestMultipart(String, String,
+ * SignatureData)
+ *
+ * @param url
+ * The URL to send the request to.
+ * @param request_string
+ * The request XML.
+ * @param data
+ * The data.
+ * @return Returns the response properties containing among others the
+ * response XML.
+ * @throws ConnectorException
+ * f.e.
+ */
+ protected Properties sendRequest(String url, String request_string,
+ SignatureData data) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ ConnectorException se = new ConnectorException(320, e);
+ throw se;
+ }
+ }
+
+ /**
+ * Performs a sign.
+ *
+ * @param data
+ * The data to be signed.
+ * @return Returns the signature object containing the signature data.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml, data);
+
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * Performs a verification.
+ *
+ * @param data
+ * The data to be verified.
+ * @param so
+ * The signature object with the signature information.
+ * @return Returns the SignatureResponse with the result of the verification.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ // TODO debug - remove
+ // try
+ // {
+ // FileOutputStream fos = new
+ // FileOutputStream("C:\\wprinz\\Filer\\egiz2\\verify_request.utf8.xml");
+ // //$NON-NLS-1$
+ // fos.write(verify_request_xml.getBytes("UTF-8")); //$NON-NLS-1$
+ // fos.close();
+ // }
+ // catch (Exception e)
+ // {
+ // log.error(e);
+ // }
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, verify_request_xml, data);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl"));
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ // MOA
+ if (SigKZIDHelper.isMOASigned(so))
+ {
+ log.debug("The signature is MOA signed -> getting XML content from DetachedLocRefMOA connector.");
+ DetachedLocRefMOAConnector moa_conn = new DetachedLocRefMOAConnector(this.environment.getProfile(), "loc ref not needed here");
+ return moa_conn.prepareXMLContent(data, so);
+
+ // MOCCA
+ } else if (SigKZIDHelper.isMOCCASigned(so)) {
+ log.debug("MOCCA signature detected.");
+ String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
+ log.debug("Algorithm = " + algorithmId);
+ LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
+ return mocca_connector.prepareXMLContent(data, so);
+
+ // ATRUST
+ } else if (SigKZIDHelper.isATrustSigned(so)) {
+ log.debug("ATrust signature detected");
+ MOASoapWithAttachmentConnector moaConn = new MOASoapWithAttachmentConnector(this.params);
+ moaConn.reInitVerifyTemplate(MOASoapWithAttachmentConnector.ATRUST_VERIFY_TEMPLATE_KEY);
+ return moaConn.prepareXMLContent(data, so);
+ }
+ // TD
+ else if (SigKZIDHelper.isBKUSigned(so)) {
+ log.debug("TD signature signature detected.");
+ return prepareXMLContent(data, so);
+ }
+ // unknown
+ else {
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+ }
+ }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ String ids_string = so.getSigID();
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ // SIG id replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_REF_REPLACE, ids[1]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_REF_REPLACE, ids[3]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_OBJ_URI_REPLACE, ids[2]);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "bku.sign.KeyboxIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "bku.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$
+
+ /**
+ * BKU template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/bku.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "bku.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String loc_ref_content = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String loc_ref_content) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.loc_ref_content = loc_ref_content;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ // when first load failed (the template file does'nt exist), load it from default template file
+ if(this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ // verify
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if(this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if(this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the LocRef content.
+ *
+ * @return Returns the LocRef content.
+ */
+ public String getLocRefContent()
+ {
+ return this.loc_ref_content;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier()
+ {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java
new file mode 100644
index 0000000..170cc45
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java
@@ -0,0 +1,666 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.UnsupportedEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.EnvelopingBase64MOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class EnvelopedBase64BKUConnector implements Connector, LocalConnector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(EnvelopedBase64BKUConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * <p>
+ * This is the new "hotfix" base64 connector.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public EnvelopedBase64BKUConnector(String profile) throws ConnectorException
+ {
+ this.environment = new Environment(profile);
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "BKU_EnvB64_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "BKU_EnvB64_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+// DebugHelper.debugStringToFile(verify_request_xml, "BKU_EnvB64_verify_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, verify_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "BKU_EnvB64_verify_response.xml"); //$NON-NLS-1$
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+// /**
+// * This emthod extracts id-values from a text. The id is given by the name.
+// *
+// * @param text
+// * the id-value that should extract from
+// * @param name
+// * the id-key
+// * @return the value of the given key in the text
+// */
+// private String extractId(String text, String name)
+// {
+// String id = null;
+// int start_idx = text.indexOf(name) + name.length();
+// int end_idx = text.indexOf("\"", start_idx);
+//
+// // TODO hotfix!
+// final int quot_end_idx = end_idx;
+// final int squot_end_idx = text.indexOf("'", start_idx);
+// end_idx = Math.min(quot_end_idx, squot_end_idx);
+// // TODO hotfix end!
+//
+// id = text.substring(start_idx, end_idx);
+// if (log.isDebugEnabled())
+// {
+// log.debug("extract id:" + name + id);
+// }
+// return id;
+// }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+ String ids_string = so.getSigID();
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value = BKUHelper.prepareEnvelopingData(data);
+ {
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ // SIG id replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_REF_REPLACE, ids[1]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_REF_REPLACE, ids[3]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_OBJ_URI_REPLACE, ids[2]);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Base64 content replace
+ String base64 = CodingHelper.encodeBase64(data_value);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+
+ // Signed Properties hash
+ {
+ String sig_prop_hash = computeSignedPropertiesReplace(verify_xml, algSuite);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ protected String computeSignedPropertiesReplace(String verify_xml, AlgorithmSuiteObject algSuite)
+ {
+ try
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ return sig_prop_hash;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very Strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequest:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String base64 = BKUHelper.prepareBase64Content(data);
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareSignRequest finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+
+// log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (SigKZIDHelper.isMOASigned(so))
+ {
+ log.debug("The signature is MOA signed -> getting XML content from Base64MOA connector.");
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(this.environment.getProfile());
+ EnvelopingBase64MOAConnector moa_conn = new EnvelopingBase64MOAConnector(cp);
+ return moa_conn.prepareXMLContent(data, so);
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+/**
+ * Sends the request to the given URL.
+ *
+ * @param url
+ * The URL.
+ * @param request_string
+ * The request string.
+ * @return Returns the response string.
+ * @throws ConnectorException
+ * F.e.
+ */
+ protected Properties sendRequest(String url, String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = at.knowcenter.wag.egov.egiz.sig.connectors.BKUPostConnection.doPostRequest(url, request_string);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(320, e);
+ }
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
+
+ SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "bku.sign.KeyboxIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "bku.sign.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "bku.verify.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile) throws ConnectorException
+ {
+ this.profile = profile;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ String sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ log.debug("Verify request template filename = " + verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ log.debug("Verify request template = " + this.verify_request_template);
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier()
+ {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, false);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
new file mode 100644
index 0000000..c5e1513
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
@@ -0,0 +1,46 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class LocRefDetachedBKUConnector extends DetachedBKUConnector
+{
+
+ /**
+ * @param connectorParameters
+ * @param loc_ref_content
+ * @throws ConnectorException
+ */
+ public LocRefDetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
+ {
+ super(connectorParameters, loc_ref_content);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
new file mode 100644
index 0000000..cfaa55d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class MultipartDetachedBKUConnector extends DetachedBKUConnector
+{
+ protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
+
+ public MultipartDetachedBKUConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ super(connectorParameters, MULTIPART_LOC_REF_CONTENT);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java
new file mode 100644
index 0000000..58bdec6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java
@@ -0,0 +1,135 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ *
+ * <p>
+ * This is the old base64 connector. The difference is in the way the sign
+ * response is parsed and the verify content_xml.
+ * </p>
+ *
+ * @author wprinz
+ *
+ */
+public class OldEnvelopingBase64BKUConnector extends EnvelopedBase64BKUConnector
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(OldEnvelopingBase64BKUConnector.class);
+
+ // TODO implement signing - with old pre 2.7.2 BKUs... not really necessary
+ // though because this connector is only used for verification
+
+ public OldEnvelopingBase64BKUConnector(String profile) throws ConnectorException
+ {
+ super(profile);
+
+ this.environment = new OverriddenEnvironment(profile);
+ }
+
+
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector#computeSignedPropertiesReplace(java.lang.String)
+ */
+ protected String computeSignedPropertiesReplace(String verify_xml, AlgorithmSuiteObject algSuite)
+ {
+ try
+ {
+ final String ETSI_QUALIFYING_PROPERTIES_START_TAG = "<etsi:QualifyingProperties"; //$NON-NLS-1$
+ final String ETSI_QUALIFYING_PROPERTIES_END_TAG = "</etsi:QualifyingProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_QUALIFYING_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_QUALIFYING_PROPERTIES_END_TAG, hash_start) + ETSI_QUALIFYING_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_QUALIFYING_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:QualifyingProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ return sig_prop_hash;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very Strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+
+
+
+ public static class OverriddenEnvironment extends EnvelopedBase64BKUConnector.Environment
+ {
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.base64old"; //$NON-NLS-1$
+
+ public OverriddenEnvironment(String profile) throws ConnectorException
+ {
+ super(profile);
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, e);
+ }
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java
new file mode 100644
index 0000000..72f181e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java
@@ -0,0 +1,272 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.Serializable;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.AlgorithmSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.ConnectorSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation;
+
+/**
+ * @author wprinz
+ *
+ */
+public class SignSignatureObject implements Serializable, MandatorySignatureInformation, ConnectorSignatureInformation, AlgorithmSignatureInformation, AdditionalSignatureInformation
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -2689261480444802213L;
+
+ public String date = null;
+ public String issuer = null;
+ public String signatureValue = null;
+
+ public String id = null;
+ public String kz = null;
+
+ public String sigAlgorithm;
+
+ public String sigTimeStamp;
+
+ /**
+ * This is used to transport the response properties to the Detached signator.
+ */
+ public Properties response_properties = null;
+
+ /**
+ * The X509Certificate.
+ *
+ * <p>
+ * This also provides the serial number and name.
+ * </p>
+ */
+ public X509Certificate x509Certificate = null;
+
+ // dferbas
+ public Map subjectDNMap = new HashMap();
+ public Map issuerDNMap = new HashMap();
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getDate()
+ */
+ public String getDate()
+ {
+ return this.date;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getIssuer()
+ */
+ public String getIssuer()
+ {
+ return this.issuer;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getSerialNumber()
+ */
+ public String getSerialNumber()
+ {
+ return this.x509Certificate.getSerialNumber().toString();
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getSignatureValue()
+ */
+ public String getSignatureValue()
+ {
+ return this.signatureValue;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.ConnectorSignatureInformation#getSigID()
+ */
+ public String getSigID()
+ {
+ return this.id;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AlgorithmSignatureInformation#getSigKZ()
+ */
+ public String getSigKZ()
+ {
+ return this.kz;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation#getName()
+ */
+ public String getName()
+ {
+ return this.x509Certificate.getSubjectDN().toString();
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation#getX509Certificate()
+ */
+ public X509Certificate getX509Certificate()
+ {
+ return this.x509Certificate;
+ }
+
+ public String getSigAlgorithm() {
+ return this.sigAlgorithm;
+ }
+
+ public String retrieveStringValue(String sigKey)
+ {
+ // mandatory
+ if (sigKey.equals(SignatureTypes.SIG_DATE))
+ {
+ return getDate();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_VALUE))
+ {
+ return getSignatureValue();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_ISSUER))
+ {
+ return getIssuer();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_NUMBER))
+ {
+ return getSerialNumber();
+ }
+
+ // connector
+ if (sigKey.equals(SignatureTypes.SIG_ID))
+ {
+ return getSigID();
+ }
+
+ // algorithm
+ if (sigKey.equals(SignatureTypes.SIG_KZ))
+ {
+ return getSigKZ();
+ }
+
+ // additional
+ if (sigKey.equals(SignatureTypes.SIG_NAME))
+ {
+ return getName();
+ }
+
+ if (sigKey.equals(SignatureTypes.SIG_SUBJECT))
+ {
+ return getName();
+ }
+
+ if (sigKey.equals(SignatureTypes.SIG_ALG)) {
+ return getSigAlgorithm();
+ }
+
+ throw new RuntimeException("The key '" + sigKey + "' is not a recognized SignatorObject member."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // dferbas
+
+
+ /**
+ * Get a timestamp if available as b64 string
+ * @see TimeStamper
+ * @return
+ */
+ public String getSigTimeStamp() {
+ return this.sigTimeStamp;
+ }
+
+ public Map getSubjectDNMap() {
+ if (this.subjectDNMap.size() == 0 && this.getX509Certificate() != null) {
+ //rpiazzi workaround
+ //the problem with atrust encoding special characters (Sonderzeichen) wrong
+ //led to this workaround. As special characters are of the form e.g. "&#xxx;"
+ //Example: for "Georg Müller" atrust returns "Georg M&#252;ller"
+ //By calling this.getX509Certificate().getSubjectDN().getName() you get "Georg M&#252\;ller",
+ //After that the down called method fillDNMap replaces the "\" with a "+"
+ //Because of this the workaround in at.gv.egiz.pdfas.impl.signator.binary.BinarySignator_1_0_0.fillReplacesWithValues()
+ //which replaces the wrong codes of atrust with the special chars does not work
+ //------------------------------------------------------------------------------
+ //The workaround here is to call this.getX509Certificate().getSubjectDN.toString()
+ //instead of this.getX509Certificate().getSubjectDN.getName()
+ if (this.getX509Certificate().getSubjectDN().toString().contains(";") ||
+ this.getX509Certificate().getSubjectDN().toString().contains("#") ||
+ this.getX509Certificate().getSubjectDN().toString().contains("&")) {
+ fillDNMap(this.getX509Certificate().getSubjectDN().toString(), this.subjectDNMap);
+ }
+ else {
+ fillDNMap(this.getX509Certificate().getSubjectDN().getName(), this.subjectDNMap);
+ }
+ //end workaround
+ }
+ return this.subjectDNMap;
+ }
+
+ public String certSubjectDNPart(String key) {
+ return (String)this.getSubjectDNMap().get(key);
+ }
+
+ public Map getIssuerDNMap() {
+ if (this.issuerDNMap.size() == 0 && this.getX509Certificate() != null) {
+ fillDNMap(this.getX509Certificate().getIssuerDN().getName(), this.issuerDNMap);
+ }
+ return this.issuerDNMap;
+ }
+
+ public String certIssuerDNPart(String key) {
+ return (String)this.getIssuerDNMap().get(key);
+ }
+
+ private void fillDNMap(String dn, Map dnMap) {
+
+ // split at "," but not at "\,"
+ String[] arr = dn.split("\\s*(?<![\\\\]),\\s*");
+
+ for (int i = 0; i < arr.length; i++) {
+ String[] entry = arr[i].split("\\s*(=)\\s*");
+
+ // resolve escaped values according to RFC2253
+ entry[1] = entry[1].replaceAll("\\\\,", ","); // \, -> ,
+ entry[1] = entry[1].replaceAll("\\\\+", "+"); // \+ -> +
+ entry[1] = entry[1].replaceAll("\\\\\"", "\""); // \" -> "
+ entry[1] = entry[1].replaceAll("\\\\\\\\", "\\"); // \\ -> \
+ entry[1] = entry[1].replaceAll("\\\\<,", "<"); // \< -> <
+ entry[1] = entry[1].replaceAll("\\\\>", ">"); // \> -> >
+ entry[1] = entry[1].replaceAll("\\\\;", ";"); // \; -> ;
+ entry[1] = entry[1].replaceAll("\\\\#", "#"); // \# -> #
+
+ dnMap.put(entry[0], entry[1]);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java
new file mode 100644
index 0000000..4eb6e39
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java
@@ -0,0 +1,76 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+//package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+//
+//import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+//import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+//
+///**
+// * @author wprinz
+// *
+// */
+//public abstract class SignSignatureObjectHelper
+//{
+// public static String retrieveStringValueFromSignatureObject (SignSignatureObject so, String key)
+// {
+// // mandatory
+// if (key.equals(SignatureTypes.SIG_DATE))
+// {
+// return so.getDate();
+// }
+// if (key.equals(SignatureTypes.SIG_VALUE))
+// {
+// return so.getSignatureValue();
+// }
+// if (key.equals(SignatureTypes.SIG_ISSUER))
+// {
+// return so.getIssuer();
+// }
+// if (key.equals(SignatureTypes.SIG_NUMBER))
+// {
+// return so.getSerialNumber();
+// }
+//
+// // connector
+// if (key.equals(SignatureTypes.SIG_ID))
+// {
+// return so.getSigID();
+// }
+//
+// // algorithm
+// if (key.equals(SignatureTypes.SIG_KZ))
+// {
+// return so.getSigKZ();
+// }
+//
+// // additional
+// if (key.equals(SignatureTypes.SIG_NAME))
+// {
+// return so.getName();
+// }
+//
+// throw new RuntimeException("The key '" + key + "' is not a recognized SignatorObject member."); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+//
+//}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
new file mode 100644
index 0000000..ea90841
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
@@ -0,0 +1,661 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.DetachedBKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ * Connects to MOA providing the Data detached as LocRef on a local resource.
+ *
+ * @author wprinz
+ */
+public class DetachedLocRefMOAConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ /**
+ * The SIG_ID prefix.
+ */
+ // public static final String SIG_ID_PREFIX = "etsi-bku-detached@"; //$NON-NLS-1$
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedLocRefMOAConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws SettingsException
+ * f.e.
+ * @throws SignatureException
+ * f.e.
+ */
+ public DetachedLocRefMOAConnector(String profile, String signature_data_url) throws ConnectorException
+ {
+ this.environment = new Environment(profile, signature_data_url);
+ }
+
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String loc_ref_content = this.environment.getSignatureDataUrl();
+ String mime_type = data.getMimeType();
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_key_identifier); //$NON-NLS-1$
+ log.debug("LocRefContent = " + loc_ref_content); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector#analyzeSignResponse(java.util.Properties)
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "MOA_DetLocRef_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "MOA_DetLocRef_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl());
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ protected Properties sendRequest(String url, String mode, String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * MOA template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moa.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String signature_data_url = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws SettingsException
+ * f.e.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signature_data_url) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.signature_data_url = signature_data_url;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ if (this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if (this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the URL where to load the detached data from.
+ *
+ * @return Returns the URL where to load the detached data from.
+ */
+ public String getSignatureDataUrl()
+ {
+ return this.signature_data_url;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (!SigKZIDHelper.isMOASigned(so))
+ {
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(this.environment.getProfile());
+ DetachedBKUConnector bku_connector = new DetachedBKUConnector(cp, "not needed here");
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java
new file mode 100644
index 0000000..6f2d171
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java
@@ -0,0 +1,638 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.OldEnvelopingBase64BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.OldMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class EnvelopingBase64MOAConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(EnvelopingBase64MOAConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ protected ConnectorParameters params = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public EnvelopingBase64MOAConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(connectorParameters.getProfileId(), connectorParameters.getSignatureKeyIdentifier());
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml);
+
+ log.debug("response_string = " + response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY));; //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ protected Properties sendRequest(String url, String mode,
+ String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequest:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String base64 = BKUHelper.prepareBase64Content(data);
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareSignRequest finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+
+ String returnHashInputDataElement = "";
+ if (this.params.isReturnHashInputData())
+ {
+ returnHashInputDataElement = MOASoapWithAttachmentConnector.RETURN_HASH_INPUT_DATA;
+ }
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement);
+
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime()));
+
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new OldMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value = BKUHelper.prepareEnvelopingData(data);
+ {
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ // Base64 content replace -> do this at last for performance
+ String base64 = CodingHelper.encodeBase64(data_value);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signKeyIdentifier) throws ConnectorException
+ {
+ this.profile = profile;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ if (signKeyIdentifier != null)
+ {
+ this.sign_key_identifier = signKeyIdentifier;
+ }
+ else
+ {
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+ }
+
+ String sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, false);
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (!SigKZIDHelper.isMOASigned(so))
+ {
+ if (SigKZIDHelper.isOldBKU(so))
+ {
+ OldEnvelopingBase64BKUConnector bku_connector = new OldEnvelopingBase64BKUConnector(this.environment.getProfile());
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ else
+ {
+ EnvelopedBase64BKUConnector bku_connector = new EnvelopedBase64BKUConnector(this.environment.getProfile());
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java
new file mode 100644
index 0000000..b52b39b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java
@@ -0,0 +1,152 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class FilePartMR extends
+ org.apache.commons.httpclient.methods.multipart.FilePart {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(FilePartMR.class);
+
+ /** Content dispostion characters */
+ protected static final String CONTENT_ID = "Content-Id: ";
+
+ /** Content dispostion as a byte array */
+ protected static final byte[] CONTENT_ID_BYTES =
+ EncodingUtil.getAsciiBytes(CONTENT_ID);
+
+ private String contentID = "";
+
+ public FilePartMR(String arg0, PartSource arg1) {
+ super(arg0, arg1);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, File arg1) throws FileNotFoundException {
+ super(arg0, arg1);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, String arg1, File arg2)
+ throws FileNotFoundException {
+ super(arg0, arg1, arg2);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, PartSource arg1, String arg2, String arg3) {
+ super(arg0, arg1, arg2, arg3);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, File arg1, String arg2, String arg3)
+ throws FileNotFoundException {
+ super(arg0, arg1, arg2, arg3);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, String arg1, File arg2, String arg3,
+ String arg4) throws FileNotFoundException {
+ super(arg0, arg1, arg2, arg3, arg4);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public void setContentID(String contentid) {
+ this.contentID = contentid;
+ }
+
+ public String getContentID() {
+ return this.contentID;
+ }
+
+ /**
+ * Write the content id header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentIDHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ out.write(CONTENT_ID_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(getContentID()));
+ }
+
+ /**
+ * Write all the data to the output stream.
+ * If you override this method make sure to override
+ * #length() as well
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ public void send(OutputStream out) throws IOException {
+ LOG.trace("enter send(OutputStream out)");
+ sendStart(out);
+
+ sendContentIDHeader(out);
+ sendContentTypeHeader(out);
+ sendTransferEncodingHeader(out);
+ sendEndOfHeader(out);
+ sendData(out);
+ sendEnd(out);
+ }
+
+
+ /**
+ * Return the full length of all the data.
+ * If you override this method make sure to override
+ * #send(OutputStream) as well
+ *
+ * @return long The length.
+ * @throws IOException If an IO problem occurs
+ */
+ public long length() throws IOException {
+ LOG.trace("enter length()");
+ if (lengthOfData() < 0) {
+ return -1;
+ }
+ ByteArrayOutputStream overhead = new ByteArrayOutputStream();
+ sendStart(overhead);
+
+ sendContentIDHeader(overhead);
+ sendContentTypeHeader(overhead);
+ sendTransferEncodingHeader(overhead);
+ sendEndOfHeader(overhead);
+ sendEnd(overhead);
+ return overhead.size() + lengthOfData();
+ }
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java
new file mode 100644
index 0000000..8cb9a92
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java
@@ -0,0 +1,228 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class MOAHelper
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOAHelper.class);
+
+ /**
+ * This method parses the MOA-Response string.
+ *
+ * <p>
+ * It separates the SignatureValue, X509IssuerName, SigningTime,
+ * X509SerialNumber, X509Certificate, CertDigest and DigestValues. If the
+ * X509Certificate is extracted it would be stored in the certificates
+ * directory.
+ * </p>
+ *
+ * @param xmlResponse
+ * the response string from the MOA sign-request
+ * @throws ConnectorException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException
+ {
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+
+ // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+ // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse);
+ // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start()));
+ }
+ log.debug("sig_val = " + sig_val); //$NON-NLS-1$
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num); //$NON-NLS-1$
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$
+
+ // CertDigest
+ // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ // {
+ // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(),
+ // sig_cer_d_m_e.start());
+ // if (dig_val_m_s.find() && dig_val_m_e.find())
+ // {
+ // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ // //sigObj.setX509CertificateDigest(sig_dig);
+ // }
+ // }
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try
+ {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (CertificateException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (IOException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert); //$NON-NLS-1$
+
+ if (log.isDebugEnabled())
+ {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$
+ log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$
+ }
+
+ SignSignatureObject so = new SignSignatureObject();
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+
+
+ so.id = id_formatter.formatIds(null, algs);
+
+ return so;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
new file mode 100644
index 0000000..7aa3d7b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
@@ -0,0 +1,277 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.Vector;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+
+import at.knowcenter.wag.egov.egiz.exceptions.WebException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+
+/**
+ * @author wprinz
+ *
+ */
+public final class MOASoapConnection
+{
+ /**
+ * MOA siganture verification mode
+ */
+ public static final String SERVICE_VERIFY = "SignatureVerification"; //$NON-NLS-1$
+
+ /**
+ * MOA siganture creation mode
+ */
+ public static final String SERVICE_SIGN = "SignatureCreation"; //$NON-NLS-1$
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOASoapConnection.class);
+
+ /**
+ * This method connects the moa server getting the requestString, the given
+ * serviseMode and the endpointUrl. The requestString is the envelope of the
+ * SOAP Message send and recieve by the AXIS module. The Response SOAP message
+ * of the MOA server is parsed by AXIS and the message envelope is send back
+ * to the calling method.
+ *
+ * @param requestString
+ * the request string (XML) to send.
+ * @param serviceMode
+ * the mode which connect to MOA
+ * @param endpointURL
+ * the URL which the MOA server is running
+ * @return the response string (XML) of the MOA server
+ * @throws WebException
+ */
+ public static Properties connectMOA(String requestString, String serviceMode,
+ String endpointURL) throws WebException
+ {
+ try
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug(serviceMode);
+ log.debug(endpointURL);
+ }
+ // Parser/DOMBuilder instanzieren
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ // XML Datei in einen DOM-Baum umwandeln
+ ByteArrayInputStream bais = new ByteArrayInputStream(requestString.getBytes("UTF-8")); //$NON-NLS-1$
+ Document xmlRequest = builder.parse(bais);
+
+ // Call öffnen
+ Call call = null;
+
+ // Neues BodyElement anlegen und mit dem DOM-Baum füllen
+ SOAPBodyElement body = new SOAPBodyElement(xmlRequest.getDocumentElement());
+ SOAPBodyElement[] params = new SOAPBodyElement[] { body };
+
+ // AXIS-Server instanzieren
+ Service service = ServiceFactory.newInstance().createService(new QName(serviceMode));
+ call = service.createCall();
+ call.setTargetEndpointAddress(endpointURL);
+
+ // Call auslösen und die Antworten speichern
+ log.debug("Calling MOA: " + endpointURL); //$NON-NLS-1$
+ Vector responses = (Vector) call.invoke(params);
+
+ // Erstes Body Element auslesen
+ SOAPBodyElement response = (SOAPBodyElement) responses.get(0);
+
+ // Aus der Response den DOM-Baum lesen
+ Document root_response = response.getAsDocument();
+ log.debug("Return from MOA: " + serviceMode); //$NON-NLS-1$
+
+ // XML-Formatierung konfiguieren
+ OutputFormat format = new OutputFormat((Document) root_response);
+ format.setLineSeparator("\n"); //$NON-NLS-1$
+ format.setIndenting(false);
+ format.setPreserveSpace(true);
+ format.setOmitXMLDeclaration(false);
+ format.setEncoding("UTF-8"); //$NON-NLS-1$
+
+ // Ausgabe der Webservice-Antwort auf die Konsole
+ // XMLSerializer conSerializer = new XMLSerializer(System.out, format);
+ // conSerializer.serialize(root_response);
+
+ // Ausgabe der Webservice-Antwort in Datei
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer response_serializer = new XMLSerializer(baos, format);
+ response_serializer.serialize(root_response);
+ String response_string = baos.toString("UTF-8"); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, response_string);
+
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new WebException(e);
+ }
+ // serialize signature only
+
+ // if
+ // (root_response.getDocumentElement().getLocalName().equals("CreateXMLSignatureResponse"))
+ // {
+ // Element signature = (Element)
+ // root_response.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#",
+ // "Signature").item(0);
+ // String signatureFile = getProperty(mode + "Request").substring(0,
+ // getProperty(mode +
+ // "Request").lastIndexOf('.')) + ".Signature.xml";
+ // fileSerializer = new XMLSerializer(new FileOutputStream(signatureFile),
+ // format);
+ // fileSerializer.serialize(signature);
+ // }
+
+ }
+
+ public static Properties doPostRequestMultipart(String url, String serviceMode, String request,
+ final SignatureData data) throws HttpException, IOException
+ {
+ log.debug("doPostRequestMultipart:"); //$NON-NLS-1$
+
+ // Wrap XMLRequest into SOAP-Body
+ request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body>" +
+ request.substring(request.indexOf("?>")+2)+ // do not forget to eliminate any additional XML-header
+ "</soapenv:Body></soapenv:Envelope>";
+
+ StringPartMR xmlpart = new StringPartMR("test", request, "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
+ xmlpart.setContentType("text/xml");
+ xmlpart.setContentID("<xmlrequest>");
+
+ // add file to be signed
+ final String filename = data.getMimeType().equals("application/pdf") ? "myfile.pdf" : "myfile.txt"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ PartSource ps = new PartSource() {
+ public InputStream createInputStream() throws IOException
+ {
+ return data.getDataSource().createInputStream();
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public long getLength()
+ {
+ return data.getDataSource().getLength();
+ }
+ };
+ //ByteArrayPartSource baps = new ByteArrayPartSource(filename, data.getData());
+ FilePartMR filepart = new FilePartMR("fileupload", ps); //$NON-NLS-1$
+ filepart.setContentType(data.getMimeType());
+ filepart.setContentID("<fileupload>");
+
+ // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+ // digest calculation, so neither content type nor charset is relevant
+ filepart.setCharSet(data.getCharacterEncoding());
+
+ Part[] parts = { xmlpart, filepart };
+
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8"); //$NON-NLS-1$
+
+ PostMethod post_method = new PostMethod(url);
+ post_method.setParams(method_params);
+
+
+ post_method.addRequestHeader("SOAPAction",serviceMode);
+
+// MultipartRequestEntity mprqe = new MultipartRequestEntity(parts, post_method.getParams());
+ MultipartRelatedEntity mprqe = new MultipartRelatedEntity(parts, post_method.getParams());
+ mprqe.setContentType("text/xml");
+ mprqe.setStartID("<xmlrequest>");
+
+ post_method.setRequestEntity(mprqe);
+ // post_method.setRequestHeader("Content-Type", "multipart/related; type=\"text/xml\"; boundary=\""+"\"");
+ HttpClient http_client = new HttpClient();
+
+ int method_response = http_client.executeMethod(post_method);
+ log.debug("method_response = " + method_response); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+
+ if (log.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ log.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ Header server_header = post_method.getResponseHeader("Server"); //$NON-NLS-1$
+
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, server_header.getValue());
+
+ String charset = post_method.getResponseCharSet();
+ log.debug("MOA response charset is \"" + charset + "\"");
+ if (!"UTF-8".equalsIgnoreCase(charset) && !"UTF8".equalsIgnoreCase(charset)) //$NON-NLS-1$
+ {
+ log.warn("MOA response charset is not UTF-8!"); //$NON-NLS-1$
+ }
+ String response_string = post_method.getResponseBodyAsString();
+
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, response_string);
+
+ log.debug("doPostRequestMultipart finished."); //$NON-NLS-1$
+ return response_properties;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
new file mode 100644
index 0000000..db0a04f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
@@ -0,0 +1,745 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.DetachedBKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connects to MOA providing the Data detached as LocRef on a local resource.
+ *
+ * @author wprinz
+ */
+public class MOASoapWithAttachmentConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ public static final String ATRUST_VERIFY_TEMPLATE_KEY = "atrust.verify.template.detached";
+
+/**
+ * The SIG_ID prefix.
+ */
+ // public static final String SIG_ID_PREFIX = "etsi-bku-detached@"; //$NON-NLS-1$
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOASoapWithAttachmentConnector.class);
+
+ protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
+
+ protected static final String RETURN_HASH_INPUT_DATA = "<ReturnHashInputData/>"; //$NON-NLS-1$
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param connectorParameters
+ * The parameters for this connector.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public MOASoapWithAttachmentConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), this.params.getSignatureKeyIdentifier(), MULTIPART_LOC_REF_CONTENT);
+ }
+
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String loc_ref_content = this.environment.getSignatureDataUrl();
+ String mime_type = data.getMimeType();
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_key_identifier); //$NON-NLS-1$
+ log.debug("LocRefContent = " + loc_ref_content); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector#analyzeSignResponse(java.util.Properties)
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "MOA_DetLocRef_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml, data);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "MOA_DetLocRef_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml, data);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl());
+
+ String returnHashInputDataElement = "";
+ if (this.params.isReturnHashInputData())
+ {
+ returnHashInputDataElement = RETURN_HASH_INPUT_DATA;
+ }
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement);
+
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime()));
+
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+
+ // MOA
+ if (SigKZIDHelper.isMOASigned(so)) {
+ log.debug("MOA signature detected.");
+ return prepareXMLContent(data, so);
+
+ // MOCCA
+ } else if (SigKZIDHelper.isMOCCASigned(so)) {
+ log.debug("MOCCA signature detected.");
+ String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
+ log.debug("Algorithm = " + algorithmId);
+ LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
+ return mocca_connector.prepareXMLContent(data, so);
+
+ // ATrust
+ } else if (SigKZIDHelper.isATrustSigned(so)) {
+ log.debug("A-Trust signature detected.");
+ this.environment.reInitVerifyTemplate(ATRUST_VERIFY_TEMPLATE_KEY);
+ return prepareXMLContent(data, so);
+
+ // TD bku
+ } else if (SigKZIDHelper.isBKUSigned(so)) {
+ log.debug("TD bku signature detected.");
+ DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here");
+ return bku_connector.prepareXMLContent(data, so);
+ } else {
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+
+ }
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ String verify_xml = null;
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+
+ protected Properties sendRequest(String url, String mode, String request_string, SignatureData data) throws ConnectorException
+ {
+ try
+ {
+ // for performance measurement
+// long startTime = 0;
+// if (log.isInfoEnabled()) {
+// startTime = System.currentTimeMillis();
+// }
+
+// Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ log.debug("Connecting to " + url);
+ Properties response_properties = MOASoapConnection.doPostRequestMultipart(url,mode, request_string, data );
+
+ // for performance measurement
+// if (log.isInfoEnabled()) {
+// long endTime = System.currentTimeMillis();
+// String toReport = "MOA-PROCESSING;-;-;" + (endTime - startTime) + ";";
+// log.info(toReport);
+// }
+
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException {
+ this.environment.reInitVerifyTemplate(templatePropKey);
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * MOA template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moa.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String signature_data_url = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+
+ public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException {
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, this.profile, templatePropKey);
+ this.verify_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ }
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws SettingsException
+ * f.e.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signKeyIdentifier, String signature_data_url) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.signature_data_url = signature_data_url;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ if (signKeyIdentifier != null)
+ {
+ this.sign_key_identifier = signKeyIdentifier;
+ }
+ else
+ {
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+ }
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ if (this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ }
+
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if (this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the URL where to load the detached data from.
+ *
+ * @return Returns the URL where to load the detached data from.
+ */
+ public String getSignatureDataUrl()
+ {
+ return this.signature_data_url;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java
new file mode 100644
index 0000000..dd9f8b8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java
@@ -0,0 +1,79 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.httpclient.util.EncodingUtil;
+
+public class MultipartRelatedEntity extends MultipartRequestEntity {
+
+ /** The Content-Type for multipart/related. */
+ private static final String MULTIPART_RELATED_CONTENT_TYPE = "multipart/related";
+
+
+ private String startID;
+
+ private String contentType;
+
+ public MultipartRelatedEntity(Part[] parts, HttpMethodParams params) {
+ super(parts, params);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+
+ public String getStartID() {
+ return startID;
+ }
+
+
+ public void setStartID(String startID) {
+ this.startID = startID;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
+ */
+ public String getContentType() {
+ StringBuffer buffer = new StringBuffer(MULTIPART_RELATED_CONTENT_TYPE);
+ buffer.append("; type=\"");
+ buffer.append(EncodingUtil.getAsciiString(this.contentType.getBytes()));
+ buffer.append("\"; start=\"");
+ buffer.append(EncodingUtil.getAsciiString(getStartID().getBytes()));
+ buffer.append("\"; boundary=\"");
+ buffer.append(EncodingUtil.getAsciiString(getMultipartBoundary()));
+ buffer.append("\"");
+ return buffer.toString();
+ }
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java
new file mode 100644
index 0000000..2efcbcc
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java
@@ -0,0 +1,189 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class StringPartMR extends StringPart {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(StringPartMR.class);
+
+
+ /** Content dispostion characters */
+ protected static final String CONTENT_ID = "Content-Id: ";
+
+ /** Content dispostion as a byte array */
+ protected static final byte[] CONTENT_ID_BYTES =
+ EncodingUtil.getAsciiBytes(CONTENT_ID);
+
+ private String contentID = "";
+
+ public StringPartMR(String name, String value, String charset) {
+ super(name, value, charset);
+ // TODO Auto-generated constructor stub
+ }
+
+ public StringPartMR(String name, String value) {
+ super(name, value);
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * Write the content disposition header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendDispositionHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ // Do nothing !
+ }
+
+ /**
+ * Write the content id header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentIDHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ out.write(CONTENT_ID_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(getContentID()));
+ }
+
+
+ /**
+ * Write the content type header to the specified output stream
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentTypeHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContentTypeHeader(OutputStream out)");
+ String contentType = getContentType();
+ if (contentType != null) {
+ out.write(CRLF_BYTES);
+ out.write(CONTENT_TYPE_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(contentType));
+ String charSet = getCharSet();
+ if (charSet != null) {
+ out.write(CHARSET_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(charSet));
+ }
+ }
+ }
+
+ /**
+ * Write the content transfer encoding header to the specified
+ * output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
+ String transferEncoding = getTransferEncoding();
+ if (transferEncoding != null) {
+ out.write(CRLF_BYTES);
+ out.write(CONTENT_TRANSFER_ENCODING_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(transferEncoding));
+ }
+ }
+
+ public void setContentID(String contentid) {
+ this.contentID = contentid;
+ }
+
+ public String getContentID() {
+ return this.contentID;
+ }
+
+ /**
+ * Write the end of the header to the output stream
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendEndOfHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendEndOfHeader(OutputStream out)");
+ out.write(CRLF_BYTES);
+ out.write(CRLF_BYTES);
+ }
+
+
+ /**
+ * Write all the data to the output stream.
+ * If you override this method make sure to override
+ * #length() as well
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ public void send(OutputStream out) throws IOException {
+ LOG.trace("enter send(OutputStream out)");
+ sendStart(out);
+
+ sendContentIDHeader(out);
+ sendContentTypeHeader(out);
+ sendTransferEncodingHeader(out);
+ sendEndOfHeader(out);
+ sendData(out);
+ sendEnd(out);
+ }
+
+
+ /**
+ * Return the full length of all the data.
+ * If you override this method make sure to override
+ * #send(OutputStream) as well
+ *
+ * @return long The length.
+ * @throws IOException If an IO problem occurs
+ */
+ public long length() throws IOException {
+ LOG.trace("enter length()");
+ if (lengthOfData() < 0) {
+ return -1;
+ }
+ ByteArrayOutputStream overhead = new ByteArrayOutputStream();
+ sendStart(overhead);
+
+ sendContentIDHeader(overhead);
+ sendContentTypeHeader(overhead);
+ sendTransferEncodingHeader(overhead);
+ sendEndOfHeader(overhead);
+ sendEnd(overhead);
+ return overhead.size() + lengthOfData();
+ }
+
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java
new file mode 100644
index 0000000..12fc709
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java
@@ -0,0 +1,623 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.mocca;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector for MOCCA.
+ * @author tknall
+ */
+public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ private static Log log = LogFactory.getLog(LocRefDetachedMOCCAConnector.class);
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environment of this connector containing templates.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector according to the
+ * given profile.
+ * @param connectorParameters The connectot parameters.
+ * @throws ConnectorException Thrown in case of error.
+ */
+ public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException {
+ this(connectorParameters, loc_ref_content, null);
+ }
+
+ /**
+ * Constructor that builds the configuration environment for this connector according to the
+ * given profile.
+ * @param connectorParameters The connectot parameters.
+ * @param algorithmId The algorithm idenifier.
+ * @throws ConnectorException Thrown in case of error.
+ */
+ public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content, String algorithmId) throws ConnectorException {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), loc_ref_content, algorithmId);
+ }
+
+ /**
+ * Sends the request to the given URL. This method handles communication exceptions.
+ * The actual send work is done by doPostRequestMultipart.
+ * @see BKUPostConnection#doPostRequestMultipart(String, String, SignatureData)
+ * @param url The URL to send the request to.
+ * @param request_string The request XML.
+ * @param data The data.
+ * @return Returns the response properties containing among others the response XML.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ protected Properties sendRequest(String url, String request_string, SignatureData data) throws ConnectorException {
+ try {
+ Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data);
+ return response_properties;
+ } catch (Exception e) {
+ ConnectorException se = new ConnectorException(320, e);
+ throw se;
+ }
+ }
+
+ /**
+ * Starts a signature process.
+ * @param data The data to be signed.
+ * @return Returns the signature object containing the signed data.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException {
+ log.debug("doSign:");
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml);
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml, data);
+
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished.");
+ return sso;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * This method analyzes a signature response of the signature device.
+ * @param response_properties The response elements of the signature device.
+ * @return The parsed signed signature object.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException {
+ log.debug("analyzeSignResponse:");
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
+ SignatureLayoutHandler sigLayout;
+ try {
+ sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
+ } catch (SettingsException e) {
+ throw new ConnectorException(e.getErrorCode(), e.getMessage());
+ }
+
+ BKUHelper.checkResponseForError(response_string);
+
+// SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter());
+ SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment);
+ so.response_properties = response_properties;
+ log.debug("analyzeSignResponse finished.");
+ return so;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * Prepares the signature request xml to be sent using the sign request template.
+ * @param data The signature data.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException {
+ log.debug("prepareSignRequestDetached:");
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String mime_type = data.getMimeType();
+ String loc_ref_content = this.environment.getLocRefContent();
+
+ if (log.isDebugEnabled()) {
+ log.debug("sign keybox identifier = " + sign_keybox_identifier);
+ log.debug("mime type = " + mime_type);
+ log.debug("loc_ref_content = " + loc_ref_content);
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+
+ log.debug("sign_request_xml = " + sign_request_xml);
+ log.debug("prepareSignRequestDetached finished.");
+ return sign_request_xml;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * Prepares the xml content of a signature creation request including the link to the signature data.
+ * @param data The signature data.
+ * @param so The signature object containing the signature information.
+ * @return Returns the xml content.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ log.debug("prepareXMLContent:");
+ try {
+
+ String ids_string = so.getSigID();
+ String sigId = this.parseSigId(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ // template replacements
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, sigId);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ Pattern spPattern = Pattern.compile("(<(\\w+:)?SignedProperties.*>.*</(\\w+:)?SignedProperties>)");
+ Matcher matcher = spPattern.matcher(verify_xml);
+ if (matcher.find()) {
+ log.debug("SignedProperties found.");
+ String string_to_be_hashed = matcher.group(1);
+ log.debug("SignedProperties string to be hashed: " + string_to_be_hashed);
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8");
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished.");
+ return verify_xml;
+ } catch (Exception e) {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment {
+
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "moc.sign.KeyboxIdentifier";
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moc.sign.request.detached";
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moc.sign.url";
+
+ /**
+ * BKU template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moc.";
+
+ /**
+ * signing file template suffix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFFIX = ".sign.request.xml";
+
+ /**
+ * verifing template file suffix
+ */
+ /* signature verification is not supported by mocca
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+ */
+
+ /**
+ * verifing file template key suffix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ /* signature verification is not supported by mocca
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moc.verify.request.detached";
+ */
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moc.verify.template.detached";
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ /* signature verification is not supported by mocca
+ protected static final String xxxVERIFY_URL_KEY = "moc.verify.url";
+ */
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa";
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa";
+
+ protected String profile = null;
+
+ protected String loc_ref_content = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ /* signature verification is not supported by mocca
+ protected String verify_request_template = null;
+ */
+
+ protected String verify_template = null;
+
+ /* signature verification is not supported by mocca
+ protected String verify_url = null;
+ */
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ protected String algorithmId = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ * @param profile The configuration profile.
+ * @param algorithmId The algorithm identifer.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public Environment(String profile, String loc_ref_content, String algorithmId) throws ConnectorException {
+ this.profile = profile;
+
+ this.loc_ref_content = loc_ref_content;
+
+ SettingsReader settings = null;
+ try {
+ settings = SettingsReader.getInstance();
+ } catch (SettingsException e) {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ if (algorithmId == null) {
+ this.algorithmId = settings.getValueFromKey("default.moc.algorithm.id");
+ } else {
+ this.algorithmId = algorithmId;
+ }
+
+ // SIGN REQUEST
+
+ // try specific file
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX;
+ log.debug("Trying to load specific sign request file " + sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ // try default request file
+ if (this.sign_request_template == null) {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ log.debug("Specific file not found. Trying default sign request file " + sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ // request file is needed !!!
+ if (this.sign_request_template == null) {
+ throw new ConnectorException(300, "Can not read the create xml request template");
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+
+ // VERIFY REQUEST
+ /* signature verification is not supported by mocca
+
+ // try specific file
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+ log.debug("Trying to load specific verify request file " + verify_request_filename);
+ this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+
+ // try default request file
+ if (this.verify_request_template == null) {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ log.debug("Specific file not found. Trying default verify request file " + verify_request_filename);
+ this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ }
+
+ // request file is needed !!!
+ if (this.verify_request_template == null) {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template");
+ }
+
+ */
+
+ // load template file
+ // try specific file
+ String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX;
+ log.debug("Trying to load specific signature template file " + verify_filename);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ // try default signature template file
+ if (this.verify_template == null) {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ log.debug("Specific signature template file not found. Trying default signature template file " + verify_filename);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ // signature template is needed !!!
+ if (this.verify_template == null) {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template");
+ }
+
+ /* signature verification is not supported by mocca
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+ */
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ /**
+ * Returns the profile name.
+ * @return The profile name.
+ */
+ public String getProfile() {
+ return this.profile;
+ }
+
+ /**
+ * Returns the LocRef content.
+ *
+ * @return Returns the LocRef content.
+ */
+ public String getLocRefContent() {
+ return this.loc_ref_content;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier() {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate() {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL() {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ /* signature verification is not supported by mocca
+ public String getVerifyRequestTemplate() {
+ return this.verify_request_template;
+ }
+ */
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate() {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ /* signature verification is not supported by mocca
+ public String getVerifyURL() {
+ return this.verify_url;
+ }
+ */
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa() {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa() {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key) {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-2$
+ if (value == null) {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+ /**
+ * Parses the common part for all id attributes from a given signature parameter string.
+ * @param sigIdString The given signature parameter string.
+ * @return The common part of all id attributes.
+ */
+ protected String parseSigId(String sigIdString) {
+ String[] parts = sigIdString.split("@");
+ String result = null;
+ if (parts != null && parts.length > 1) {
+ result = parts[1].trim();
+ }
+ return result;
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = prepareXMLContent(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java
new file mode 100644
index 0000000..6b90fa1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java
@@ -0,0 +1,223 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * 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.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.mocca;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector.Environment;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Provides useful methods for the usage of the open source cce mocca.
+ *
+ * @author tknall
+ */
+public final class MOCCAHelper {
+
+ /**
+ * Prevents this plain util class from being instantiated.
+ */
+ private MOCCAHelper() {
+ }
+
+ /**
+ * The logging implementation.
+ */
+ private final static Log log = LogFactory.getLog(MOCCAHelper.class);
+
+ /**
+ * This method parses the signature creation response of the signature
+ * device mocca.
+ *
+ * @param xmlResponse The response string.
+ * @return Returns the parsed signature object holding the data.
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public final static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("xmlResponse = " + xmlResponse);
+ }
+
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName[^>]*>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber[^>]*>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ Pattern signatureValuePattern = Pattern.compile("<(\\w+:)?SignatureValue( Id=\"[\\w-]+\")?>\\s*(.*)\\s*</(\\w+:)?SignatureValue>", Pattern.DOTALL);
+ Matcher signatureValueMatcher = signatureValuePattern.matcher(xmlResponse);
+ if (signatureValueMatcher.find()) {
+ sig_val = signatureValueMatcher.group(3);
+ if (sig_val != null) {
+ sig_val = sig_val.replaceAll("\\s", "");
+ }
+ }
+ log.debug("sig_val = " + sig_val);
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find()) {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam);
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find()) {
+ ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num);
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find()) {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim);
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find()) {
+ String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ } catch (UnsupportedEncodingException e) {
+ throw new ConnectorException(300, e);
+ } catch (CertificateException e) {
+ throw new ConnectorException(300, e);
+ } catch (IOException e) {
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert);
+
+ if (log.isDebugEnabled()) {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss);
+ log.debug("response's issuer = " + iss_nam);
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam));
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num));
+ }
+
+ SignSignatureObject so = new SignSignatureObject();
+
+ // extract Signature Id's
+ String[] ids = extractIds(xmlResponse);
+ // dferbas
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+ String final_ids = id_formatter.formatIds(ids, algs);
+
+
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ so.id = final_ids;
+
+ return so;
+ }
+
+ /**
+ * Extraction of the id attributes from the xml response.
+ *
+ * @param xmlResponse The xml response.
+ * @return The parsed id attributes.
+ */
+ public final static String[] extractIds(String xmlResponse) {
+ return new String[] { extractId(xmlResponse) };
+ }
+
+ /**
+ * There is only one special common part of all id attributes of this
+ * connector that has to be stored. This method returns that single part.
+ *
+ * @param xmlResponse The xml response.
+ * @return The parsed common part of all id attributes.
+ */
+ private final static String extractId(String xmlResponse) {
+ final Pattern ID_PATTERN = Pattern.compile("Id\\s*=\\s*\"\\s*Signature-([\\p{XDigit}]+)-\\d+\\s*\"");
+ Matcher matcher = ID_PATTERN.matcher(xmlResponse);
+ if (matcher.find() && matcher.groupCount() > 0) {
+ return matcher.group(1);
+ }
+ return null;
+ }
+
+}