diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2014-11-07 01:16:21 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2014-11-07 01:16:21 +0000 |
commit | 08c876f7926e7b824589f5e672fcc1412af002c3 (patch) | |
tree | d2df7c15a4e285d54f76166a713ff57caac68153 | |
parent | a6216f43837f96ab81a65b352d2cb41fd666e554 (diff) | |
download | poi-08c876f7926e7b824589f5e672fcc1412af002c3.tar.gz poi-08c876f7926e7b824589f5e672fcc1412af002c3.zip |
another signature ubuntu jdk6 bug fix ... and offline/online handling
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1637283 13f79535-47bb-0310-9956-ffa450edef68
3 files changed, 183 insertions, 157 deletions
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java index 59d7f44d28..bf9dae94f5 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java @@ -57,6 +57,7 @@ import javax.xml.crypto.dsig.XMLSignContext; import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.XMLValidateContext;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
@@ -230,9 +231,25 @@ public class SignatureInfo implements SignatureConfigurable { DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());
+ brokenJvmWorkaround(domValidateContext);
XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory();
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
+
+ // TODO: replace with property when xml-sec patch is applied
+ for (Reference ref : (List<Reference>)xmlSignature.getSignedInfo().getReferences()) {
+ SignatureFacet.brokenJvmWorkaround(ref);
+ }
+ for (XMLObject xo : (List<XMLObject>)xmlSignature.getObjects()) {
+ for (XMLStructure xs : (List<XMLStructure>)xo.getContent()) {
+ if (xs instanceof Manifest) {
+ for (Reference ref : (List<Reference>)((Manifest)xs).getReferences()) {
+ SignatureFacet.brokenJvmWorkaround(ref);
+ }
+ }
+ }
+ }
+
boolean valid = xmlSignature.validate(domValidateContext);
if (valid) {
@@ -241,8 +258,6 @@ public class SignatureInfo implements SignatureConfigurable { }
return valid;
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new JvmBrokenException(e);
} catch (Exception e) {
LOG.log(POILogger.ERROR, "error in marshalling and validating the signature", e);
return false;
@@ -399,149 +414,141 @@ public class SignatureInfo implements SignatureConfigurable { @SuppressWarnings("unchecked")
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)
throws XMLSignatureException, MarshalException {
- try {
- signatureConfig.init(false);
-
- // 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 ...
- EventTarget target = (EventTarget)document;
- EventListener creationListener = signatureConfig.getSignatureMarshalListener();
- if (creationListener != null) {
- if (creationListener instanceof SignatureMarshalListener) {
- ((SignatureMarshalListener)creationListener).setEventTarget(target);
- }
- SignatureMarshalListener.setListener(target, creationListener, true);
- }
-
- /*
- * Signature context construction.
- */
- XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);
- URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();
- if (null != uriDereferencer) {
- xmlSignContext.setURIDereferencer(uriDereferencer);
- }
-
- for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
- xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());
- }
- xmlSignContext.setDefaultNamespacePrefix("");
- // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
-
- // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012
- Provider bcProv = Security.getProvider("BC");
- if (bcProv != null) {
- xmlSignContext.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);
- }
-
- XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();
-
- /*
- * Add ds:References that come from signing client local files.
- */
- List<Reference> references = new ArrayList<Reference>();
- for (DigestInfo digestInfo : safe(digestInfos)) {
- byte[] documentDigestValue = digestInfo.digestValue;
-
- String uri = new File(digestInfo.description).getName();
- Reference reference = SignatureFacet.newReference
- (uri, null, null, null, documentDigestValue, signatureConfig);
- references.add(reference);
- }
-
- /*
- * Invoke the signature facets.
- */
- List<XMLObject> objects = new ArrayList<XMLObject>();
- for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
- LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
- signatureFacet.preSign(document, references, objects);
- }
-
- /*
- * ds:SignedInfo
- */
- SignedInfo signedInfo;
- try {
- SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
- (signatureConfig.getSignatureMethodUri(), null);
- CanonicalizationMethod canonicalizationMethod = signatureFactory
- .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
- (C14NMethodParameterSpec) null);
- signedInfo = signatureFactory.newSignedInfo(
- canonicalizationMethod, signatureMethod, references);
- } catch (GeneralSecurityException e) {
- throw new XMLSignatureException(e);
+ signatureConfig.init(false);
+
+ // 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 ...
+ EventTarget target = (EventTarget)document;
+ EventListener creationListener = signatureConfig.getSignatureMarshalListener();
+ if (creationListener != null) {
+ if (creationListener instanceof SignatureMarshalListener) {
+ ((SignatureMarshalListener)creationListener).setEventTarget(target);
}
-
- /*
- * JSR105 ds:Signature creation
- */
- String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";
- javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory
- .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),
- signatureValueId);
-
- /*
- * ds:Signature Marshalling.
- */
- xmlSignature.sign(xmlSignContext);
-
- /*
- * Completion of undigested ds:References in the ds:Manifests.
- */
- for (XMLObject object : objects) {
- LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());
- List<XMLStructure> objectContentList = object.getContent();
- for (XMLStructure objectContent : objectContentList) {
- LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());
- if (!(objectContent instanceof Manifest)) continue;
- Manifest manifest = (Manifest) objectContent;
- List<Reference> manifestReferences = manifest.getReferences();
- for (Reference manifestReference : manifestReferences) {
- if (manifestReference.getDigestValue() != null) continue;
-
- DOMReference manifestDOMReference = (DOMReference)manifestReference;
- manifestDOMReference.digest(xmlSignContext);
- }
+ SignatureMarshalListener.setListener(target, creationListener, true);
+ }
+
+ /*
+ * Signature context construction.
+ */
+ XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);
+ URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();
+ if (null != uriDereferencer) {
+ xmlSignContext.setURIDereferencer(uriDereferencer);
+ }
+
+ for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
+ xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());
+ }
+ xmlSignContext.setDefaultNamespacePrefix("");
+ // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
+
+ brokenJvmWorkaround(xmlSignContext);
+
+ XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();
+
+ /*
+ * Add ds:References that come from signing client local files.
+ */
+ List<Reference> references = new ArrayList<Reference>();
+ for (DigestInfo digestInfo : safe(digestInfos)) {
+ byte[] documentDigestValue = digestInfo.digestValue;
+
+ String uri = new File(digestInfo.description).getName();
+ Reference reference = SignatureFacet.newReference
+ (uri, null, null, null, documentDigestValue, signatureConfig);
+ references.add(reference);
+ }
+
+ /*
+ * Invoke the signature facets.
+ */
+ List<XMLObject> objects = new ArrayList<XMLObject>();
+ for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {
+ LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());
+ signatureFacet.preSign(document, references, objects);
+ }
+
+ /*
+ * ds:SignedInfo
+ */
+ SignedInfo signedInfo;
+ try {
+ SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
+ (signatureConfig.getSignatureMethodUri(), null);
+ CanonicalizationMethod canonicalizationMethod = signatureFactory
+ .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
+ (C14NMethodParameterSpec) null);
+ signedInfo = signatureFactory.newSignedInfo(
+ canonicalizationMethod, signatureMethod, references);
+ } catch (GeneralSecurityException e) {
+ throw new XMLSignatureException(e);
+ }
+
+ /*
+ * JSR105 ds:Signature creation
+ */
+ String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";
+ javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory
+ .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),
+ signatureValueId);
+
+ /*
+ * ds:Signature Marshalling.
+ */
+ xmlSignature.sign(xmlSignContext);
+
+ /*
+ * Completion of undigested ds:References in the ds:Manifests.
+ */
+ for (XMLObject object : objects) {
+ LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());
+ List<XMLStructure> objectContentList = object.getContent();
+ for (XMLStructure objectContent : objectContentList) {
+ LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());
+ if (!(objectContent instanceof Manifest)) continue;
+ Manifest manifest = (Manifest) objectContent;
+ List<Reference> manifestReferences = manifest.getReferences();
+ for (Reference manifestReference : manifestReferences) {
+ if (manifestReference.getDigestValue() != null) continue;
+
+ DOMReference manifestDOMReference = (DOMReference)manifestReference;
+ manifestDOMReference.digest(xmlSignContext);
}
}
-
- /*
- * Completion of undigested ds:References.
- */
- List<Reference> signedInfoReferences = signedInfo.getReferences();
- for (Reference signedInfoReference : signedInfoReferences) {
- DOMReference domReference = (DOMReference)signedInfoReference;
-
- // ds:Reference with external digest value
- if (domReference.getDigestValue() != null) continue;
-
- domReference.digest(xmlSignContext);
- }
-
- /*
- * Calculation of XML signature digest value.
- */
- DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;
- ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
- domSignedInfo.canonicalize(xmlSignContext, dataStream);
- byte[] octets = dataStream.toByteArray();
-
- /*
- * TODO: we could be using DigestOutputStream here to optimize memory
- * usage.
- */
-
- MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());
- byte[] digestValue = md.digest(octets);
-
+ }
+
+ /*
+ * Completion of undigested ds:References.
+ */
+ List<Reference> signedInfoReferences = signedInfo.getReferences();
+ for (Reference signedInfoReference : signedInfoReferences) {
+ DOMReference domReference = (DOMReference)signedInfoReference;
+
+ // ds:Reference with external digest value
+ if (domReference.getDigestValue() != null) continue;
- String description = signatureConfig.getSignatureDescription();
- return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new JvmBrokenException(e);
+ domReference.digest(xmlSignContext);
}
+
+ /*
+ * Calculation of XML signature digest value.
+ */
+ DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;
+ ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
+ domSignedInfo.canonicalize(xmlSignContext, dataStream);
+ byte[] octets = dataStream.toByteArray();
+
+ /*
+ * TODO: we could be using DigestOutputStream here to optimize memory
+ * usage.
+ */
+
+ MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());
+ byte[] digestValue = md.digest(octets);
+
+
+ String description = signatureConfig.getSignatureDescription();
+ return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);
}
/**
@@ -651,10 +658,20 @@ public class SignatureInfo implements SignatureConfigurable { private static <T> List<T> safe(List<T> other) {
return other == null ? Collections.EMPTY_LIST : other;
}
-
- private static class JvmBrokenException extends EncryptedDocumentException {
- public JvmBrokenException(Throwable cause) {
- super("\"your JVM is just too broken\" - check https://bugzilla.redhat.com/show_bug.cgi?id=1155012 if this applies to the stacktrace ...", cause);
- }
+
+ private void brokenJvmWorkaround(XMLSignContext context) {
+ // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012
+ Provider bcProv = Security.getProvider("BC");
+ if (bcProv != null) {
+ context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);
+ }
+ }
+
+ private void brokenJvmWorkaround(XMLValidateContext context) {
+ // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012
+ Provider bcProv = Security.getProvider("BC");
+ if (bcProv != null) {
+ context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);
+ }
}
}
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java index c21a4c8525..21922fe1c7 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java @@ -150,6 +150,16 @@ public abstract class SignatureFacet implements SignatureConfigurable { reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue);
}
+ brokenJvmWorkaround(reference);
+
+ return reference;
+ }
+
+ // helper method ... will be removed soon
+ public static void brokenJvmWorkaround(Reference reference) {
+ DigestMethod digestMethod = reference.getDigestMethod();
+ String digestMethodUri = digestMethod.getAlgorithm();
+
// workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012
// overwrite standard message digest, if a digest <> SHA1 is used
Provider bcProv = Security.getProvider("BC");
@@ -166,7 +176,5 @@ public abstract class SignatureFacet implements SignatureConfigurable { LOG.log(POILogger.WARN, "Can't overwrite message digest (workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012)", e);
}
}
-
- return reference;
}
}
\ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java index 7c185721e7..3628ac75b4 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java @@ -50,7 +50,6 @@ import java.util.Iterator; import java.util.List;
import java.util.TimeZone;
-import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
@@ -299,7 +298,9 @@ public class TestSignatureInfo { signatureConfig.addSignatureFacet(new XAdESSignatureFacet());
signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet());
- boolean mockTsp = false;
+ // check for internet
+ Process p1 = Runtime.getRuntime().exec("ping www.google.com");
+ boolean mockTsp = (p1.waitFor() == 1);
// http://timestamping.edelweb.fr/service/tsp
// http://tsa.belgium.be/connect
// http://timestamp.comodoca.com/authenticode
@@ -471,14 +472,14 @@ public class TestSignatureInfo { si.confirmSignature();
boolean b = si.verifySignature();
assertTrue("Signature not correctly calculated for " + ha, b);
- } catch (EncryptedDocumentException e) {
- // see http://apache-poi.1045710.n5.nabble.com/org-apache-poi-poifs-crypt-TestSignatureInfo-failing-on-trunk-on-Java-6-tp5717032.html
- Throwable cause = e.getCause();
- if (cause instanceof ArrayIndexOutOfBoundsException) {
- LOG.log(POILogger.ERROR, "ignoring AIOOBE - hopefully a SHA2 bug ...", e);
- } else {
- throw e;
- }
+// } catch (EncryptedDocumentException e) {
+// // see http://apache-poi.1045710.n5.nabble.com/org-apache-poi-poifs-crypt-TestSignatureInfo-failing-on-trunk-on-Java-6-tp5717032.html
+// Throwable cause = e.getCause();
+// if (cause instanceof ArrayIndexOutOfBoundsException) {
+// LOG.log(POILogger.ERROR, "ignoring AIOOBE - hopefully a SHA2 bug ...", e);
+// } else {
+// throw e;
+// }
} finally {
if (pkg != null) pkg.close();
}
|