/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.societies.security.digsig.main;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import org.apache.xml.security.Init;
import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.security.digsig.DigsigException;
import org.societies.security.digsig.certs.SignatureCheck;
import org.societies.security.digsig.util.XmlManipulator;
import org.w3c.dom.Document;
/**
*
*
* @author Mitja Vardjan, based on code by Miroslav Pavleski
*
*/
public class XmlDSig {
private static Logger LOG = LoggerFactory.getLogger(XmlDSig.class);
/** Our certificate */
private X509Certificate cert;
private PrivateKey key;
public XmlDSig(X509Certificate cert, PrivateKey key) throws DigsigException {
this.cert = cert;
this.key = key;
if (cert == null || key == null) {
LOG.error("XmlDSig: cert and key must not be null: cert = {}, key = {}", cert, key);
throw new DigsigException("Cert or key is null");
}
try {
if (!Init.isInitialized()) {
Init.init();
}
} catch (Exception e) {
LOG.error("XmlDSig", "Failed to initialize", e);
return;
}
}
/**
* Please use one of other methods with same name.
*/
@Deprecated
public String signXml(String xml, String xmlNodeId) throws DigsigException {
LOG.debug("signXml(String, {}, {})", xmlNodeId);
ArrayList<String> idsToSign = new ArrayList<String>();
idsToSign.add(xmlNodeId);
xml = signXml(xml, idsToSign);
return xml;
}
public Document signXml(Document xml, String xmlNodeId) throws DigsigException {
LOG.debug("signXml(Document, {}, {})", xmlNodeId);
ArrayList<String> idsToSign = new ArrayList<String>();
idsToSign.add(xmlNodeId);
xml = signXml(xml, idsToSign);
return xml;
}
// TODO: move to PolicyNegotiator
public String getRequesterSignatureId(Document doc) {
SignatureCheck check = new SignatureCheck(doc);
XMLSignature xmlSig;
try {
xmlSig = check.getCustomerSignature();
} catch (DigsigException e) {
LOG.warn("getRequesterSignatureId", e);
return null;
}
return xmlSig.getElement().getAttribute("Id");
}
public Document signXml(Document doc, ArrayList<String> idsToSign) throws DigsigException {
XMLSignature sig;
LOG.debug("signXml({}, {})", doc, idsToSign);
try {
sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
doc.getDocumentElement().appendChild(sig.getElement());
Transforms transforms = new Transforms(doc);
// Also must use c14n
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
for (String id : idsToSign) {
LOG.debug("signXml(): adding URI of the resource to be signed: \"{}\"", id);
sig.addDocument("#" + id, transforms,
MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA1);
}
sig.addKeyInfo(cert);
sig.sign(key);
sig.getElement().setAttribute("Id", "Signature-" + UUID.randomUUID().toString());
return doc;
} catch (Exception e) {
LOG.error("signXml", "Failed while signing!", e);
throw new DigsigException(e);
}
}
public String signXml(String xml, ArrayList<String> idsToSign) throws DigsigException {
Document doc;
String str;
XmlManipulator xmlManipulator = new XmlManipulator();
xmlManipulator.load(xml);
doc = xmlManipulator.getDocument();
doc = signXml(doc, idsToSign);
xmlManipulator = new XmlManipulator();
xmlManipulator.setDocument(doc);
str = xmlManipulator.getDocumentAsString();
return str;
}
public HashMap<String, X509Certificate> verifyXml(String xml) throws DigsigException {
LOG.debug("verifyXml()");
HashMap<String, X509Certificate> result;
SignatureCheck sigCheck;
Document doc;
XmlManipulator xmlManipulator = new XmlManipulator();
xmlManipulator.load(xml);
doc = xmlManipulator.getDocument();
sigCheck = new SignatureCheck(doc);
try {
result = sigCheck.verifyAllSignatures();
} catch (DigsigException e) {
LOG.warn("verifyXml(): ", e);
throw e;
}
LOG.debug("verifyXml(): found {} signatures, all valid", result.size());
return result;
}
}