configure namespaces via signatureconfig

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1627985 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2014-09-27 17:49:09 +00:00
parent c9688fae89
commit b602302753
10 changed files with 69 additions and 108 deletions

View File

@ -17,11 +17,16 @@
package org.apache.poi.poifs.crypt.dsig;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XADES_132_NS;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.xml.crypto.URIDereferencer;
@ -73,7 +78,6 @@ public class SignatureConfig {
*/
private SignaturePolicyService signaturePolicyService;
private URIDereferencer uriDereferencer = new OOXMLURIDereferencer();
private String signatureNamespacePrefix;
private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;
private boolean includeEntireCertificateChain = true;
@ -130,6 +134,12 @@ public class SignatureConfig {
*/
EventListener signCreationListener = null;
/**
* Map of namespace uris to prefix
* If a mapping is specified, the corresponding elements will be prefixed
*/
Map<String,String> namespacePrefixes = new HashMap<String,String>();
protected void init(boolean onlyValidation) {
if (uriDereferencer == null) {
throw new EncryptedDocumentException("uriDereferencer is null");
@ -140,6 +150,15 @@ public class SignatureConfig {
if (uriDereferencer instanceof SignatureConfigurable) {
((SignatureConfigurable)uriDereferencer).setSignatureConfig(this);
}
if (namespacePrefixes.isEmpty()) {
/*
* OOo doesn't like ds namespaces so per default prefixing is off.
*/
// namespacePrefixes.put(XML_DIGSIG_NS, "");
namespacePrefixes.put(OO_DIGSIG_NS, "mdssi");
namespacePrefixes.put(XADES_132_NS, "xd");
}
if (onlyValidation) return;
if (signCreationListener == null) {
@ -149,7 +168,6 @@ public class SignatureConfig {
if (signCreationListener instanceof SignatureConfigurable) {
((SignatureConfigurable)signCreationListener).setSignatureConfig(this);
}
if (tspService != null) {
tspService.setSignatureConfig(this);
@ -263,12 +281,6 @@ public class SignatureConfig {
public void setSignatureDescription(String signatureDescription) {
this.signatureDescription = signatureDescription;
}
public String getSignatureNamespacePrefix() {
return signatureNamespacePrefix;
}
public void setSignatureNamespacePrefix(String signatureNamespacePrefix) {
this.signatureNamespacePrefix = signatureNamespacePrefix;
}
public String getCanonicalizationMethod() {
return canonicalizationMethod;
}
@ -403,4 +415,10 @@ public class SignatureConfig {
public void setSignCreationListener(EventListener signCreationListener) {
this.signCreationListener = signCreationListener;
}
public Map<String, String> getNamespacePrefixes() {
return namespacePrefixes;
}
public void setNamespacePrefixes(Map<String, String> namespacePrefixes) {
this.namespacePrefixes = namespacePrefixes;
}
}

View File

@ -24,6 +24,9 @@
package org.apache.poi.poifs.crypt.dsig;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_DIGSIG_NS;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS;
import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
@ -80,7 +83,6 @@ import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
@ -115,9 +117,6 @@ import org.xml.sax.SAXException;
public class SignatureInfo implements SignatureConfigurable {
public static final String XmlNS = "http://www.w3.org/2000/xmlns/";
public static final String XmlDSigNS = XMLSignature.XMLNS;
// see https://www.ietf.org/rfc/rfc3110.txt
// RSA/SHA1 SIG Resource Records
public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[]
@ -222,13 +221,14 @@ public class SignatureInfo implements SignatureConfigurable {
if (packageId.equals(el.getAttribute("Id"))) {
target.get().removeEventListener("DOMSubtreeModified", this, false);
el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS);
target.get().addEventListener("DOMSubtreeModified", this, false);
}
}
}
}
}
public void setSignatureConfig(SignatureConfig signatureConfig) {
this.signatureConfig = signatureConfig;
}
@ -439,18 +439,11 @@ public class SignatureInfo implements SignatureConfigurable {
xmlSignContext.setURIDereferencer(uriDereferencer);
}
xmlSignContext.putNamespacePrefix(
"http://schemas.openxmlformats.org/package/2006/digital-signature",
"mdssi");
String sigNsPrefix = signatureConfig.getSignatureNamespacePrefix();
if (sigNsPrefix != null) {
/*
* OOo doesn't like ds namespaces so per default prefixing is off.
*/
xmlSignContext.putNamespacePrefix(XmlDSigNS, sigNsPrefix);
for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());
}
xmlSignContext.setDefaultNamespacePrefix(signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();
/*
@ -500,8 +493,6 @@ public class SignatureInfo implements SignatureConfigurable {
/*
* ds:Signature Marshalling.
*/
xmlSignContext.setDefaultNamespacePrefix(signatureConfig.getSignatureNamespacePrefix());
// xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
xmlSignature.sign(xmlSignContext);
/*
@ -550,8 +541,8 @@ public class SignatureInfo implements SignatureConfigurable {
* usage.
*/
MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());
byte[] digestValue = jcaMessageDigest.digest(octets);
MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());
byte[] digestValue = md.digest(octets);
String description = signatureConfig.getSignatureDescription();
@ -577,7 +568,7 @@ public class SignatureInfo implements SignatureConfigurable {
/*
* Insert signature value into the ds:SignatureValue element
*/
NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");
NodeList sigValNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue");
if (sigValNl.getLength() != 1) {
throw new RuntimeException("preSign has to be called before postSign");
}
@ -596,12 +587,9 @@ public class SignatureInfo implements SignatureConfigurable {
protected void writeDocument(Document document) throws IOException, XmlException {
XmlOptions xo = new XmlOptions();
Map<String,String> namespaceMap = new HashMap<String,String>();
for (SignatureFacet sf : signatureConfig.getSignatureFacets()) {
Map<String,String> sfm = sf.getNamespacePrefixMapping();
if (sfm != null) {
namespaceMap.putAll(sfm);
}
}
for(Map.Entry<String,String> entry : signatureConfig.getNamespacePrefixes().entrySet()){
namespaceMap.put(entry.getValue(), entry.getKey());
}
xo.setSaveSuggestedPrefixes(namespaceMap);
xo.setUseDefaultNamespace();
@ -651,7 +639,7 @@ public class SignatureInfo implements SignatureConfigurable {
}
@SuppressWarnings("unchecked")
public static <T> List<T> safe(List<T> other) {
private static <T> List<T> safe(List<T> other) {
return other == null ? Collections.EMPTY_LIST : other;
}
}

View File

@ -5,7 +5,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
@ -60,9 +59,4 @@ public class EnvelopedSignatureFacet implements SignatureFacet {
references.add(reference);
}
@Override
public Map<String,String> getNamespacePrefixMapping() {
return null;
}
}

View File

@ -24,17 +24,13 @@
package org.apache.poi.poifs.crypt.dsig.facets;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dom.DOMCryptoContext;
@ -79,7 +75,7 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
throws MarshalException {
LOG.log(POILogger.DEBUG, "postSign");
NodeList nl = document.getElementsByTagNameNS(XmlDSigNS, "Object");
NodeList nl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "Object");
/*
* Make sure we insert right after the ds:SignatureValue element, just
@ -144,14 +140,14 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
Element n = document.getDocumentElement();
DOMSignContext domSignContext = new DOMSignContext(key, n, nextSibling);
DOMCryptoContext domCryptoContext = domSignContext;
domCryptoContext.putNamespacePrefix(XmlDSigNS, "xd");
domCryptoContext.putNamespacePrefix(XML_DIGSIG_NS, "xd");
DOMStructure domStructure = new DOMStructure(n);
// how to set nextSibling??? - marshal is ignoring nextSibling in DOMSignContext
domKeyInfo.marshal(domStructure, domCryptoContext);
// move keyinfo into the right place
if (nextSibling != null) {
NodeList kiNl = document.getElementsByTagNameNS(XmlDSigNS, "KeyInfo");
NodeList kiNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "KeyInfo");
if (kiNl.getLength() != 1) {
throw new RuntimeException("KeyInfo wasn't set");
}
@ -168,11 +164,4 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
// empty
}
public Map<String,String> getNamespacePrefixMapping() {
Map<String,String> map = new HashMap<String,String>();
// map.put("xd", XmlDSigNS);
return map;
}
}

View File

@ -24,8 +24,6 @@
package org.apache.poi.poifs.crypt.dsig.facets;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
import java.io.IOException;
@ -37,10 +35,8 @@ import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
@ -60,7 +56,6 @@ import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.ContentTypes;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
@ -91,9 +86,6 @@ public class OOXMLSignatureFacet implements SignatureFacet {
private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class);
public static final String OOXML_DIGSIG_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature";
public static final String OFFICE_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
private SignatureConfig signatureConfig;
public void setSignatureConfig(SignatureConfig signatureConfig) {
@ -133,7 +125,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);
Reference reference = signatureFactory.newReference
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
references.add(reference);
}
@ -238,7 +230,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
// TODO: find better method to have xmlbeans + export the prefix
Element n = (Element)document.importNode(ctTime.getDomNode(),true);
setPrefix(n, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
setPrefix(n, OO_DIGSIG_NS, "mdssi");
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();
signatureTimeContent.add(new DOMStructure(n));
@ -264,7 +256,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestAlgo().xmlSignUri);
Element n = (Element)document.importNode(ctSigV1.getDomNode(), true);
n.setAttributeNS(XmlNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
n.setAttributeNS(XML_NS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();
signatureInfoContent.add(new DOMStructure(n));
@ -283,7 +275,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);
Reference reference = signatureFactory.newReference
("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null);
("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
references.add(reference);
}
@ -360,14 +352,6 @@ public class OOXMLSignatureFacet implements SignatureFacet {
return false;
}
public Map<String,String> getNamespacePrefixMapping() {
Map<String,String> m = new HashMap<String,String>();
m.put("mdssi", OOXML_DIGSIG_NS);
m.put("xd", "http://uri.etsi.org/01903/v1.3.2#");
return m;
}
/**
* Office 2010 list of signed types (extensions).
*/

View File

@ -28,7 +28,6 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLObject;
@ -71,7 +70,7 @@ public class Office2010SignatureFacet implements SignatureFacet {
public void postSign(Document document, List<X509Certificate> signingCertificateChain)
throws XmlException {
// check for XAdES-BES
NodeList nl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties");
NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
if (nl.getLength() != 1) {
throw new IllegalArgumentException("no XAdES-BES extension present");
}
@ -92,8 +91,4 @@ public class Office2010SignatureFacet implements SignatureFacet {
Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true);
nl.item(0).getParentNode().replaceChild(n, nl.item(0));
}
public Map<String,String> getNamespacePrefixMapping() {
return null;
}
}

View File

@ -30,13 +30,15 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLObject;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable;
import org.apache.xmlbeans.XmlException;
import org.w3c.dom.Document;
@ -49,6 +51,14 @@ import org.w3c.dom.Document;
*/
public interface SignatureFacet extends SignatureConfigurable {
String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
String XML_DIGSIG_NS = XMLSignature.XMLNS;
String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE;
String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#";
String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#";
/**
* This method is being invoked by the XML signature service engine during
* pre-sign phase. Via this method a signature facet implementation can add
@ -83,6 +93,4 @@ public interface SignatureFacet extends SignatureConfigurable {
Document document
, List<X509Certificate> signingCertificateChain
) throws MarshalException, XmlException;
Map<String,String> getNamespacePrefixMapping();
}

View File

@ -24,7 +24,6 @@
package org.apache.poi.poifs.crypt.dsig.facets;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
import java.security.InvalidAlgorithmParameterException;
@ -213,8 +212,8 @@ public class XAdESSignatureFacet implements SignatureFacet {
// add XAdES ds:Object
List<XMLStructure> xadesObjectContent = new ArrayList<XMLStructure>();
Element qualDocEl = (Element)document.importNode(qualifyingProperties.getDomNode(), true);
qualDocEl.setAttributeNS(XmlNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#");
setPrefix(qualDocEl, "http://uri.etsi.org/01903/v1.3.2#", "xd");
qualDocEl.setAttributeNS(XML_NS, "xmlns:xd", XADES_132_NS);
setPrefix(qualDocEl, XADES_132_NS, "xd");
xadesObjectContent.add(new DOMStructure(qualDocEl));
XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null);
objects.add(xadesObject);
@ -298,12 +297,6 @@ public class XAdESSignatureFacet implements SignatureFacet {
this.dataObjectFormatMimeTypes.put(dsReferenceUri, mimetype);
}
public Map<String,String> getNamespacePrefixMapping() {
Map<String,String> map = new HashMap<String,String>();
map.put("xd", "http://uri.etsi.org/01903/v1.3.2#");
return map;
}
protected static void insertXChild(XmlObject root, XmlObject child) {
XmlCursor rootCursor = root.newCursor();
rootCursor.toEndToken();

View File

@ -24,7 +24,6 @@
package org.apache.poi.poifs.crypt.dsig.facets;
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertXChild;
import java.io.ByteArrayInputStream;
@ -42,7 +41,6 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.xml.crypto.dsig.CanonicalizationMethod;
@ -112,10 +110,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
public static final String XADES_NAMESPACE = "http://uri.etsi.org/01903/v1.3.2#";
public static final String XADES141_NAMESPACE = "http://uri.etsi.org/01903/v1.4.1#";
private SignatureConfig signatureConfig;
private String c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
@ -157,7 +151,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
QualifyingPropertiesType qualProps = null;
// check for XAdES-BES
NodeList qualNl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties");
NodeList qualNl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties");
if (qualNl.getLength() == 1) {
qualDoc = QualifyingPropertiesDocument.Factory.parse(qualNl.item(0));
qualProps = qualDoc.getQualifyingProperties();
@ -177,7 +171,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
// create the XAdES-T time-stamp
NodeList nlSigVal = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");
NodeList nlSigVal = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue");
if (nlSigVal.getLength() != 1) {
throw new IllegalArgumentException("SignatureValue is not set.");
}
@ -436,9 +430,4 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
}
}
}
public Map<String,String> getNamespacePrefixMapping() {
return null;
}
}

View File

@ -24,6 +24,9 @@
package org.apache.poi.poifs.crypt.dsig.services;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_DIGSIG_NS;
import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -161,7 +164,7 @@ public class RelationshipTransformService extends TransformService {
LOG.log(POILogger.DEBUG, "marshallParams(parent,context)");
DOMStructure domParent = (DOMStructure) parent;
Element parentNode = (Element)domParent.getNode();
// parentNode.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", DIGITAL_SIGNATURE);
// parentNode.setAttributeNS(XML_NS, "xmlns:mdssi", XML_DIGSIG_NS);
Document doc = parentNode.getOwnerDocument();
for (String sourceId : this.sourceIds) {