You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2014/08/25 01:06:06 UTC
svn commit: r1620230 [2/2] - in
/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig:
facets/ services/ spi/
Modified: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java?rev=1620230&r1=1620229&r2=1620230&view=diff
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java (original)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java Sun Aug 24 23:06:05 2014
@@ -24,20 +24,25 @@
package org.apache.poi.poifs.crypt.dsig.services;
+import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;
+import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.security.InvalidAlgorithmParameterException;
-import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -45,7 +50,6 @@ import java.util.UUID;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.URIDereferencer;
import javax.xml.crypto.XMLStructure;
-import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Manifest;
@@ -57,11 +61,12 @@ import javax.xml.crypto.dsig.XMLSignCont
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
-import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.apache.jcp.xml.dsig.internal.dom.DOMReference;
+import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
@@ -74,11 +79,6 @@ import org.apache.poi.openxml4j.opc.Pack
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMReferenceIf;
-import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMSignedInfoIf;
-import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMXMLSignatureIf;
-import org.apache.poi.poifs.crypt.dsig.HorribleProxies.XMLSignatureIf;
-import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
@@ -87,19 +87,22 @@ import org.apache.poi.poifs.crypt.dsig.f
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;
-import org.apache.poi.poifs.crypt.dsig.spi.Constants;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.utils.Base64;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.w3.x2000.x09.xmldsig.SignatureDocument;
-import org.w3.x2000.x09.xmldsig.SignatureType;
-import org.w3.x2000.x09.xmldsig.SignatureValueType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MutationEvent;
import org.xml.sax.SAXException;
@@ -115,18 +118,18 @@ public class XmlSignatureService impleme
private String signatureId = "idPackageSignature";
private final HashAlgorithm hashAlgo;
private final OPCPackage opcPackage;
- private SignatureDocument sigDoc;
+ // private SignatureDocument sigDoc;
private XAdESSignatureFacet xadesSignatureFacet;
/**
* Main constructor.
*/
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
- this.signatureFacets = new LinkedList<SignatureFacet>();
+ this.signatureFacets = new ArrayList<SignatureFacet>();
this.signatureNamespacePrefix = null;
this.hashAlgo = digestAlgo;
this.opcPackage = opcPackage;
- this.sigDoc = null;
+ // this.sigDoc = null;
}
public void initFacets(Date clock) {
@@ -228,19 +231,20 @@ public class XmlSignatureService impleme
* @return
*/
// protected abstract OutputStream getSignedDocumentOutputStream();
-
- public DigestInfo preSign(List<DigestInfo> digestInfos,
+ @Override
+ public DigestInfo preSign(Document document, List<DigestInfo> digestInfos,
+ PrivateKey key,
List<X509Certificate> signingCertificateChain,
IdentityDTO identity, AddressDTO address, byte[] photo)
throws NoSuchAlgorithmException {
SignatureInfo.initXmlProvider();
-
+
LOG.log(POILogger.DEBUG, "preSign");
HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();
byte[] digestValue;
try {
- digestValue = getXmlSignatureDigestValue(hashAlgo, digestInfos, signingCertificateChain);
+ digestValue = getXmlSignatureDigestValue(document, hashAlgo, digestInfos, key, signingCertificateChain);
} catch (Exception e) {
throw new RuntimeException("XML signature error: " + e.getMessage(), e);
}
@@ -249,78 +253,74 @@ public class XmlSignatureService impleme
return new DigestInfo(digestValue, hashAlgo, description);
}
- public void postSign(byte[] signatureValue, List<X509Certificate> signingCertificateChain)
- throws IOException {
+ @Override
+ public void postSign(Document document, byte[] signatureValue, List<X509Certificate> signingCertificateChain)
+ throws IOException, MarshalException, ParserConfigurationException, XmlException {
LOG.log(POILogger.DEBUG, "postSign");
SignatureInfo.initXmlProvider();
/*
- * Retrieve the intermediate XML signature document from the temporary
- * data storage.
- */
- SignatureType sigType = sigDoc.getSignature();
-
- /*
* Check ds:Signature node.
*/
- if (!signatureId.equals(sigType.getId())) {
+ if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {
throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);
}
/*
* Insert signature value into the ds:SignatureValue element
*/
- SignatureValueType sigVal = sigType.getSignatureValue();
- sigVal.setByteArrayValue(signatureValue);
+ NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");
+ if (sigValNl.getLength() != 1) {
+ throw new RuntimeException("preSign has to be called before postSign");
+ }
+ sigValNl.item(0).setTextContent(Base64.encode(signatureValue));
/*
* Allow signature facets to inject their own stuff.
*/
for (SignatureFacet signatureFacet : this.signatureFacets) {
- signatureFacet.postSign(sigType, signingCertificateChain);
+ signatureFacet.postSign(document, signingCertificateChain);
}
- writeDocument();
+ writeDocument(document);
}
@SuppressWarnings("unchecked")
- private byte[] getXmlSignatureDigestValue(HashAlgorithm hashAlgo,
+ private byte[] getXmlSignatureDigestValue(Document document, HashAlgorithm hashAlgo,
List<DigestInfo> digestInfos,
+ PrivateKey privateKey,
List<X509Certificate> signingCertificateChain)
throws ParserConfigurationException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, MarshalException,
javax.xml.crypto.dsig.XMLSignatureException,
TransformerFactoryConfigurationError, TransformerException,
- IOException, SAXException, NoSuchProviderException, XmlException {
- /*
- * DOM Document construction.
- */
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true);
- Document doc = dbf.newDocumentBuilder().newDocument();
+ IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {
- /*
- * Signature context construction.
- */
- Key key = new Key() {
- private static final long serialVersionUID = 1L;
-
- public String getAlgorithm() {
- return null;
- }
-
- public byte[] getEncoded() {
- return null;
- }
-
- public String getFormat() {
- return null;
+ // it's necessary to explicitly set the mdssi namespace, but the sign() method has no
+ // normal way to interfere with, so we need to add the namespace under the hand ...
+ final EventTarget et = (EventTarget)document;
+ EventListener myModificationListener = new EventListener() {
+ @Override
+ public void handleEvent(Event e) {
+ if (e instanceof MutationEvent) {
+ MutationEvent mutEvt = (MutationEvent)e;
+ if (mutEvt.getTarget() instanceof Element) {
+ Element el = (Element)mutEvt.getTarget();
+ if ("idPackageObject".equals(el.getAttribute("Id"))) {
+ et.removeEventListener("DOMSubtreeModified", this, false);
+ el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
+ }
+ }
+ }
}
};
- // As of JDK 7, can't use sigDoc here directly, because the
- // setAttributeID will be called and it's not implemented in xmlbeans
- XMLSignContext xmlSignContext = new DOMSignContext(key, doc);
+ et.addEventListener("DOMSubtreeModified", myModificationListener, false);
+
+ /*
+ * Signature context construction.
+ */
+ XMLSignContext xmlSignContext = new DOMSignContext(privateKey, document);
URIDereferencer uriDereferencer = getURIDereferencer();
if (null != uriDereferencer) {
xmlSignContext.setURIDereferencer(uriDereferencer);
@@ -334,40 +334,34 @@ public class XmlSignatureService impleme
/*
* OOo doesn't like ds namespaces so per default prefixing is off.
*/
- xmlSignContext.putNamespacePrefix(
- javax.xml.crypto.dsig.XMLSignature.XMLNS,
- this.signatureNamespacePrefix);
+ xmlSignContext.putNamespacePrefix(XmlDSigNS, this.signatureNamespacePrefix);
}
- XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", "XMLDSig");
+ XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();
/*
* Add ds:References that come from signing client local files.
*/
- List<Reference> references = new LinkedList<Reference>();
+ List<Reference> references = new ArrayList<Reference>();
addDigestInfosAsReferences(digestInfos, signatureFactory, references);
/*
* Invoke the signature facets.
*/
- String localSignatureId;
- if (null == this.signatureId) {
+ String localSignatureId = this.signatureId;
+ if (localSignatureId == null) {
localSignatureId = "xmldsig-" + UUID.randomUUID().toString();
- } else {
- localSignatureId = this.signatureId;
}
- List<XMLObject> objects = new LinkedList<XMLObject>();
+ List<XMLObject> objects = new ArrayList<XMLObject>();
for (SignatureFacet signatureFacet : this.signatureFacets) {
- LOG.log(POILogger.DEBUG, "invoking signature facet: "
- + signatureFacet.getClass().getSimpleName());
- signatureFacet.preSign(signatureFactory, localSignatureId, signingCertificateChain, references, objects);
+ LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
+ signatureFacet.preSign(document, signatureFactory, localSignatureId, signingCertificateChain, references, objects);
}
/*
* ds:SignedInfo
*/
- SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(
- getSignatureMethod(hashAlgo), null);
+ SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(hashAlgo), null);
CanonicalizationMethod canonicalizationMethod = signatureFactory
.newCanonicalizationMethod(getCanonicalizationMethod(),
(C14NMethodParameterSpec) null);
@@ -385,20 +379,12 @@ public class XmlSignatureService impleme
/*
* ds:Signature Marshalling.
*/
- DOMXMLSignatureIf domXmlSignature;
- try {
- domXmlSignature = HorribleProxy.newProxy(DOMXMLSignatureIf.class, xmlSignature);
- } catch (Exception e) {
- throw new RuntimeException("DomXmlSignature instance error: " + e.getMessage(), e);
- }
-
- domXmlSignature.marshal(doc, this.signatureNamespacePrefix, (DOMCryptoContext) xmlSignContext);
+ xmlSignContext.setDefaultNamespacePrefix(this.signatureNamespacePrefix);
+ // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
+ xmlSignature.sign(xmlSignContext);
- registerIds(doc);
- Element el = doc.getElementById("idPackageObject");
- if (el != null) {
- el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
- }
+ registerIds(document);
+ // document.getElementById("idPackageObject").setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
/*
@@ -415,12 +401,7 @@ public class XmlSignatureService impleme
for (Reference manifestReference : manifestReferences) {
if (manifestReference.getDigestValue() != null) continue;
- DOMReferenceIf manifestDOMReference;
- try {
- manifestDOMReference = HorribleProxy.newProxy(DOMReferenceIf.class, manifestReference);
- } catch (Exception e) {
- throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);
- }
+ DOMReference manifestDOMReference = (DOMReference)manifestReference;
manifestDOMReference.digest(xmlSignContext);
}
}
@@ -431,12 +412,7 @@ public class XmlSignatureService impleme
*/
List<Reference> signedInfoReferences = signedInfo.getReferences();
for (Reference signedInfoReference : signedInfoReferences) {
- DOMReferenceIf domReference;
- try {
- domReference = HorribleProxy.newProxy(DOMReferenceIf.class, signedInfoReference);
- } catch (Exception e) {
- throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);
- }
+ DOMReference domReference = (DOMReference)signedInfoReference;
// ds:Reference with external digest value
if (domReference.getDigestValue() != null) continue;
@@ -447,20 +423,11 @@ public class XmlSignatureService impleme
/*
* Calculation of XML signature digest value.
*/
- DOMSignedInfoIf domSignedInfo;
- try {
- domSignedInfo = HorribleProxy.newProxy(DOMSignedInfoIf.class, signedInfo);
- } catch (Exception e) {
- throw new RuntimeException("DOMSignedInfo instance error: " + e.getMessage(), e);
- }
-
+ DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;
ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
domSignedInfo.canonicalize(xmlSignContext, dataStream);
byte[] octets = dataStream.toByteArray();
- sigDoc = SignatureDocument.Factory.parse(doc.getDocumentElement());
-
-
/*
* TODO: we could be using DigestOutputStream here to optimize memory
* usage.
@@ -478,13 +445,13 @@ public class XmlSignatureService impleme
* @param doc
*/
public void registerIds(Document doc) {
- NodeList nl = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Object");
+ NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");
registerIdAttribute(nl);
nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");
registerIdAttribute(nl);
}
- protected void registerIdAttribute(NodeList nl) {
+ public static void registerIdAttribute(NodeList nl) {
for (int i=0; i<nl.getLength(); i++) {
Element el = (Element)nl.item(i);
if (el.hasAttribute("Id")) {
@@ -493,12 +460,9 @@ public class XmlSignatureService impleme
}
}
- private void addDigestInfosAsReferences(List<DigestInfo> digestInfos,
- XMLSignatureFactory signatureFactory, List<Reference> references)
- throws NoSuchAlgorithmException,
- InvalidAlgorithmParameterException, MalformedURLException {
- if (digestInfos == null) return;
- for (DigestInfo digestInfo : digestInfos) {
+ private void addDigestInfosAsReferences(List<DigestInfo> digestInfos, XMLSignatureFactory signatureFactory, List<Reference> references)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MalformedURLException {
+ for (DigestInfo digestInfo : safe(digestInfos)) {
byte[] documentDigestValue = digestInfo.digestValue;
DigestMethod digestMethod = signatureFactory.newDigestMethod(
@@ -517,19 +481,12 @@ public class XmlSignatureService impleme
throw new RuntimeException("digest algo is null");
}
- XMLSignatureIf XmlSignature;
- try {
- XmlSignature = HorribleProxy.newProxy(XMLSignatureIf.class);
- } catch (Exception e) {
- throw new RuntimeException("JDK doesn't support XmlSignature", e);
- }
-
switch (hashAlgo) {
- case sha1: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA1();
- case sha256: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA256();
- case sha384: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA384();
- case sha512: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA512();
- case ripemd160: return XmlSignature.ALGO_ID_MAC_HMAC_RIPEMD160();
+ case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
+ case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
+ case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
+ case ripemd160: return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
default: break;
}
@@ -549,15 +506,11 @@ public class XmlSignatureService impleme
return null;
}
- public SignatureDocument getSignatureDocument() {
- return sigDoc;
- }
-
protected String getCanonicalizationMethod() {
return CanonicalizationMethod.INCLUSIVE;
}
- protected void writeDocument() throws IOException {
+ protected void writeDocument(Document document) throws IOException, XmlException {
XmlOptions xo = new XmlOptions();
Map<String,String> namespaceMap = new HashMap<String,String>();
for (SignatureFacet sf : this.signatureFacets) {
@@ -594,6 +547,7 @@ public class XmlSignatureService impleme
}
OutputStream os = sigPart.getOutputStream();
+ SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);
sigDoc.save(os, xo);
os.close();
@@ -612,4 +566,9 @@ public class XmlSignatureService impleme
sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);
}
+
+ @SuppressWarnings("unchecked")
+ public static <T> List<T> safe(List<T> other) {
+ return other == null ? Collections.EMPTY_LIST : other;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org