From 4691bdcbc9b3bbbb2ec1753e4b3099eceada5802 Mon Sep 17 00:00:00 2001 From: knowcenter Date: Wed, 16 May 2007 19:59:04 +0000 Subject: enveloping connectors git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@80 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../wag/egov/egiz/sig/connectors/BKUConnector.java | 6 +- .../wag/egov/egiz/sig/connectors/Connector.java | 42 ++ .../egov/egiz/sig/connectors/TemplateReplaces.java | 20 + .../egov/egiz/sig/connectors/bku/BKUHelper.java | 466 +++++++++++++ .../bku/DetachedMultipartBKUConnector.java | 540 ++------------- .../bku/EnvelopedBase64BKUConnector.java | 604 +++++++++++++++++ .../connectors/moa/DetachedLocRefMOAConnector.java | 391 +++++++++++ .../moa/EnvelopingBase64MOAConnector.java | 721 +++++++++++++++++++++ .../egiz/sig/connectors/moa/MOASoapConnection.java | 152 +++++ 9 files changed, 2441 insertions(+), 501 deletions(-) create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java index 6327a11..d6301a9 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java @@ -67,9 +67,9 @@ public class BKUConnector implements LocalConnector /** * The empty constructor */ - public BKUConnector() throws SignatureException + public BKUConnector() //throws SignatureException { - loadSettings(); + //loadSettings(); } /** @@ -77,7 +77,7 @@ public class BKUConnector implements LocalConnector * * @see SettingsReader */ - private void loadSettings() throws SignatureException + public void loadSettings() throws SignatureException { if (settings_ == null) { diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java new file mode 100644 index 0000000..5444d1b --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java @@ -0,0 +1,42 @@ +/** + * + */ +package at.knowcenter.wag.egov.egiz.sig.connectors; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * @author wprinz + * + */ +public interface Connector +{ + /** + * Performs a sign. + * + * @param data + * The data to be signed. + * @return Returns the signature object containing the signature data. + * @throws ConnectorException + * Thrown if something goes wrong. + */ + + public SignSignatureObject doSign(SignatureData data) throws ConnectorException; + + /** + * Performs a verification. + * + * @param data + * The data to be verified. + * @param so + * The signature object with the signature information. + * @return Returns the SignatureResponse with the result of the verification. + * @throws ConnectorException + * Thrown if something goes wrong. + */ + public SignatureResponse doVerify(SignatureData data, SignSignatureObject so) throws ConnectorException; + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java index 46a721a..18cf76d 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java @@ -102,4 +102,24 @@ public final class TemplateReplaces */ public static final String SIG_ID_REPLACE = "SigIdReplace"; //$NON-NLS-1$ + /** + * The placeholder text in the template to be replaced by the key identifier. + */ + public static final String KEY_IDENTIFIER_REPLACE = "KeyIdentifierReplace"; //$NON-NLS-1$ + + /** + * The placeholder text in the template to be replaced by the LocRefContent + * URL. + */ + public static final String LOC_REF_CONTENT_REPLACE = "LocRefContentReplace"; //$NON-NLS-1$ + + /** + * The placeholder text in the template to be replaced by the trust profile ID. + */ + public static final String TRUST_PROFILE_ID_REPLACE = "TrustProfileIDReplace"; //$NON-NLS-1$ + + /** + * The placeholder text in the template to be replaced by the Base64 content. + */ + public static final String BASE64_CONTENT_REPLACE = "Base64ContentReplace"; //$NON-NLS-1$ } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java new file mode 100644 index 0000000..78165c2 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java @@ -0,0 +1,466 @@ +package at.knowcenter.wag.egov.egiz.sig.connectors.bku; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.X509Cert; +import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter; +import at.knowcenter.wag.egov.egiz.tools.CodingHelper; + +/** + * Contains static helper methods used by the BKU Connectors. + * + * @author wprinz + */ +public final class BKUHelper +{ + + /** + * The log. + */ + private static Log log = LogFactory.getLog(BKUHelper.class); + + /** + * Encodes the given SignatureData to a valid Base64Content. + * + *

+ * The data is Base64 encoded. If the mime-type suggests that the data is + * binary, it is Base64 encoded for a second time. + *

+ * + * @param data + * The data to be converted to a valid Base64 content. + * @return Returns the Base64 content. + */ + public static String prepareBase64Content(SignatureData data) + { + String base64 = CodingHelper.encodeBase64(data.getData()); + if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$ + { + log.debug("The data is application/pdf - so it is Base64 encoded again."); //$NON-NLS-1$ + base64 = CodingHelper.encodeUTF8AsBase64(base64); + } + return base64; + } + + /** + * Checks the response xml for an error description and if found throws an + * appropriate exception. + * + * @param response_string + * The response xml. + * @throws ConnectorException + * f.e. + */ + public static void checkResponseForError(String response_string) throws ConnectorException + { + Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>"); //$NON-NLS-1$ + Pattern erc_p_e = Pattern.compile(""); //$NON-NLS-1$ + Matcher erc_m_s = erc_p_s.matcher(response_string); + Matcher erc_m_e = erc_p_e.matcher(response_string); + + if (erc_m_s.find() && erc_m_e.find()) + { + log.error("Found error in response: " + response_string); //$NON-NLS-1$ + + Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$ + Pattern erm_p_e = Pattern.compile(""); //$NON-NLS-1$ + Matcher erm_m_s = erm_p_s.matcher(response_string); + Matcher erm_m_e = erm_p_e.matcher(response_string); + ConnectorException se = new ConnectorException(0, "BKUSigExc"); //$NON-NLS-1$ + String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start()); + se.setExternalErrorCode(error_code); + if (erm_m_s.find() && erm_m_e.find()) + { + String error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start()); + se.setExternalErrorMessage(error_mess); + } + throw se; + } + } + + /** + * This method parses the BKU-Response string. + * + *

+ * It separates the SignatureValue, X509IssuerName, SigningTime, + * X509SerialNumber, X509Certificate, CertDigest, DigestValue and the + * signation id-s. If the X509Certificate is extracted it would be stored in + * the certificates directory. + *

+ * + * @param xmlResponse + * The response string. + * @return Returns the parsed signature object holding the data. + * + * @throws ConnectorException + * ErrorCode (303, 304) + * @see SignatureObject + * @see CodingHelper + * @see X509Cert + */ + public static SignSignatureObject parseCreateXMLResponse(String xmlResponse, + IdFormatter id_formatter) throws ConnectorException + { + Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$ + Pattern sig_val_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$ + Pattern iss_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$ + Pattern sig_tim_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$ + Pattern ser_num_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$ + Pattern sig_cer_p_e = Pattern.compile(""); //$NON-NLS-1$ + + // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>"); + // //$NON-NLS-1$ + // Pattern sig_cer_d_p_e = Pattern.compile(""); + // //$NON-NLS-1$ + // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>"); + // //$NON-NLS-1$ + // Pattern dig_val_p_e = Pattern.compile(""); + // //$NON-NLS-1$ + + Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse); + Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse); + Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse); + Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse); + Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse); + Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse); + Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse); + Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse); + Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse); + Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse); + + // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse); + // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse); + // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse); + // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse); + + // SignatureValue + String sig_val = null; + if (sig_val_m_s.find() && sig_val_m_e.find()) + { + sig_val = removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start())); + } + log.debug("sig_val = " + sig_val); //$NON-NLS-1$ + + // X509IssuerName + String iss_nam = null; + if (iss_nam_m_s.find() && iss_nam_m_e.find()) + { + iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); + } + log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$ + + // X509SerialNumber + String ser_num = null; + if (ser_num_m_s.find() && ser_num_m_e.find()) + { + ser_num = removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start())); + } + log.debug("ser_num = " + ser_num); //$NON-NLS-1$ + + // SigningTime + String sig_tim = null; + if (sig_tim_m_s.find() && sig_tim_m_e.find()) + { + sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start()); + } + log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$ + + // CertDigest + // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find()) + // { + // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), + // sig_cer_d_m_e.start()); + // if (dig_val_m_s.find() && dig_val_m_e.find()) + // { + // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start()); + // //sigObj.setX509CertificateDigest(sig_dig); + // } + // } + + // X509Certificate + X509Certificate cert = null; + if (sig_cer_m_s.find() && sig_cer_m_e.find()) + { + String sig_cer = removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start())); + + try + { + byte[] der = CodingHelper.decodeBase64(sig_cer); + ByteArrayInputStream bais = new ByteArrayInputStream(der); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$ + cert = (X509Certificate) cf.generateCertificate(bais); + bais.close(); + } + catch (UnsupportedEncodingException e) + { + log.error(e); + throw new ConnectorException(300, e); + } + catch (CertificateException e) + { + log.error(e); + throw new ConnectorException(300, e); + } + catch (IOException e) + { + log.error(e); + throw new ConnectorException(300, e); + } + } + log.debug("X509Certificate = " + cert); //$NON-NLS-1$ + + if (log.isDebugEnabled()) + { + + String cert_iss = cert.getIssuerDN().getName(); + log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$ + log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$ + log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$ + log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$ + } + + // extract Subject Name from X509Certificate + // if (sig_cer_m_s.find() && sig_cer_m_e.find()) + // { + // sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()); + // sig_cer = sig_cer.replaceAll("\\s", ""); + // //sigObj.setX509Certificate(sig_cer); + // X509Cert cert = X509Cert.initByString(sig_cer); + // if (cert.isX509Cert()) + // { + // //sigObj.setX509Certificate(cert.getCertString()); + // String serial_num = cert.getSerialNumber(); + // String subject_name = cert.getSubjectName(); + // if (!ser_num.equals(serial_num)) + // { + // ConnectorException se = new ConnectorException(303, "Serialnumber of + // certificate and tag X509SerialNumber differs!"); + // throw se; + // } + // //sigObj.setSignationName(subject_name); + // } + // } + + // extract Signature Id's + String[] ids = new String[5]; + ids[0] = extractId(xmlResponse, "signature-"); //$NON-NLS-1$ + ids[1] = extractId(xmlResponse, "signed-data-reference-"); //$NON-NLS-1$ + ids[2] = extractId(xmlResponse, "signed-data-object-"); //$NON-NLS-1$ + ids[3] = extractId(xmlResponse, "etsi-data-reference-"); //$NON-NLS-1$ + ids[4] = extractId(xmlResponse, "etsi-data-object-"); //$NON-NLS-1$ + String final_ids = id_formatter.formatIds(ids); + + SignSignatureObject so = new SignSignatureObject(); + so.date = sig_tim; + so.issuer = iss_nam; + so.signatureValue = sig_val; + so.x509Certificate = cert; + + so.id = final_ids; + + return so; + } + + /** + * Removes all whitespaces ("\\s") from the String. + * + * @param str + * The String. + * @return The String with all whitespaces removed. + */ + public static String removeAllWhitespace(String str) + { + return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * This emthod extracts id-values from a text. The id is given by the name. + * + * @param text + * the id-value that should extract from + * @param name + * the id-key + * @return the value of the given key in the text + */ + private static String extractId(String text, String name) + { + String id = null; + int start_idx = text.indexOf(name) + name.length(); + int end_idx = text.indexOf("\"", start_idx); //$NON-NLS-1$ + + final int quot_end_idx = end_idx; + final int squot_end_idx = text.indexOf("'", start_idx); //$NON-NLS-1$ + end_idx = Math.min(quot_end_idx, squot_end_idx); + id = text.substring(start_idx, end_idx); + log.info("extract id:" + name + id); //$NON-NLS-1$ + if (log.isDebugEnabled()) + { + log.debug("extract id:" + name + id); //$NON-NLS-1$ + } + return id; + } + + /** + * This method parses the verify response string and return a + * SignatureResponse object. The SignatureResponse object is filled out by the + * response values from the BKU-response. + * + * @param xmlResponse + * the response values from the BKU-verify request + * @return SignatureResponse object + * @see SignatureResponse + */ + public static SignatureResponse parseVerifyXMLResponse(String xmlResponse) + { + log.debug("parseVerifyXMLResponse:"); //$NON-NLS-1$ + + Pattern sub_nam_p_s = Pattern.compile(""); //$NON-NLS-1$ + Pattern sub_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern iss_nam_p_s = Pattern.compile(""); //$NON-NLS-1$ + Pattern iss_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern ser_num_p_s = Pattern.compile(""); //$NON-NLS-1$ + Pattern ser_num_p_e = Pattern.compile(""); //$NON-NLS-1$ + + Pattern sig_chk_p_s = Pattern.compile("<[\\w]*:?SignatureCheck>"); //$NON-NLS-1$ + Pattern sig_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern man_chk_p_s = Pattern.compile("<[\\w]*:?SignatureManifestCheck>"); //$NON-NLS-1$ + Pattern man_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern cer_chk_p_s = Pattern.compile("<[\\w]*:?CertificateCheck>"); //$NON-NLS-1$ + Pattern cer_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ + + // [tknall] start qualified certificate + Pattern cert_qualified_p = Pattern.compile("<[\\w]*:?QualifiedCertificate/>"); //$NON-NLS-1$ + Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse); + // [tknall] stop qualified certificate + + Pattern code_p_s = Pattern.compile("<[\\w]*:?Code>"); //$NON-NLS-1$ + Pattern code_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern info_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$ + Pattern info_p_e = Pattern.compile(""); //$NON-NLS-1$ + + Pattern cert_p_s = Pattern.compile(""); //$NON-NLS-1$ + Pattern cert_p_e = Pattern.compile(""); //$NON-NLS-1$ + + Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse); + Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse); + Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse); + Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse); + Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse); + Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse); + + Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse); + Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse); + Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse); + Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse); + Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse); + Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse); + + Matcher cert_m_s = cert_p_s.matcher(xmlResponse); + Matcher cert_m_e = cert_p_e.matcher(xmlResponse); + + SignatureResponse sig_res = new SignatureResponse(); + + // [tknall] start qualified certificate + sig_res.setQualifiedCertificate(cert_qualified_m.find()); + // [tknall] stop qualified certificate + + if (sub_nam_m_s.find() && sub_nam_m_e.find()) + { + String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start()); + sig_res.setX509SubjectName(sub_nam); + } + if (iss_nam_m_s.find() && iss_nam_m_e.find()) + { + String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); + sig_res.setX509IssuerName(iss_nam); + } + if (ser_num_m_s.find() && ser_num_m_e.find()) + { + String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()); + sig_res.setX509SerialNumber(ser_num); + } + if (sig_chk_m_s.find() && sig_chk_m_e.find()) + { + String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start()); + Matcher code_m_s = code_p_s.matcher(sig_chk); + Matcher code_m_e = code_p_e.matcher(sig_chk); + Matcher info_m_s = info_p_s.matcher(sig_chk); + Matcher info_m_e = info_p_e.matcher(sig_chk); + if (code_m_s.find() && code_m_e.find()) + { + String code = sig_chk.substring(code_m_s.end(), code_m_e.start()); + sig_res.setSignatureCheckCode(code); + } + if (info_m_s.find() && info_m_e.find()) + { + String info = sig_chk.substring(info_m_s.end(), info_m_e.start()); + sig_res.setSignatureCheckInfo(info); + } + } + if (man_chk_m_s.find() && man_chk_m_e.find()) + { + String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start()); + Matcher code_m_s = code_p_s.matcher(man_chk); + Matcher code_m_e = code_p_e.matcher(man_chk); + Matcher info_m_s = info_p_s.matcher(man_chk); + Matcher info_m_e = info_p_e.matcher(man_chk); + if (code_m_s.find() && code_m_e.find()) + { + String code = man_chk.substring(code_m_s.end(), code_m_e.start()); + sig_res.setSignatureManifestCheckCode(code); + } + if (info_m_s.find() && info_m_e.find()) + { + String info = man_chk.substring(info_m_s.end(), info_m_e.start()); + sig_res.setSignatureManifestCheckInfo(info); + } + } + if (cer_chk_m_s.find() && cer_chk_m_e.find()) + { + String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start()); + Matcher code_m_s = code_p_s.matcher(cer_chk); + Matcher code_m_e = code_p_e.matcher(cer_chk); + Matcher info_m_s = info_p_s.matcher(cer_chk); + Matcher info_m_e = info_p_e.matcher(cer_chk); + if (code_m_s.find() && code_m_e.find()) + { + String code = cer_chk.substring(code_m_s.end(), code_m_e.start()); + sig_res.setCertificateCheckCode(code); + } + if (info_m_s.find() && info_m_e.find()) + { + String info = cer_chk.substring(info_m_s.end(), info_m_e.start()); + sig_res.setCertificateCheckInfo(info); + } + } + if (cert_m_s.find() && cert_m_e.find()) + { + String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start()); + + X509Cert resp_cert = X509Cert.initByString(cert_string); + sig_res.setCertificate(resp_cert); + } + + log.debug("parseVerifyXMLResponse finished."); //$NON-NLS-1$ + return sig_res; + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedMultipartBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedMultipartBKUConnector.java index a3b2700..68ff62e 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedMultipartBKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedMultipartBKUConnector.java @@ -3,27 +3,21 @@ */ package at.knowcenter.wag.egov.egiz.sig.connectors.bku; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.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.SignatureObject; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; -import at.knowcenter.wag.egov.egiz.sig.X509Cert; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; @@ -36,13 +30,8 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper; * * @author wprinz */ -public class DetachedMultipartBKUConnector +public class DetachedMultipartBKUConnector implements Connector { - /** - * The SIG_ID prefix. - */ - public static final String SIG_ID_PREFIX = "etsi-bku-detached@"; //$NON-NLS-1$ - /** * The log. */ @@ -65,12 +54,10 @@ public class DetachedMultipartBKUConnector * * @param profile * The profile from which the Environment should be assembled. - * @throws SettingsException - * f.e. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public DetachedMultipartBKUConnector(String profile) throws SignatureException, SettingsException + public DetachedMultipartBKUConnector(String profile) throws ConnectorException { this.environment = new Environment(profile); } @@ -81,10 +68,10 @@ public class DetachedMultipartBKUConnector * @param data * The SignatureData. * @return Returns the sign request xml to be sent. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - protected String prepareSignRequestDetached(SignatureData data) throws SignatureException + protected String prepareSignRequestDetached(SignatureData data) throws ConnectorException { log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$ @@ -112,329 +99,26 @@ public class DetachedMultipartBKUConnector * The response properties containing the response String and * transport related information. * @return Returns the extracted data encapsulated in a SignatureObject. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public SignSignatureObject analyzeSignResponse(Properties response_properties) throws SignatureException + public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException { log.debug("analyzeSignResponse:"); //$NON-NLS-1$ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); - // TODO debug - // try - // { - // FileOutputStream fos = new - // FileOutputStream("C:\\wprinz\\Filer\\egiz2\\sign_response.utf8.xml"); - // //$NON-NLS-1$ - // OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); - // //$NON-NLS-1$ - // osw.write(response_string); - // osw.close(); - // } - // catch (Exception e) - // { - // log.error(e); - // } - - checkResponseForError(response_string); + BKUHelper.checkResponseForError(response_string); - SignSignatureObject so = parseCreateXMLResponse(response_string); + SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new DetachedIdFormatter()); log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ return so; } - /** - * Checks the response xml for an error description and if found throws an - * appropriate exception. - * - * @param response_string - * The response xml. - * @throws SignatureException - * f.e. - */ - protected void checkResponseForError(String response_string) throws SignatureException - { - Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>"); //$NON-NLS-1$ - Pattern erc_p_e = Pattern.compile(""); //$NON-NLS-1$ - Matcher erc_m_s = erc_p_s.matcher(response_string); - Matcher erc_m_e = erc_p_e.matcher(response_string); - - if (erc_m_s.find() && erc_m_e.find()) - { - log.error("Found error in response: " + response_string); //$NON-NLS-1$ - - Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$ - Pattern erm_p_e = Pattern.compile(""); //$NON-NLS-1$ - Matcher erm_m_s = erm_p_s.matcher(response_string); - Matcher erm_m_e = erm_p_e.matcher(response_string); - SignatureException se = new SignatureException(0, "BKUSigExc"); //$NON-NLS-1$ - String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start()); - se.setExternalErrorCode(error_code); - if (erm_m_s.find() && erm_m_e.find()) - { - String error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start()); - se.setExternalErrorMessage(error_mess); - } - throw se; - } - } - - /** - * This method parses the BKU-Response string. - * - *

- * It separates the SignatureValue, X509IssuerName, SigningTime, - * X509SerialNumber, X509Certificate, CertDigest, DigestValue and the - * signation id-s. If the X509Certificate is extracted it would be stored in - * the certificates directory. - *

- * - * @param xmlResponse - * The response string. - * @return Returns the parsed signature object holding the data. - * - * @throws SignatureException - * ErrorCode (303, 304) - * @see SignatureObject - * @see CodingHelper - * @see X509Cert - */ - private SignSignatureObject parseCreateXMLResponse(String xmlResponse) throws SignatureException - { - Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$ - Pattern sig_val_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$ - Pattern iss_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$ - Pattern sig_tim_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$ - Pattern ser_num_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$ - Pattern sig_cer_p_e = Pattern.compile(""); //$NON-NLS-1$ - - // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>"); - // //$NON-NLS-1$ - // Pattern sig_cer_d_p_e = Pattern.compile(""); - // //$NON-NLS-1$ - // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>"); - // //$NON-NLS-1$ - // Pattern dig_val_p_e = Pattern.compile(""); - // //$NON-NLS-1$ - - Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse); - Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse); - Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse); - Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse); - Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse); - Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse); - Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse); - Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse); - Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse); - Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse); - - // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse); - // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse); - // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse); - // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse); - - // SignatureValue - String sig_val = null; - if (sig_val_m_s.find() && sig_val_m_e.find()) - { - sig_val = removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start())); - } - log.debug("sig_val = " + sig_val); //$NON-NLS-1$ - - // X509IssuerName - String iss_nam = null; - if (iss_nam_m_s.find() && iss_nam_m_e.find()) - { - iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); - } - log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$ - - // X509SerialNumber - String ser_num = null; - if (ser_num_m_s.find() && ser_num_m_e.find()) - { - ser_num = removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start())); - } - log.debug("ser_num = " + ser_num); //$NON-NLS-1$ - - // SigningTime - String sig_tim = null; - if (sig_tim_m_s.find() && sig_tim_m_e.find()) - { - sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start()); - } - log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$ - - // CertDigest - // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find()) - // { - // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), - // sig_cer_d_m_e.start()); - // if (dig_val_m_s.find() && dig_val_m_e.find()) - // { - // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start()); - // //sigObj.setX509CertificateDigest(sig_dig); - // } - // } - - // X509Certificate - X509Certificate cert = null; - if (sig_cer_m_s.find() && sig_cer_m_e.find()) - { - String sig_cer = removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start())); - - try - { - byte[] der = CodingHelper.decodeBase64(sig_cer); - ByteArrayInputStream bais = new ByteArrayInputStream(der); - CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$ - cert = (X509Certificate) cf.generateCertificate(bais); - bais.close(); - } - catch (UnsupportedEncodingException e) - { - log.error(e); - throw new SignatureException(300, e); - } - catch (CertificateException e) - { - log.error(e); - throw new SignatureException(300, e); - } - catch (IOException e) - { - log.error(e); - throw new SignatureException(300, e); - } - } - log.debug("X509Certificate = " + cert); //$NON-NLS-1$ - - if (log.isDebugEnabled()) - { - - String cert_iss = cert.getIssuerDN().getName(); - log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$ - log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$ - log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$ - log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$ - } - - // extract Subject Name from X509Certificate - // if (sig_cer_m_s.find() && sig_cer_m_e.find()) - // { - // sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()); - // sig_cer = sig_cer.replaceAll("\\s", ""); - // //sigObj.setX509Certificate(sig_cer); - // X509Cert cert = X509Cert.initByString(sig_cer); - // if (cert.isX509Cert()) - // { - // //sigObj.setX509Certificate(cert.getCertString()); - // String serial_num = cert.getSerialNumber(); - // String subject_name = cert.getSubjectName(); - // if (!ser_num.equals(serial_num)) - // { - // SignatureException se = new SignatureException(303, "Serialnumber of - // certificate and tag X509SerialNumber differs!"); - // throw se; - // } - // //sigObj.setSignationName(subject_name); - // } - // } - - // extract Signature Id's - String[] ids = new String[5]; - ids[0] = extractId(xmlResponse, "signature-"); //$NON-NLS-1$ - ids[1] = extractId(xmlResponse, "signed-data-reference-"); //$NON-NLS-1$ - ids[2] = extractId(xmlResponse, "signed-data-object-"); //$NON-NLS-1$ - ids[3] = extractId(xmlResponse, "etsi-data-reference-"); //$NON-NLS-1$ - ids[4] = extractId(xmlResponse, "etsi-data-object-"); //$NON-NLS-1$ - String final_ids = formatSigIds(ids); - - SignSignatureObject so = new SignSignatureObject(); - so.date = sig_tim; - so.issuer = iss_nam; - so.signatureValue = sig_val; - so.x509Certificate = cert; - - so.id = final_ids; - - return so; - } - - /** - * Removes all whitespaces ("\\s") from the String. - * - * @param str - * The String. - * @return The String with all whitespaces removed. - */ - protected static String removeAllWhitespace(String str) - { - return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$ - } - /** - * This emthod extracts id-values from a text. The id is given by the name. - * - * @param text - * the id-value that should extract from - * @param name - * the id-key - * @return the value of the given key in the text - */ - private String extractId(String text, String name) - { - String id = null; - int start_idx = text.indexOf(name) + name.length(); - int end_idx = text.indexOf("\"", start_idx); //$NON-NLS-1$ - - final int quot_end_idx = end_idx; - final int squot_end_idx = text.indexOf("'", start_idx); //$NON-NLS-1$ - end_idx = Math.min(quot_end_idx, squot_end_idx); - id = text.substring(start_idx, end_idx); - log.info("extract id:" + name + id); //$NON-NLS-1$ - if (log.isDebugEnabled()) - { - log.debug("extract id:" + name + id); //$NON-NLS-1$ - } - return id; - } - protected String formatSigIds(String[] sigIds) throws SignatureException - { - // ids algorithm: - String join = ""; //$NON-NLS-1$ - String base = null; - for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++) - { - String id = sigIds[arr_idx]; - if (log.isDebugEnabled()) - { - log.debug("Set BKU id:" + id); //$NON-NLS-1$ - } - int id_idx = id.lastIndexOf("-"); //$NON-NLS-1$ - if (arr_idx == 0) - { - base = id.substring(0, id_idx); - } - String cur_id = id.substring(id_idx + 1); - if (cur_id.equalsIgnoreCase("")) //$NON-NLS-1$ - { - cur_id = "0"; //$NON-NLS-1$ - } - join += "-" + cur_id; //$NON-NLS-1$ - } - String ids = base + "@" + join.substring(1); //$NON-NLS-1$ - String final_ids = SIG_ID_PREFIX + ids; - return final_ids; - } public static String[] parseSigIds(String sig_ids) { @@ -505,11 +189,11 @@ public class DetachedMultipartBKUConnector * The data. * @return Returns the response properties containing among others the * response XML. - * @throws SignatureException + * @throws ConnectorException * f.e. */ protected Properties sendRequest(String url, String request_string, - SignatureData data) throws SignatureException + SignatureData data) throws ConnectorException { try { @@ -518,7 +202,7 @@ public class DetachedMultipartBKUConnector } catch (Exception e) { - SignatureException se = new SignatureException(320, e); + ConnectorException se = new ConnectorException(320, e); throw se; } } @@ -529,10 +213,10 @@ public class DetachedMultipartBKUConnector * @param data * The data to be signed. * @return Returns the signature object containing the signature data. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public SignSignatureObject doSign(SignatureData data) throws SignatureException + public SignSignatureObject doSign(SignatureData data) throws ConnectorException { log.debug("doSign:"); //$NON-NLS-1$ @@ -559,10 +243,10 @@ public class DetachedMultipartBKUConnector * @param so * The signature object with the signature information. * @return Returns the SignatureResponse with the result of the verification. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public SignatureResponse doVerify(SignatureData data, SignSignatureObject so) throws SignatureException + public SignatureResponse doVerify(SignatureData data, SignSignatureObject so) throws ConnectorException { log.debug("doVerify:"); //$NON-NLS-1$ @@ -601,11 +285,11 @@ public class DetachedMultipartBKUConnector * @param so * The signature information object. * @return Returns the verify request xml to be sent. - * @throws SignatureException + * @throws ConnectorException * f.e. */ public String prepareVerifyRequestDetached(SignatureData data, - SignSignatureObject so) throws SignatureException + SignSignatureObject so) throws ConnectorException { String verify_request_template = this.environment.getVerifyRequestTemplate(); @@ -641,10 +325,10 @@ public class DetachedMultipartBKUConnector * @param so * The signature object containing the signature information. * @return Returns the XML content. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws SignatureException + public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException { log.debug("prepareXMLContent:"); //$NON-NLS-1$ try @@ -725,7 +409,7 @@ public class DetachedMultipartBKUConnector catch (Exception e) { log.debug(e); - throw new SignatureException(310, e); + throw new ConnectorException(310, e); } } @@ -735,167 +419,23 @@ public class DetachedMultipartBKUConnector * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException + public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException { log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); - checkResponseForError(response_string); + BKUHelper.checkResponseForError(response_string); - SignatureResponse signature_response = parseVerifyXMLResponse(response_string); + SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string); log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$ return signature_response; } - /** - * This method parses the verify response string and return a - * SignatureResponse object. The SignatureResponse object is filled out by the - * response values from the BKU-response. - * - * @param xmlResponse - * the response values from the BKU-verify request - * @return SignatureResponse object - * @see SignatureResponse - */ - private SignatureResponse parseVerifyXMLResponse(String xmlResponse) - { - log.debug("parseVerifyXMLResponse:"); //$NON-NLS-1$ - - Pattern sub_nam_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern sub_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern iss_nam_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern iss_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern ser_num_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern ser_num_p_e = Pattern.compile(""); //$NON-NLS-1$ - - Pattern sig_chk_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern sig_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern man_chk_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern man_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern cer_chk_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern cer_chk_p_e = Pattern.compile(""); //$NON-NLS-1$ - - // [tknall] start qualified certificate - Pattern cert_qualified_p = Pattern.compile(""); //$NON-NLS-1$ - Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse); - // [tknall] stop qualified certificate - - Pattern code_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern code_p_e = Pattern.compile(""); //$NON-NLS-1$ - Pattern info_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern info_p_e = Pattern.compile(""); //$NON-NLS-1$ - - Pattern cert_p_s = Pattern.compile(""); //$NON-NLS-1$ - Pattern cert_p_e = Pattern.compile(""); //$NON-NLS-1$ - - Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse); - Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse); - Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse); - Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse); - Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse); - Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse); - - Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse); - Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse); - Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse); - Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse); - Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse); - Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse); - - Matcher cert_m_s = cert_p_s.matcher(xmlResponse); - Matcher cert_m_e = cert_p_e.matcher(xmlResponse); - - SignatureResponse sig_res = new SignatureResponse(); - - // [tknall] start qualified certificate - sig_res.setQualifiedCertificate(cert_qualified_m.find()); - // [tknall] stop qualified certificate - - if (sub_nam_m_s.find() && sub_nam_m_e.find()) - { - String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start()); - sig_res.setX509SubjectName(sub_nam); - } - if (iss_nam_m_s.find() && iss_nam_m_e.find()) - { - String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); - sig_res.setX509IssuerName(iss_nam); - } - if (ser_num_m_s.find() && ser_num_m_e.find()) - { - String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()); - sig_res.setX509SerialNumber(ser_num); - } - if (sig_chk_m_s.find() && sig_chk_m_e.find()) - { - String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start()); - Matcher code_m_s = code_p_s.matcher(sig_chk); - Matcher code_m_e = code_p_e.matcher(sig_chk); - Matcher info_m_s = info_p_s.matcher(sig_chk); - Matcher info_m_e = info_p_e.matcher(sig_chk); - if (code_m_s.find() && code_m_e.find()) - { - String code = sig_chk.substring(code_m_s.end(), code_m_e.start()); - sig_res.setSignatureCheckCode(code); - } - if (info_m_s.find() && info_m_e.find()) - { - String info = sig_chk.substring(info_m_s.end(), info_m_e.start()); - sig_res.setSignatureCheckInfo(info); - } - } - if (man_chk_m_s.find() && man_chk_m_e.find()) - { - String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start()); - Matcher code_m_s = code_p_s.matcher(man_chk); - Matcher code_m_e = code_p_e.matcher(man_chk); - Matcher info_m_s = info_p_s.matcher(man_chk); - Matcher info_m_e = info_p_e.matcher(man_chk); - if (code_m_s.find() && code_m_e.find()) - { - String code = man_chk.substring(code_m_s.end(), code_m_e.start()); - sig_res.setSignatureManifestCheckCode(code); - } - if (info_m_s.find() && info_m_e.find()) - { - String info = man_chk.substring(info_m_s.end(), info_m_e.start()); - sig_res.setSignatureManifestCheckInfo(info); - } - } - if (cer_chk_m_s.find() && cer_chk_m_e.find()) - { - String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start()); - Matcher code_m_s = code_p_s.matcher(cer_chk); - Matcher code_m_e = code_p_e.matcher(cer_chk); - Matcher info_m_s = info_p_s.matcher(cer_chk); - Matcher info_m_e = info_p_e.matcher(cer_chk); - if (code_m_s.find() && code_m_e.find()) - { - String code = cer_chk.substring(code_m_s.end(), code_m_e.start()); - sig_res.setCertificateCheckCode(code); - } - if (info_m_s.find() && info_m_e.find()) - { - String info = cer_chk.substring(info_m_s.end(), info_m_e.start()); - sig_res.setCertificateCheckInfo(info); - } - } - if (cert_m_s.find() && cert_m_e.find()) - { - String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start()); - - X509Cert resp_cert = X509Cert.initByString(cert_string); - sig_res.setCertificate(resp_cert); - } - - log.debug("parseVerifyXMLResponse finished."); //$NON-NLS-1$ - return sig_res; - } /** * Holds environment configuration information like templates. @@ -965,14 +505,20 @@ public class DetachedMultipartBKUConnector * * @param profile * The configuration profile. - * @throws SettingsException - * f.e. - * @throws SignatureException + * @throws ConnectorException * f.e. */ - public Environment(String profile) throws SettingsException, SignatureException + public Environment(String profile) throws ConnectorException { - SettingsReader settings = SettingsReader.getInstance(); + SettingsReader settings = null; + try + { + settings = SettingsReader.getInstance(); + } + catch (SettingsException e) + { + throw new ConnectorException(300, e); + } this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY); @@ -980,8 +526,7 @@ public class DetachedMultipartBKUConnector this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); if (this.sign_request_template == null) { - // TODO make this a settings exception - throw new SignatureException(300, "Can not read the create xml request template"); //$NON-NLS-1$ + throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$ } this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY); @@ -991,7 +536,7 @@ public class DetachedMultipartBKUConnector if (this.verify_request_template == null) { // TODO make this a settings exception - throw new SignatureException(300, "Can not read the verify xml request template"); //$NON-NLS-1$ + throw new ConnectorException(300, "Can not read the verify xml request template"); //$NON-NLS-1$ } String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY); @@ -999,7 +544,7 @@ public class DetachedMultipartBKUConnector if (this.verify_template == null) { // TODO make this a settings exception - throw new SignatureException(300, "Can not read the verify template"); //$NON-NLS-1$ + throw new ConnectorException(300, "Can not read the verify template"); //$NON-NLS-1$ } this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY); @@ -1112,6 +657,5 @@ public class DetachedMultipartBKUConnector } return value; } - } } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java new file mode 100644 index 0000000..cabfe92 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java @@ -0,0 +1,604 @@ +/** + * + */ +package at.knowcenter.wag.egov.egiz.sig.connectors.bku; + +import java.security.cert.X509Certificate; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter; +import at.knowcenter.wag.egov.egiz.tools.CodingHelper; +import at.knowcenter.wag.egov.egiz.tools.FileHelper; + +/** + * @author wprinz + * + */ +public class EnvelopedBase64BKUConnector implements Connector +{ + + /** + * The log. + */ + private static Log log = LogFactory.getLog(EnvelopedBase64BKUConnector.class); + + /** + * The environemnt configuration of this connector containing templates and + * other configurable elements. + */ + protected Environment environment = null; + + /** + * Constructor that builds the configuration environment for this connector + * according to the given profile. + * + *

+ * If confuguration parameters are not defined on that profile, the default + * parameters defined in the configuration are used. + *

+ * + * @param profile + * The profile from which the Environment should be assembled. + * @throws ConnectorException + * f.e. + */ + public EnvelopedBase64BKUConnector(String profile) throws ConnectorException + { + this.environment = new Environment(profile); + } + + /** + * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData) + */ + public SignSignatureObject doSign(SignatureData data) throws ConnectorException + { + log.debug("doSign:"); //$NON-NLS-1$ + + String sign_request_xml = prepareSignRequest(data); + log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$ + + String url = this.environment.getSignURL(); + Properties response_properties = sendRequest(url, sign_request_xml); + + SignSignatureObject sso = analyzeSignResponse(response_properties); + + // TODO this could be made more generic + 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) throws ConnectorException + { + log.debug("doVerify:"); //$NON-NLS-1$ + + String verify_request_xml = prepareVerifyRequest(data, so); + log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$ + + // TODO debug + // try + // { + // FileOutputStream fos = new + // FileOutputStream("C:\\wprinz\\Filer\\egiz2\\verify_request.utf8.xml"); + // //$NON-NLS-1$ + // fos.write(verify_request_xml.getBytes("UTF-8")); //$NON-NLS-1$ + // fos.close(); + // } + // catch (Exception e) + // { + // log.error(e); + // } + + String url = this.environment.getVerifyURL(); + Properties response_properties = sendRequest(url, verify_request_xml); + + SignatureResponse signature_response = analyzeVerifyResponse(response_properties); + + log.debug("doVerify finished."); //$NON-NLS-1$ + return signature_response; + } + + /** + * This emthod extracts id-values from a text. The id is given by the name. + * + * @param text + * the id-value that should extract from + * @param name + * the id-key + * @return the value of the given key in the text + */ + private String extractId(String text, String name) + { + String id = null; + int start_idx = text.indexOf(name) + name.length(); + int end_idx = text.indexOf("\"", start_idx); + + // TODO hotfix! + final int quot_end_idx = end_idx; + final int squot_end_idx = text.indexOf("'", start_idx); + end_idx = Math.min(quot_end_idx, squot_end_idx); + // TODO hotfix end! + + id = text.substring(start_idx, end_idx); + if (log.isDebugEnabled()) + { + log.debug("extract id:" + name + id); + } + return id; + } + + + /** + * Prepares the XML content the holds the actual signature data. + * + *

+ * This strongly rebuilds the XML content as retuned from a sign request. + *

+ * + * @param data + * The data. + * @param so + * The signature object containing the signature information. + * @return Returns the XML content. + * @throws ConnectorException + * f.e. + */ + public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException + { + log.debug("prepareXMLContent:"); //$NON-NLS-1$ + try + { + String verify_template = this.environment.getVerifyTemplate(); + + String ids_string = so.getSigID(); + String[] ids = SignatureObject.parseSigIds(ids_string); + + X509Certificate cert = so.getX509Certificate(); + String cert_alg = this.environment.getCertAlgEcdsa(); + if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$ + { + cert_alg = this.environment.getCertAlgRsa(); + } + + // cert alg replace + String verify_xml = verify_template.replaceFirst(TemplateReplaces.CERT_ALG_REPLACE, cert_alg); + + // data digest replace + { + byte[] data_value = data.getData(); + byte[] data_value_hash = CodingHelper.buildDigest(data_value); + String object_data_hash = CodingHelper.encodeBase64(data_value_hash); + + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash); + } + + // SIG id replaces + verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_REF_REPLACE, ids[1]); + verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_REF_REPLACE, ids[3]); + verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_OBJ_URI_REPLACE, ids[2]); + + verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue()); + + // X.509 Certificate replace + byte[] der = cert.getEncoded(); + byte[] cert_hash = CodingHelper.buildDigest(der); + String certDigest = CodingHelper.encodeBase64(cert_hash); + String x509_cert_string = CodingHelper.encodeBase64(der); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string); + + // Base64 content replace + String base64 = BKUHelper.prepareBase64Content(data); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64); + + // Qualified Properties replaces + verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]); + verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); + // SigDataRefReplace already done above + + // Signed Properties hash + { + final String ETSI_SIGNED_PROPERTIES_START_TAG = "= 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); + 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); + } + } + + /** + * Prepares the sign request xml to be sent using the sign request template. + * + * @param data + * The SignatureData. + * @return Returns the sign request xml to be sent. + * @throws ConnectorException + * f.e. + */ + public String prepareSignRequest(SignatureData data) throws ConnectorException + { + log.debug("prepareSignRequest:"); //$NON-NLS-1$ + + String sign_request_template = this.environment.getSignRequestTemplate(); + + String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier(); + String base64 = BKUHelper.prepareBase64Content(data); + + String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier); + sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64); + + log.debug("prepareSignRequest finished."); //$NON-NLS-1$ + return sign_request_xml; + } + + /** + * Prepares the verify request xml to be sent using the verify request + * template. + * + * @param data + * The SignatureData. + * @param so + * The signature information object. + * @return Returns the verify request xml to be sent. + * @throws ConnectorException + * f.e. + */ + public String prepareVerifyRequest(SignatureData data, + SignSignatureObject so) throws ConnectorException + { + String verify_request_template = this.environment.getVerifyRequestTemplate(); + + String xml_content = null; + // TODO implement MOA + // if (sigObject.isMOASigned()) + // { + // MOAConnector moa_conn = new MOAConnector(); + // // get the MOA-template + // verify_template_str = moa_conn.getVerifyTemplate(normalizedText, + // sigObject); + // } + // else + // { + // get the BKU-template + xml_content = prepareXMLContent(data, so); + // } + + String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + + return verify_request_xml; + } + + + /** + * Sends the request to the given URL. + * + * @param url + * The URL. + * @param request_string + * The request string. + * @return Returns the response string. + * @throws ConnectorException + * F.e. + */ + protected Properties sendRequest(String url, String request_string) throws ConnectorException + { + try + { + Properties response_properties = at.knowcenter.wag.egov.egiz.sig.connectors.BKUPostConnection.doPostRequest(url, request_string); + return response_properties; + } + catch (Exception e) + { + throw new ConnectorException(320, e); + } + } + + /** + * Analyzes the sign response xml and extracts the signature data. + * + * @param response_properties + * The response properties containing the response String and + * transport related information. + * @return Returns the extracted data encapsulated in a SignatureObject. + * @throws ConnectorException + * f.e. + */ + public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException + { + log.debug("analyzeSignResponse:"); //$NON-NLS-1$ + + String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + + BKUHelper.checkResponseForError(response_string); + + SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter()); + + log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ + return so; + } + + /** + * Analyzes the verify response string. + * + * @param response_properties + * The response properties containing the response XML. + * @return Returns the SignatureResponse containing the verification result. + * @throws ConnectorException + * f.e. + */ + public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException + { + log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$ + + String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + + BKUHelper.checkResponseForError(response_string); + + SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string); + + log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$ + return signature_response; + } + + /** + * Holds environment configuration information like templates. + * + * @author wprinz + */ + public static class Environment + { + /** + * The configuration key of the sign keybox identifier. + */ + protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "bku.sign.KeyboxIdentifier"; //$NON-NLS-1$ + + /** + * The configuration key of the sign request template. + */ + protected static final String SIGN_REQUEST_TEMPLATE_KEY = "bku.sign.request.base64"; //$NON-NLS-1$ + + /** + * The configuration key of the sign URL. + */ + protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$ + + /** + * The configuration key of the verify request template. + */ + protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "bku.verify.request.base64"; //$NON-NLS-1$ + + /** + * The configuration key of the verify template. + */ + protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.base64"; //$NON-NLS-1$ + + /** + * The configuration key of the verify URL. + */ + protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$ + + /** + * The configuration key for the ECDSA cert alg property. + */ + protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$ + + /** + * The configuration key for the RSA cert alg property. + */ + protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$ + + protected String sign_keybox_identifier = null; + + protected String sign_request_template = null; + + protected String sign_url = null; + + protected String verify_request_template = null; + + protected String verify_template = null; + + protected String verify_url = null; + + protected String cert_alg_ecdsa = null; + + protected String cert_alg_rsa = null; + + /** + * Initializes the environment with a given profile. + * + * @param profile + * The configuration profile. + * @throws ConnectorException + * f.e. + */ + public Environment(String profile) throws ConnectorException + { + SettingsReader settings = null; + try + { + settings = SettingsReader.getInstance(); + } + catch (SettingsException e) + { + throw new ConnectorException(300, e); + } + + this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY); + + String sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY); + this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); + 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)); + if (this.verify_request_template == null) + { + // TODO make this a settings exception + 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)); + if (this.verify_template == null) + { + // TODO make this a settings exception + throw new ConnectorException(300, "Can not read the verify template"); //$NON-NLS-1$ + } + + this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY); + + this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY); + + this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY); + + } + + /** + * Returns the sign keybox identifier. + * + * @return Returns the sign keybox identifier. + */ + public String getSignKeyboxIdentifier() + { + return this.sign_keybox_identifier; + } + + /** + * Returns the sign request template. + * + * @return Returns the sign request template. + */ + public String getSignRequestTemplate() + { + return this.sign_request_template; + } + + /** + * Returns the sign URL. + * + * @return Returns the sign URL. + */ + public String getSignURL() + { + return this.sign_url; + } + + /** + * Returns the verify request template. + * + * @return Returns the verify request template. + */ + public String getVerifyRequestTemplate() + { + return this.verify_request_template; + } + + /** + * Returns the verify template. + * + * @return Returns the verify template. + */ + public String getVerifyTemplate() + { + return this.verify_template; + } + + /** + * Returns the verify URL. + * + * @return Returns the verify URL. + */ + public String getVerifyURL() + { + return this.verify_url; + } + + /** + * Returns the ecdsa cert alg property. + * + * @return Returns the ecdsa cert alg property. + */ + public String getCertAlgEcdsa() + { + return this.cert_alg_ecdsa; + } + + /** + * Returns the rsa cert alg property. + * + * @return Returns the rsa cert alg property. + */ + public String getCertAlgRsa() + { + return this.cert_alg_rsa; + } + + /** + * Reads the configuration entry given by the key, first from the given + * profile, if not found from the defaults. + * + * @param settings + * The settings. + * @param profile + * The profile. + * @param key + * The configuration key. + * @return Returns the configuration entry. + */ + public static String getConnectorValueFromProfile(SettingsReader settings, + String profile, String key) + { + String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$ + if (value == null) + { + value = settings.getValueFromKey(key); + } + return value; + } + } +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java new file mode 100644 index 0000000..e5278b9 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java @@ -0,0 +1,391 @@ +/** + * + */ +package at.knowcenter.wag.egov.egiz.sig.connectors.moa; + +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.exceptions.WebException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.tools.FileHelper; + +/** + * Connects to MOA providing the Data detached as LocRef on a local resource. + * + * @author wprinz + */ +public class DetachedLocRefMOAConnector +{ + /** + * 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. + * + *

+ * If confuguration parameters are not defined on that profile, the default + * parameters defined in the configuration are used. + *

+ * + * @param profile + * The profile from which the Environment should be assembled. + * @throws SettingsException + * f.e. + * @throws SignatureException + * f.e. + */ + public DetachedLocRefMOAConnector(String profile) throws SignatureException, SettingsException + { + this.environment = new Environment(profile); + } + + /** + * 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 SignatureException + * f.e. + */ + protected String prepareSignRequest(SignatureData data) throws SignatureException + { + log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$ + + String sign_request_template = this.environment.getSignRequestTemplate(); + + String sign_key_identifier = this.environment.getSignKeyIdentifier(); + String loc_ref_content = // "http://wwwx.google.at"; + // this doesn't work - MOA always complains that file system access is + // forbidden + "file:///C:/wprinz/Filer/egiz2/test.utf8.txt"; + 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; + } + + /** + * 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 SignatureException + * f.e. + */ + public SignSignatureObject analyzeSignResponse(Properties response_properties) throws SignatureException + { + log.debug("analyzeSignResponse:"); //$NON-NLS-1$ + + String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + + BKUHelper.checkResponseForError(response_string); + + // SignSignatureObject so = parseCreateXMLResponse(response_string); + + log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ + return null;// so; + } + + /** + * Performs a sign. + * + * @param data + * The data to be signed. + * @return Returns the signature object containing the signature data. + * @throws SignatureException + * f.e. + * @throws WebException + */ + public SignSignatureObject doSign(SignatureData data) throws SignatureException, WebException + { + 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, data); + + log.debug("response_string = " + response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY));; //$NON-NLS-1$ + SignSignatureObject sso = analyzeSignResponse(response_properties); + + // TODO this could be made more generic + sso.response_properties = response_properties; + + log.debug("doSign finished."); //$NON-NLS-1$ + return sso; + } + + protected Properties sendRequest(String url, String mode, + String request_string, SignatureData data) throws SignatureException + { + try + { + Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url); + return response_properties; + } + catch (Exception e) + { + SignatureException se = new SignatureException(320, e); + throw se; + } + } + + /** + * Holds environment configuration information like templates. + * + * @author wprinz + */ + public static class Environment + { + /** + * 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$ + + /** + * 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 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 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 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 SignatureException + * f.e. + */ + public Environment(String profile) throws SettingsException, SignatureException + { + SettingsReader settings = SettingsReader.getInstance(); + + 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)); + if (this.sign_request_template == null) + { + // TODO make this a settings exception + throw new SignatureException(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)); + if (this.verify_request_template == null) + { + // TODO make this a settings exception + throw new SignatureException(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)); + if (this.verify_template == null) + { + // TODO make this a settings exception + throw new SignatureException(300, "Can not read the verify template"); //$NON-NLS-1$ + } + + this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY); + + this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY); + + this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY); + + } + + /** + * 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 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; + } + + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java new file mode 100644 index 0000000..4e9dd04 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java @@ -0,0 +1,721 @@ +/** + * + */ +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.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.X509Cert; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.tools.CodingHelper; +import at.knowcenter.wag.egov.egiz.tools.FileHelper; + +/** + * @author wprinz + * + */ +public class EnvelopingBase64MOAConnector implements Connector +{ + /** + * 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; + + /** + * Constructor that builds the configuration environment for this connector + * according to the given profile. + * + *

+ * If confuguration parameters are not defined on that profile, the default + * parameters defined in the configuration are used. + *

+ * + * @param profile + * The profile from which the Environment should be assembled. + * @throws ConnectorException + * f.e. + */ + public EnvelopingBase64MOAConnector(String profile) throws ConnectorException + { + this.environment = new Environment(profile); + } + + /** + * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData) + */ + public SignSignatureObject doSign(SignatureData data) throws ConnectorException + { + log.debug("doSign:"); //$NON-NLS-1$ + + String sign_request_xml = prepareSignRequest(data); + 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); + + // TODO this could be made more generic + 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) throws ConnectorException + { + log.debug("doVerify:"); //$NON-NLS-1$ + + String verify_request_xml = prepareVerifyRequest(data, so); + 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(320, 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) throws ConnectorException + { + String verify_request_template = this.environment.getVerifyRequestTemplate(); + + String xml_content = null; + // TODO implement MOA + // if (sigObject.isMOASigned()) + // { + // MOAConnector moa_conn = new MOAConnector(); + // // get the MOA-template + // verify_template_str = moa_conn.getVerifyTemplate(normalizedText, + // sigObject); + // } + // else + // { + // get the BKU-template + xml_content = prepareXMLContent(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()); + + 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 = parseCreateXMLResponse(response_string); + + 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. + * + *

+ * This strongly rebuilds the XML content as retuned from a sign request. + *

+ * + * @param data + * The data. + * @param so + * The signature object containing the signature information. + * @return Returns the XML content. + * @throws ConnectorException + * f.e. + */ + public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException + { + log.debug("prepareXMLContent:"); //$NON-NLS-1$ + try + { + String verify_template = this.environment.getVerifyTemplate(); + + X509Certificate cert = so.getX509Certificate(); + String cert_alg = this.environment.getCertAlgEcdsa(); + if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$ + { + cert_alg = this.environment.getCertAlgRsa(); + } + + // cert alg replace + String verify_xml = verify_template.replaceFirst(TemplateReplaces.CERT_ALG_REPLACE, cert_alg); + + // data digest replace + { + byte[] data_value = data.getData(); + byte[] data_value_hash = CodingHelper.buildDigest(data_value); + 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); + String certDigest = CodingHelper.encodeBase64(cert_hash); + String x509_cert_string = CodingHelper.encodeBase64(der); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string); + + // Base64 content replace + String base64 = BKUHelper.prepareBase64Content(data); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64); + + // 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 = "= 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); + 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); + } + } + + + /** + * This method parses the MOA-Response string. It separates the + * SignatureValue, X509IssuerName, SigningTime, X509SerialNumber, + * X509Certificate, CertDigest and DigestValues. If the X509Certificate is + * extracted it would be stored in the certificates directory. + * + * @param xmlResponse + * the response string from the MOA sign-request + * @throws ConnectorException + * ErrorCode (303, 304) + * @see SignatureObject + * @see CodingHelper + * @see X509Cert + */ + public static SignSignatureObject parseCreateXMLResponse(String xmlResponse) throws ConnectorException + { + Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$ + Pattern sig_val_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$ + Pattern iss_nam_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$ + Pattern sig_tim_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$ + Pattern ser_num_p_e = Pattern.compile(""); //$NON-NLS-1$ + Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$ + Pattern sig_cer_p_e = Pattern.compile(""); //$NON-NLS-1$ + + // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>"); + // //$NON-NLS-1$ + // Pattern sig_cer_d_p_e = Pattern.compile(""); + // //$NON-NLS-1$ + // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>"); + // //$NON-NLS-1$ + // Pattern dig_val_p_e = Pattern.compile(""); + // //$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; + + so.id = null; + + return so; + } + + /** + * Holds environment configuration information like templates. + * + * @author wprinz + */ + public static class Environment + { + /** + * 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 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) throws ConnectorException + { + 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 = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY); + this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(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)); + 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)); + 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); + + } + + /** + * 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; + } + + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java new file mode 100644 index 0000000..11e7d2f --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java @@ -0,0 +1,152 @@ +/** + * + */ +package at.knowcenter.wag.egov.egiz.sig.connectors.moa; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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.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.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.isInfoEnabled()) + { + log.info(serviceMode); + log.info(endpointURL); + } + // Parser/DOMBuilder instanzieren + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + + // XML Datei in einen DOM-Baum umwandeln + ByteArrayInputStream bais = new ByteArrayInputStream(requestString.getBytes("UTF-8")); //$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(330, 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); + // } + + } + +} -- cgit v1.2.3