package at.knowcenter.wag.egov.egiz.sig.connectors.mocca; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.sig.SignatureObject; import at.knowcenter.wag.egov.egiz.sig.X509Cert; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; /** * Provides useful methods for the usage of the open source cce mocca. * * @author tknall */ public final class MOCCAHelper { /** * Prevents this plain util class from being instantiated. */ private MOCCAHelper() { } /** * The logging implementation. */ private final static Log log = LogFactory.getLog(MOCCAHelper.class); /** * This method parses the signature creation response of the signature * device mocca. * * @param xmlResponse The response string. * @return Returns the parsed signature object holding the data. * @see SignatureObject * @see CodingHelper * @see X509Cert */ public final static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter) throws ConnectorException { if (log.isDebugEnabled()) { log.debug("xmlResponse = " + xmlResponse); } Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName[^>]*>"); Pattern iss_nam_p_e = Pattern.compile(""); Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); Pattern sig_tim_p_e = Pattern.compile(""); Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber[^>]*>"); Pattern ser_num_p_e = Pattern.compile(""); Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); Pattern sig_cer_p_e = Pattern.compile(""); Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse); Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse); Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse); Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse); Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse); Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse); Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse); Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse); // SignatureValue String sig_val = null; Matcher signatureValueMatcher = Pattern.compile("<(\\w+:)?SignatureValue( Id=\"[\\w-]+\")?>\\s*(.*)\\s*").matcher(xmlResponse); if (signatureValueMatcher.find()) { sig_val = signatureValueMatcher.group(3); } log.debug("sig_val = " + sig_val); // X509IssuerName String iss_nam = null; if (iss_nam_m_s.find() && iss_nam_m_e.find()) { iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); } log.debug("iss_nam = " + iss_nam); // X509SerialNumber String ser_num = null; if (ser_num_m_s.find() && ser_num_m_e.find()) { ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start())); } log.debug("ser_num = " + ser_num); // SigningTime String sig_tim = null; if (sig_tim_m_s.find() && sig_tim_m_e.find()) { sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start()); } log.debug("sig_tim = " + sig_tim); // X509Certificate X509Certificate cert = null; if (sig_cer_m_s.find() && sig_cer_m_e.find()) { String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start())); try { byte[] der = CodingHelper.decodeBase64(sig_cer); ByteArrayInputStream bais = new ByteArrayInputStream(der); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) cf.generateCertificate(bais); bais.close(); } catch (UnsupportedEncodingException e) { throw new ConnectorException(300, e); } catch (CertificateException e) { throw new ConnectorException(300, e); } catch (IOException e) { throw new ConnectorException(300, e); } } log.debug("X509Certificate = " + cert); if (log.isDebugEnabled()) { String cert_iss = cert.getIssuerDN().getName(); log.debug("certificate's issuer = " + cert_iss); log.debug("response's issuer = " + iss_nam); log.debug("issuer matches = " + cert_iss.equals(iss_nam)); log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); } // extract Signature Id's String[] ids = extractIds(xmlResponse); 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; } /** * Extraction of the id attributes from the xml response. * * @param xmlResponse The xml response. * @return The parsed id attributes. */ public final static String[] extractIds(String xmlResponse) { return new String[] { extractId(xmlResponse) }; } /** * There is only one special common part of all id attributes of this * connector that has to be stored. This method returns that single part. * * @param xmlResponse The xml response. * @return The parsed common part of all id attributes. */ private final static String extractId(String xmlResponse) { final Pattern ID_PATTERN = Pattern.compile("Id\\s*=\\s*\"\\s*Signature-([\\p{XDigit}]+)-\\d+\\s*\""); Matcher matcher = ID_PATTERN.matcher(xmlResponse); if (matcher.find() && matcher.groupCount() > 0) { return matcher.group(1); } return null; } }