/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.knowcenter.wag.egov.egiz.sig.connectors.mocca; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper; import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject; import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.sig.SignatureObject; import at.knowcenter.wag.egov.egiz.sig.X509Cert; import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector.Environment; import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; /** * Provides useful methods for the usage of the open source cce mocca. * * @author tknall */ public final class MOCCAHelper { /** * Prevents this plain util class from being instantiated. */ private MOCCAHelper() { } /** * The logging implementation. */ private final static Log log = LogFactory.getLog(MOCCAHelper.class); /** * This method parses the signature creation response of the signature * device mocca. * * @param xmlResponse The response string. * @return Returns the parsed signature object holding the data. * @see SignatureObject * @see CodingHelper * @see X509Cert */ public final static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException { if (log.isDebugEnabled()) { log.debug("xmlResponse = " + xmlResponse); } Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName[^>]*>"); Pattern iss_nam_p_e = Pattern.compile(""); 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; Pattern signatureValuePattern = Pattern.compile("<(\\w+:)?SignatureValue( Id=\"[\\w-]+\")?>\\s*(.*)\\s*", Pattern.DOTALL); Matcher signatureValueMatcher = signatureValuePattern.matcher(xmlResponse); if (signatureValueMatcher.find()) { sig_val = signatureValueMatcher.group(3); if (sig_val != null) { sig_val = sig_val.replaceAll("\\s", ""); } } log.debug("sig_val = " + sig_val); // X509IssuerName String iss_nam = null; if (iss_nam_m_s.find() && iss_nam_m_e.find()) { iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start()); } log.debug("iss_nam = " + iss_nam); // X509SerialNumber String ser_num = null; if (ser_num_m_s.find() && ser_num_m_e.find()) { ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start())); } log.debug("ser_num = " + ser_num); // SigningTime String sig_tim = null; if (sig_tim_m_s.find() && sig_tim_m_e.find()) { sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start()); } log.debug("sig_tim = " + sig_tim); // X509Certificate X509Certificate cert = null; if (sig_cer_m_s.find() && sig_cer_m_e.find()) { String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start())); try { byte[] der = CodingHelper.decodeBase64(sig_cer); ByteArrayInputStream bais = new ByteArrayInputStream(der); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) cf.generateCertificate(bais); bais.close(); } catch (UnsupportedEncodingException e) { throw new ConnectorException(300, e); } catch (CertificateException e) { throw new ConnectorException(300, e); } catch (IOException e) { throw new ConnectorException(300, e); } } log.debug("X509Certificate = " + cert); if (log.isDebugEnabled()) { String cert_iss = cert.getIssuerDN().getName(); log.debug("certificate's issuer = " + cert_iss); log.debug("response's issuer = " + iss_nam); log.debug("issuer matches = " + cert_iss.equals(iss_nam)); log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); } SignSignatureObject so = new SignSignatureObject(); // extract Signature Id's String[] ids = extractIds(xmlResponse); // dferbas String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse); AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false); so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod()); String defaultCertAlg = environment.getDefaultAlgForCert(cert); if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) { // do not embed default alg algs = null; } String final_ids = id_formatter.formatIds(ids, algs); so.date = sig_tim; so.issuer = iss_nam; so.signatureValue = sig_val; so.x509Certificate = cert; so.id = final_ids; return so; } /** * Extraction of the id attributes from the xml response. * * @param xmlResponse The xml response. * @return The parsed id attributes. */ public final static String[] extractIds(String xmlResponse) { return new String[] { extractId(xmlResponse) }; } /** * There is only one special common part of all id attributes of this * connector that has to be stored. This method returns that single part. * * @param xmlResponse The xml response. * @return The parsed common part of all id attributes. */ private final static String extractId(String xmlResponse) { final Pattern ID_PATTERN = Pattern.compile("Id\\s*=\\s*\"\\s*Signature-([\\p{XDigit}]+)-\\d+\\s*\""); Matcher matcher = ID_PATTERN.matcher(xmlResponse); if (matcher.find() && matcher.groupCount() > 0) { return matcher.group(1); } return null; } }