import javax.xml.crypto.dsig.XMLSignature;\r
import javax.xml.crypto.dsig.XMLSignatureException;\r
import javax.xml.crypto.dsig.XMLSignatureFactory;\r
+import javax.xml.crypto.dsig.XMLValidateContext;\r
import javax.xml.crypto.dsig.dom.DOMSignContext;\r
import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer());\r
+ brokenJvmWorkaround(domValidateContext);\r
\r
XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory();\r
XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);\r
+ \r
+ // TODO: replace with property when xml-sec patch is applied\r
+ for (Reference ref : (List<Reference>)xmlSignature.getSignedInfo().getReferences()) {\r
+ SignatureFacet.brokenJvmWorkaround(ref);\r
+ }\r
+ for (XMLObject xo : (List<XMLObject>)xmlSignature.getObjects()) {\r
+ for (XMLStructure xs : (List<XMLStructure>)xo.getContent()) {\r
+ if (xs instanceof Manifest) {\r
+ for (Reference ref : (List<Reference>)((Manifest)xs).getReferences()) {\r
+ SignatureFacet.brokenJvmWorkaround(ref);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
boolean valid = xmlSignature.validate(domValidateContext);\r
\r
if (valid) {\r
}\r
\r
return valid;\r
- } catch (ArrayIndexOutOfBoundsException e) {\r
- throw new JvmBrokenException(e);\r
} catch (Exception e) {\r
LOG.log(POILogger.ERROR, "error in marshalling and validating the signature", e);\r
return false;\r
@SuppressWarnings("unchecked")\r
public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
throws XMLSignatureException, MarshalException {\r
- try {\r
- signatureConfig.init(false);\r
- \r
- // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
- // normal way to interfere with, so we need to add the namespace under the hand ...\r
- EventTarget target = (EventTarget)document;\r
- EventListener creationListener = signatureConfig.getSignatureMarshalListener();\r
- if (creationListener != null) {\r
- if (creationListener instanceof SignatureMarshalListener) {\r
- ((SignatureMarshalListener)creationListener).setEventTarget(target);\r
- }\r
- SignatureMarshalListener.setListener(target, creationListener, true);\r
- }\r
- \r
- /*\r
- * Signature context construction.\r
- */\r
- XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
- URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
- if (null != uriDereferencer) {\r
- xmlSignContext.setURIDereferencer(uriDereferencer);\r
- }\r
- \r
- for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {\r
- xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());\r
- }\r
- xmlSignContext.setDefaultNamespacePrefix("");\r
- // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));\r
- \r
- // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
- Provider bcProv = Security.getProvider("BC");\r
- if (bcProv != null) {\r
- xmlSignContext.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
- } \r
- \r
- XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();\r
- \r
- /*\r
- * Add ds:References that come from signing client local files.\r
- */\r
- List<Reference> references = new ArrayList<Reference>();\r
- for (DigestInfo digestInfo : safe(digestInfos)) {\r
- byte[] documentDigestValue = digestInfo.digestValue;\r
- \r
- String uri = new File(digestInfo.description).getName();\r
- Reference reference = SignatureFacet.newReference\r
- (uri, null, null, null, documentDigestValue, signatureConfig);\r
- references.add(reference);\r
- }\r
- \r
- /*\r
- * Invoke the signature facets.\r
- */\r
- List<XMLObject> objects = new ArrayList<XMLObject>();\r
- for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
- LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
- signatureFacet.preSign(document, references, objects);\r
- }\r
- \r
- /*\r
- * ds:SignedInfo\r
- */\r
- SignedInfo signedInfo;\r
- try {\r
- SignatureMethod signatureMethod = signatureFactory.newSignatureMethod\r
- (signatureConfig.getSignatureMethodUri(), null);\r
- CanonicalizationMethod canonicalizationMethod = signatureFactory\r
- .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
- (C14NMethodParameterSpec) null);\r
- signedInfo = signatureFactory.newSignedInfo(\r
- canonicalizationMethod, signatureMethod, references);\r
- } catch (GeneralSecurityException e) {\r
- throw new XMLSignatureException(e);\r
+ signatureConfig.init(false);\r
+ \r
+ // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
+ // normal way to interfere with, so we need to add the namespace under the hand ...\r
+ EventTarget target = (EventTarget)document;\r
+ EventListener creationListener = signatureConfig.getSignatureMarshalListener();\r
+ if (creationListener != null) {\r
+ if (creationListener instanceof SignatureMarshalListener) {\r
+ ((SignatureMarshalListener)creationListener).setEventTarget(target);\r
}\r
- \r
- /*\r
- * JSR105 ds:Signature creation\r
- */\r
- String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
- javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
- .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
- signatureValueId);\r
- \r
- /*\r
- * ds:Signature Marshalling.\r
- */\r
- xmlSignature.sign(xmlSignContext);\r
- \r
- /*\r
- * Completion of undigested ds:References in the ds:Manifests.\r
- */\r
- for (XMLObject object : objects) {\r
- LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
- List<XMLStructure> objectContentList = object.getContent();\r
- for (XMLStructure objectContent : objectContentList) {\r
- LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
- if (!(objectContent instanceof Manifest)) continue;\r
- Manifest manifest = (Manifest) objectContent;\r
- List<Reference> manifestReferences = manifest.getReferences();\r
- for (Reference manifestReference : manifestReferences) {\r
- if (manifestReference.getDigestValue() != null) continue;\r
- \r
- DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
- manifestDOMReference.digest(xmlSignContext);\r
- }\r
+ SignatureMarshalListener.setListener(target, creationListener, true);\r
+ }\r
+ \r
+ /*\r
+ * Signature context construction.\r
+ */\r
+ XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
+ URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
+ if (null != uriDereferencer) {\r
+ xmlSignContext.setURIDereferencer(uriDereferencer);\r
+ }\r
+\r
+ for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {\r
+ xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());\r
+ }\r
+ xmlSignContext.setDefaultNamespacePrefix("");\r
+ // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));\r
+ \r
+ brokenJvmWorkaround(xmlSignContext);\r
+ \r
+ XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory();\r
+\r
+ /*\r
+ * Add ds:References that come from signing client local files.\r
+ */\r
+ List<Reference> references = new ArrayList<Reference>();\r
+ for (DigestInfo digestInfo : safe(digestInfos)) {\r
+ byte[] documentDigestValue = digestInfo.digestValue;\r
+\r
+ String uri = new File(digestInfo.description).getName();\r
+ Reference reference = SignatureFacet.newReference\r
+ (uri, null, null, null, documentDigestValue, signatureConfig);\r
+ references.add(reference);\r
+ }\r
+\r
+ /*\r
+ * Invoke the signature facets.\r
+ */\r
+ List<XMLObject> objects = new ArrayList<XMLObject>();\r
+ for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+ LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
+ signatureFacet.preSign(document, references, objects);\r
+ }\r
+\r
+ /*\r
+ * ds:SignedInfo\r
+ */\r
+ SignedInfo signedInfo;\r
+ try {\r
+ SignatureMethod signatureMethod = signatureFactory.newSignatureMethod\r
+ (signatureConfig.getSignatureMethodUri(), null);\r
+ CanonicalizationMethod canonicalizationMethod = signatureFactory\r
+ .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
+ (C14NMethodParameterSpec) null);\r
+ signedInfo = signatureFactory.newSignedInfo(\r
+ canonicalizationMethod, signatureMethod, references);\r
+ } catch (GeneralSecurityException e) {\r
+ throw new XMLSignatureException(e);\r
+ }\r
+\r
+ /*\r
+ * JSR105 ds:Signature creation\r
+ */\r
+ String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
+ javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
+ .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
+ signatureValueId);\r
+\r
+ /*\r
+ * ds:Signature Marshalling.\r
+ */\r
+ xmlSignature.sign(xmlSignContext);\r
+\r
+ /*\r
+ * Completion of undigested ds:References in the ds:Manifests.\r
+ */\r
+ for (XMLObject object : objects) {\r
+ LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
+ List<XMLStructure> objectContentList = object.getContent();\r
+ for (XMLStructure objectContent : objectContentList) {\r
+ LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
+ if (!(objectContent instanceof Manifest)) continue;\r
+ Manifest manifest = (Manifest) objectContent;\r
+ List<Reference> manifestReferences = manifest.getReferences();\r
+ for (Reference manifestReference : manifestReferences) {\r
+ if (manifestReference.getDigestValue() != null) continue;\r
+\r
+ DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
+ manifestDOMReference.digest(xmlSignContext);\r
}\r
}\r
- \r
- /*\r
- * Completion of undigested ds:References.\r
- */\r
- List<Reference> signedInfoReferences = signedInfo.getReferences();\r
- for (Reference signedInfoReference : signedInfoReferences) {\r
- DOMReference domReference = (DOMReference)signedInfoReference;\r
- \r
- // ds:Reference with external digest value\r
- if (domReference.getDigestValue() != null) continue;\r
- \r
- domReference.digest(xmlSignContext);\r
- }\r
- \r
- /*\r
- * Calculation of XML signature digest value.\r
- */\r
- DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
- ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
- domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
- byte[] octets = dataStream.toByteArray();\r
- \r
- /*\r
- * TODO: we could be using DigestOutputStream here to optimize memory\r
- * usage.\r
- */\r
- \r
- MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
- byte[] digestValue = md.digest(octets);\r
- \r
+ }\r
+\r
+ /*\r
+ * Completion of undigested ds:References.\r
+ */\r
+ List<Reference> signedInfoReferences = signedInfo.getReferences();\r
+ for (Reference signedInfoReference : signedInfoReferences) {\r
+ DOMReference domReference = (DOMReference)signedInfoReference;\r
+\r
+ // ds:Reference with external digest value\r
+ if (domReference.getDigestValue() != null) continue;\r
\r
- String description = signatureConfig.getSignatureDescription();\r
- return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
- } catch (ArrayIndexOutOfBoundsException e) {\r
- throw new JvmBrokenException(e);\r
+ domReference.digest(xmlSignContext);\r
}\r
+\r
+ /*\r
+ * Calculation of XML signature digest value.\r
+ */\r
+ DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
+ ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
+ domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
+ byte[] octets = dataStream.toByteArray();\r
+\r
+ /*\r
+ * TODO: we could be using DigestOutputStream here to optimize memory\r
+ * usage.\r
+ */\r
+\r
+ MessageDigest md = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
+ byte[] digestValue = md.digest(octets);\r
+ \r
+ \r
+ String description = signatureConfig.getSignatureDescription();\r
+ return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
}\r
\r
/**\r
private static <T> List<T> safe(List<T> other) {\r
return other == null ? Collections.EMPTY_LIST : other;\r
}\r
- \r
- private static class JvmBrokenException extends EncryptedDocumentException {\r
- public JvmBrokenException(Throwable cause) {\r
- super("\"your JVM is just too broken\" - check https://bugzilla.redhat.com/show_bug.cgi?id=1155012 if this applies to the stacktrace ...", cause);\r
- }\r
+\r
+ private void brokenJvmWorkaround(XMLSignContext context) {\r
+ // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
+ Provider bcProv = Security.getProvider("BC");\r
+ if (bcProv != null) {\r
+ context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
+ } \r
+ }\r
+\r
+ private void brokenJvmWorkaround(XMLValidateContext context) {\r
+ // workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1155012\r
+ Provider bcProv = Security.getProvider("BC");\r
+ if (bcProv != null) {\r
+ context.setProperty("org.jcp.xml.dsig.internal.dom.SignatureProvider", bcProv);\r
+ } \r
}\r
}\r