aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa')
-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
8 files changed, 2969 insertions, 0 deletions
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();
+ }
+
+
+
+
+}