/** * */ package at.knowcenter.wag.egov.egiz.sig.connectors.bku; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; 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.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.TemplateReplaces; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; /** * Connects to the BKU using the detached multipart/formdata requests. * *

* This feature is available since BKU version 2.7.4. *

* * @author wprinz */ public class DetachedMultipartBKUConnector { /** * 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(DetachedMultipartBKUConnector.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 DetachedMultipartBKUConnector(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 prepareSignRequestDetached(SignatureData data) throws SignatureException { log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$ String sign_request_template = this.environment.getSignRequestTemplate(); String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier(); String mime_type = data.getMimeType(); if (log.isDebugEnabled()) { log.debug("signn keybox identifier = " + sign_keybox_identifier); //$NON-NLS-1$ log.debug("mime type = " + mime_type); //$NON-NLS-1$ } String sign_request_xml = sign_request_template.replace(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier); sign_request_xml = sign_request_xml.replace(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); // 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); SignSignatureObject so = parseCreateXMLResponse(response_string); 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) { if (sig_ids == null || sig_ids.length() == 0) { return null; } // int index = sig_ids.indexOf(PdfAS.IDS); // if (index < 0) // { // return null; // } // sig_ids = sig_ids.substring(index + PdfAS.IDS.length()); // // if (sig_ids == null || sig_ids.length() == 0) // { // return null; // } String[] ids_str = sig_ids.split("@"); String etsi_string = null; if (ids_str.length == 3) { etsi_string = ids_str[0]; String[] rest_ids = new String[] { ids_str[1], ids_str[2] }; ids_str = rest_ids; } String base = ids_str[0]; String[] ids = ids_str[1].split("-"); String[] real_ids = new String[6]; // the last one contains the etsi string real_ids[0] = base + "-" + ids[0]; real_ids[1] = "0-" + base + "-" + ids[1]; real_ids[2] = "0-" + base + "-" + ids[2]; real_ids[3] = "0-" + base + "-" + ids[3]; real_ids[4] = "0-" + base + "-" + ids[4]; real_ids[5] = etsi_string; if (log.isDebugEnabled()) { for (int id_idx = 0; id_idx < real_ids.length; id_idx++) { log.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]); } } return real_ids; } /** * Sends the request and data to the given URL. * *

* This method mainly handles communication exceptions. The actual send work * is done by doPostRequestMultipart. *

* * @see BKUPostConnection#doPostRequestMultipart(String, String, SignatureData) * * @param url * The URL to send the request to. * @param request_string * The request XML. * @param data * The data. * @return Returns the response properties containing among others the * response XML. * @throws SignatureException * f.e. */ protected Properties sendRequest(String url, String request_string, SignatureData data) throws SignatureException { try { Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data); return response_properties; } catch (Exception e) { SignatureException se = new SignatureException(320, e); throw se; } } /** * Performs a sign. * * @param data * The data to be signed. * @return Returns the signature object containing the signature data. * @throws SignatureException * f.e. */ public SignSignatureObject doSign(SignatureData data) throws SignatureException { log.debug("doSign:"); //$NON-NLS-1$ String sign_request_xml = prepareSignRequestDetached(data); log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$ String url = this.environment.getSignURL(); Properties response_properties = sendRequest(url, sign_request_xml, data); try { FileOutputStream fos = new FileOutputStream("C:\\wprinz\\Filer\\egiz2\\sign_response.utf8.xml"); //$NON-NLS-1$ fos.write(response_properties.getProperty("response_string").getBytes("UTF-8")); //$NON-NLS-1$ //$NON-NLS-2$ fos.close(); } catch (Exception e) { log.error(e); } 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; } /** * 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 SignatureException * f.e. */ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so) throws SignatureException { log.debug("doVerify:"); //$NON-NLS-1$ String verify_request_xml = prepareVerifyRequestDetached(data, so); log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$ try { FileOutputStream fos = new FileOutputStream("C:\\wprinz\\Filer\\egiz2\\verify_request.utf8.xml"); //$NON-NLS-1$ fos.write(verify_request_xml.getBytes("UTF-8")); //$NON-NLS-1$ fos.close(); } catch (Exception e) { log.error(e); } String url = this.environment.getVerifyURL(); Properties response_properties = sendRequest(url, verify_request_xml, data); SignatureResponse signature_response = analyzeVerifyResponse(response_properties); log.debug("doVerify finished."); //$NON-NLS-1$ return signature_response; } /** * Prepares the verify request xml to be sent using the verify request * template. * * @param data * The SignatureData. * @param so * The signature information object. * @return Returns the verify request xml to be sent. * @throws SignatureException * f.e. */ public String prepareVerifyRequestDetached(SignatureData data, SignSignatureObject so) throws SignatureException { 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; } /** * 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 SignatureException * f.e. */ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws SignatureException { 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.replace(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.replace(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.replace(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); // Qualified Properties replaces verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]); verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]); verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); // Signed Properties hash { final String ETSI_SIGNED_PROPERTIES_START_TAG = "= 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 SignatureException(310, e); } } /** * Analyzes the verify response string. * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. * @throws SignatureException * f.e. */ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException { log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); checkResponseForError(response_string); SignatureResponse signature_response = 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. * * @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.detached"; //$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.detached"; //$NON-NLS-1$ /** * The configuration key of the verify template. */ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.detached"; //$NON-NLS-1$ /** * The configuration key of the verify URL. */ protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$ /** * The configuration key for the ECDSA cert alg property. */ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$ /** * The configuration key for the RSA cert alg property. */ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$ protected String 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 SettingsException * f.e. * @throws SignatureException * f.e. */ public Environment(String profile) throws SettingsException, SignatureException { SettingsReader settings = SettingsReader.getInstance(); 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) { // 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 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; } } }