/** * 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.gv.egiz.pdfas.algorithmSuite; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Iterator; import java.util.List; 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.sig.connectors.ConnectorEnvironment; import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; /** * Utility class for handling dynamic algorithm suites * * @author dferbas * */ public class AlgorithmSuiteUtil { private static Log log = LogFactory.getLog(AlgorithmSuiteUtil.class); /** * Creates new verify_xml, evaluates algorithm suite and replaces methods in verify_xml * * @param algSuite out-param empty algorithm suite object * @param environment connector environment to load verify template * @param so signsignator object * @return verify xml */ public static String evaluateReplaceAlgs(AlgorithmSuiteObject algSuite, ConnectorEnvironment environment, SignSignatureObject so) { String verify_template = environment.getVerifyTemplate(); String cert_alg = null; String verify_xml = null; X509Certificate cert = so.getX509Certificate(); String ids_string = so.getSigID(); //AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(ids_string); algSuite.parseFrom(ids_string, true); // 1. is specified in sig_id if (algSuite.isSpecified()) { log.debug("Algorithm suite defined as parameter. Using new dynamic template replacement."); cert_alg = AlgorithmMapper.getUri(algSuite.getSignatureMethod()); // 2. is specified in /alg replace -> baik } else if (so.getSigAlgorithm() != null && so.getSigAlgorithm().length() > 0) { String algAbbr = AlgorithmMapper.getAbbreviation(so.getSigAlgorithm()); algSuite.parseFrom(algAbbr, false); if (algSuite.isSpecified()) { log.debug("Algorithm /alg available. Using: " + so.getSigAlgorithm()); cert_alg = AlgorithmMapper.getUri(algSuite.getSignatureMethod()); // algSuite.setCertDigestMethod("sha1"); //algSuite.setPropertiesDigestMethod("sha1"); } } // 3. default if (cert_alg == null) { log.debug("NO algorithm suite defined. Using default old static algorithm."); cert_alg = environment.getCertAlgEcdsa(); if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$ { cert_alg = environment.getCertAlgRsa(); } // fix digest methods to sha1 for old algorithm String oldDigest = "sha1"; algSuite.setCertDigestMethod(oldDigest); algSuite.setDataDigestMethod(oldDigest); algSuite.setPropertiesDigestMethod(oldDigest); } // cert alg replace verify_xml = verify_template.replaceFirst(TemplateReplaces.CERT_ALG_REPLACE, cert_alg); // digest method replaces verify_xml = verify_xml.replaceFirst(TemplateReplaces.DATA_DIGEST_REPLACE, AlgorithmMapper.getUri(algSuite.getDataDigestMethod())); verify_xml = verify_xml.replaceFirst(TemplateReplaces.PROPERTIES_DIGEST_REPLACE, AlgorithmMapper.getUri(algSuite.getPropertiesDigestMethod())); verify_xml = verify_xml.replaceFirst(TemplateReplaces.CERT_DIGEST_REPLACE, AlgorithmMapper.getUri(algSuite.getCertDigestMethod())); return verify_xml; } /** * Extract algorithm suite as optimized string from CreateXMLSignatureResponse * * @param xmlResponse * @return algorith suite string */ public static String extractAlgorithmSuiteString(String xmlResponse) { String elem = findFirstElement(xmlResponse, "SignatureMethod"); String alg = findAttributeValue(elem, "Algorithm"); List digAlgs = findAllAttributeValues(xmlResponse, "DigestMethod", "Algorithm"); digAlgs.add(0, AlgorithmMapper.getHashUriFromSuite(alg)); reduceDigestAlgs(digAlgs); digAlgs.remove(0); return createSigDevString(alg, digAlgs); } public static boolean isDefaultCertAlg(String algsString, String defaultCertAlg) { return AlgorithmMapper.getAbbreviation(defaultCertAlg).equals(algsString); } private static String createSigDevString(String suite, List digAlgs) { StringBuffer sb = new StringBuffer(AlgorithmMapper.getAbbreviation(suite)); for (Iterator iterator = digAlgs.iterator(); iterator.hasNext();) { String dig = (String) iterator.next(); sb.append(":").append(AlgorithmMapper.getAbbreviation(dig)); } return sb.toString(); } private static String findAttributeValue(String elemContent, String attrName) { String sig_alg = removeAllWhitespace(elemContent); attrName += "=\""; int start = sig_alg.indexOf(attrName) + attrName.length(); int end = sig_alg.indexOf("\"", start); return sig_alg.substring(start, end); } private static String findFirstElement(String xml, String elemName) { Pattern p = Pattern.compile("<[\\w]*:?" + elemName); Matcher m = p.matcher(xml); if (m.find()) { int start = m.start(); int end = xml.indexOf("/>", start) + 2; return xml.substring(start, end); } return null; } private static List findElements(String xml, String elemName) { Pattern p = Pattern.compile("<[\\w]*:?" + elemName); Matcher m = p.matcher(xml); ArrayList res = new ArrayList(); while (m.find()) { int start = m.start(); int end = xml.indexOf("/>", start) + 2; res.add(xml.substring(start, end)); } return res; } private static String findAttributeValue(String xmlContent, String elemName, String attrName) { String elemCont = findFirstElement(xmlContent, elemName); return findAttributeValue(elemCont, attrName); } private static List findAllAttributeValues(String xmlContent, String elemName, String attrName) { List elemConts = findElements(xmlContent, elemName); ArrayList res = new ArrayList(); for (int i = 0; i < elemConts.size(); i++) { res.add(findAttributeValue((String) elemConts.get(i), attrName)); } return res; } /** * Helper method to remove whitespaces from a string * @param str * @return */ public static String removeAllWhitespace(String str) { return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$ } private static void reduceDigestAlgs(List digestAlgs) { if (digestAlgs == null) return; reduceDigestAlgsRec(digestAlgs, digestAlgs.size() - 1); } private static void reduceDigestAlgsRec(List digestAlgs, int act) { if (act <= 0) return; else if (digestAlgs.get(act - 1).equals(digestAlgs.get(act))) { // reduce digestAlgs.remove(act); reduceDigestAlgsRec(digestAlgs, act - 1); } else { return; } } }