/**
* 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;
}
}
}