List of usage examples for javax.xml.crypto.dsig Reference validate
boolean validate(XMLValidateContext validateContext) throws XMLSignatureException;
From source file:com.bcmcgroup.flare.xmldsig.Xmldsig.java
/** * Used to verify an enveloped digital signature * * @param doc a Document object containing the xml with the signature * @param keyStorePath a String containing the path to the KeyStore * @param keyStorePW a String containing the KeyStore password * @param verifyAlias a String containing the alias of the public key used for verification * @return True if signature passes verification, False otherwise *//*from ww w. j a v a 2 s.c o m*/ public static boolean verifySignature(Document doc, String keyStorePath, String keyStorePW, String verifyAlias) { boolean coreValidation = false; PublicKey publicKey = ClientUtil.getPublicKeyByAlias(keyStorePath, keyStorePW, verifyAlias); if (publicKey == null) { logger.error( "Public key was null when verifying signature. Ensure keystore configuration values are set properly."); return false; } try { NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nl.getLength() == 0) { logger.error("No XML Digital Signature was found. The document was discarded."); return false; } Node signatureNode = nl.item(nl.getLength() - 1); DOMValidateContext valContext = new DOMValidateContext(publicKey, signatureNode); valContext.setURIDereferencer(new MyURIDereferencer(signatureNode.getParentNode())); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); XMLSignature signature = fac.unmarshalXMLSignature(valContext); coreValidation = signature.validate(valContext); if (!coreValidation) { // for testing/debugging when validation fails... logger.error("Digital Signature Core Validation failed."); boolean signatureValidation = signature.getSignatureValue().validate(valContext); logger.debug("Digital Signature Validation: " + signatureValidation); @SuppressWarnings("rawtypes") Iterator i = signature.getSignedInfo().getReferences().iterator(); for (int j = 0; i.hasNext(); j++) { Reference ref = (Reference) i.next(); boolean referenceValidation = ref.validate(valContext); logger.debug("Digital Signature Reference Validation: " + referenceValidation); byte[] calculatedDigestValue = ref.getCalculatedDigestValue(); byte[] digestValue = ref.getDigestValue(); String cdvString = new String(Base64.encodeBase64(calculatedDigestValue)); logger.debug("Digital Signature Calculated Digest Value: " + cdvString); String dvString = new String(Base64.encodeBase64(digestValue)); logger.debug("Digital Signature Digest Value: " + dvString); } } } catch (MarshalException e) { logger.error("MarshalException when attempting to verify a digital signature."); } catch (XMLSignatureException e) { logger.error("XMLSignature Exception when attempting to verify a digital signature."); } return coreValidation; }
From source file:cl.nic.dte.util.XMLUtil.java
/** * Verifica si una firma XML embedida es válida según define * el estándar XML Signature (<a * href="http://www.w3.org/TR/xmldsig-core/#sec-CoreValidation">Core * Validation</a>), y si el certificado era válido en la fecha dada. * <p>/*from w w w . j a v a2 s .c o m*/ * * Esta rutina <b>NO</b> verifica si el certificado embedido en * <KeyInfo> es válido (eso debe verificarlo con la autoridad * certificadora que emitió el certificado), pero si verifica que la * llave utilizada para verificar corresponde a la contenida en el * certificado. * * @param xml * el nodo <Signature> * @param date * una fecha en la que se verifica la validez del certificado * @return el resultado de la verificación * * @see javax.xml.crypto.dsig.XMLSignature#sign(javax.xml.crypto.dsig.XMLSignContext) * @see cl.nic.dte.VerifyResult * @see cl.nic.dte.extension.DTEDefTypeExtensionHandler * @see #getCertificate(XMLSignature) */ @SuppressWarnings("unchecked") public static VerifyResult verifySignature(XMLSignature signature, DOMValidateContext valContext) { try { KeyValueKeySelector ksel = (KeyValueKeySelector) valContext.getKeySelector(); X509Certificate x509 = getCertificate(signature); // Verifica que un certificado bien embedido if (x509 == null) { return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels.getString("XML_SIGNATURE_ERROR_NO509"))); } // Validate the XMLSignature boolean coreValidity = signature.validate(valContext); // Check core validation status if (coreValidity == false) { boolean sv = signature.getSignatureValue().validate(valContext); if (!sv) return new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels.getString("XML_SIGNATURE_BAD_VALUE")); // check the validation status of each Reference String message = ""; for (Reference ref : (List<Reference>) signature.getSignedInfo().getReferences()) { if (!ref.validate(valContext)) { message += Utilities.verificationLabels.getString("XML_SIGNATURE_BAD_REFERENCE"); message = message.replaceAll("%1", new String(Base64.encodeBase64(ref.getCalculatedDigestValue()))); message = message.replaceAll("%2", new String(Base64.encodeBase64(ref.getDigestValue()))); message += "\n"; } } return new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, message); } // Verifica que la llave del certificado corresponde a la usada para // la firma if (!ksel.getPk().equals(x509.getPublicKey())) { String message = Utilities.verificationLabels.getString("XML_SIGNATURE_ERROR_BADKEY"); return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, message)); } return new VerifyResult(VerifyResult.XML_SIGNATURE_OK, true, null); } catch (XMLSignatureException e) { return (new VerifyResult(VerifyResult.XML_SIGNATURE_WRONG, false, Utilities.verificationLabels.getString("XML_SIGNATURE_ERROR_UNKNOWN") + ": " + e.getMessage())); } }
From source file:com.vmware.identity.sts.ws.SignatureValidator.java
/** * Validate references present in the XmlSignature. * @param xmlSignature the xml signature whose references are to be validated. not null. * @param valContext validation context used to validate the signature itself. not null. * @param document document the signature belongs to. not null. * @param timestampNode the timestamp node of the soap security header within the document. * @throws XMLSignatureException when the validation fails. *//*from w w w . j a v a 2 s. c o m*/ private void validateSignatureReferences(XMLSignature xmlSignature, DOMValidateContext valContext, Document document, Node timestampNode) throws XMLSignatureException { assert xmlSignature != null; assert valContext != null; assert document != null; assert timestampNode != null; // If a signature is applied to a request then it must include: // Either the <S11:Body>, or the WS-Trust element as a direct child of the <S11:Body> // The <wsu:Timestamp>, if present in the <S11:Header>. // (in fact this must be present as per same spec, and SOAPHeaderExtractor validates it) Node soapBody = getSoapBody(document); Node wsTrustNode = getWsTrustNode(soapBody); boolean foundTimestampElement = false; boolean foundBodyOrWSTrustElement = false; List<Reference> references = xmlSignature.getSignedInfo().getReferences(); if ((references == null) || (references.size() == 0)) { throw new XMLSignatureException("Signature's SignInfo does not contain any references."); } for (Reference reference : references) { if (reference != null) { validateReferenceTransforms(reference); validateReferenceUri(reference); // note: order is important, we should not try to validate digests // before we checked expected transforms, and uri etc. if (!reference.validate(valContext)) { throw new XMLSignatureException( String.format("Signature reference '%s' is invalid.", reference.getURI())); } if (!foundTimestampElement || !foundBodyOrWSTrustElement) { String id = org.jcp.xml.dsig.internal.dom.Utils.parseIdFromSameDocumentURI(reference.getURI()); Node referencedNode = document.getElementById(id); foundTimestampElement = (foundTimestampElement) || (timestampNode.isSameNode(referencedNode)); foundBodyOrWSTrustElement = (foundBodyOrWSTrustElement) || (soapBody.isSameNode(referencedNode)) || (wsTrustNode.isSameNode(referencedNode)); } } } // for each reference if (!foundTimestampElement || !foundBodyOrWSTrustElement) { throw new XMLSignatureException( "Signature must include <wsu:Timestamp> and either SoapBody, or the WSTrust element within it."); } }
From source file:eu.europa.ec.markt.dss.validation.xades.XAdESSignature.java
@Override public List<AdvancedSignature> getCounterSignatures() { // see ETSI TS 101 903 V1.4.2 (2010-12) pp. 38/39/40 try {/*from w w w . j a va2s. com*/ NodeList counterSigs = XMLUtils.getNodeList(signatureElement, "./ds:Object/xades:QualifyingProperties/xades:UnsignedProperties/xades:UnsignedSignatureProperties" + "/xades:CounterSignature"); if (counterSigs == null) { return null; } List<AdvancedSignature> xadesList = new ArrayList<AdvancedSignature>(); for (int i = 0; i < counterSigs.getLength(); i++) { Element counterSigEl = (Element) counterSigs.item(i); Element signatureEl = XMLUtils.getElement(counterSigEl, "./ds:Signature"); // Verify that the element is a proper signature by trying to build a XAdESSignature out of it XAdESSignature xCounterSig = new XAdESSignature(signatureEl); // Verify that there is a ds:Reference element with a Type set to: http://uri.etsi.org/01903#CountersignedSignature // (as per the XAdES spec) XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM"); XMLSignature signature = factory.unmarshalXMLSignature(new DOMStructure(signatureEl)); LOG.info("Verifying countersignature References"); for (Object refobj : signature.getSignedInfo().getReferences()) { Reference ref = (Reference) refobj; if (ref.getType() != null && ref.getType().equals("http://uri.etsi.org/01903#CountersignedSignature")) { // Ok, this seems to be a countersignature // Verify that the digest is that of the signature value if (ref.validate(new DOMValidateContext(xCounterSig.getSigningCertificate().getPublicKey(), XMLUtils.getElement(signatureElement, "./ds:SignatureValue")))) { LOG.info("Reference verification succeeded, adding countersignature"); xadesList.add(xCounterSig); } else { LOG.warning( "Skipping countersignature because the Reference doesn't contain a hash of the embedding SignatureValue"); } break; } } } return xadesList; } catch (XPathExpressionException e) { throw new EncodingException(MSG.COUNTERSIGNATURE_ENCODING); } catch (MarshalException e) { throw new EncodingException(MSG.COUNTERSIGNATURE_ENCODING); } catch (XMLSignatureException e) { throw new EncodingException(MSG.COUNTERSIGNATURE_ENCODING); } }
From source file:eu.europa.ec.markt.dss.validation102853.xades.XAdESSignature.java
@Override public SignatureCryptographicVerification checkIntegrity(DSSDocument detachedDocument) { final SignatureCryptographicVerification scv = new SignatureCryptographicVerification(); final CertificateToken certToken = getSigningCertificate().getCertToken(); if (certToken != null) { final PublicKey publicKey = certToken.getCertificate().getPublicKey(); final KeySelector keySelector = KeySelector.singletonKeySelector(publicKey); /**//w ww.ja va2 s . c o m * Creating a Validation Context<br> * We create an XMLValidateContext instance containing input parameters for validating the signature. Since we * are using DOM, we instantiate a DOMValidateContext instance (a subclass of XMLValidateContext), and pass it * two parameters, a KeyValueKeySelector object and a reference to the Signature element to be validated (which * is the first entry of the NodeList we generated earlier): */ final DOMValidateContext valContext = new DOMValidateContext(keySelector, signatureElement); try { URIDereferencer dereferencer = new ExternalFileURIDereferencer(detachedDocument); valContext.setURIDereferencer(dereferencer); /** * This property controls whether or not the digested Reference objects will cache the dereferenced content * and pre-digested input for subsequent retrieval via the Reference.getDereferencedData and * Reference.getDigestInputStream methods. The default value if not specified is Boolean.FALSE. */ valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); /** * Unmarshalling the XML Signature<br> * We extract the contents of the Signature element into an XMLSignature object. This process is called * unmarshalling. The Signature element is unmarshalled using an XMLSignatureFactory object. An application * can obtain a DOM implementation of XMLSignatureFactory by calling the following line of code: */ // These providers do not support ECDSA algorithm // factory = XMLSignatureFactory.getInstance("DOM"); // factory = XMLSignatureFactory.getInstance("DOM", "XMLDSig"); // factory = XMLSignatureFactory.getInstance("DOM", new org.jcp.xml.dsig.internal.dom.XMLDSigRI()); // This provider support ECDSA signature /** * ApacheXMLDSig / Apache Santuario XMLDSig (DOM XMLSignatureFactory; DOM KeyInfoFactory; C14N 1.0, C14N * 1.1, Exclusive C14N, Base64, Enveloped, XPath, XPath2, XSLT TransformServices)<br> * If this library is used than the same library must be used for the URIDereferencer. */ final XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM", xmlProvider); /** * We then invoke the unmarshalXMLSignature method of the factory to unmarshal an XMLSignature object, and * pass it the validation context we created earlier: */ final XMLSignature signature = factory.unmarshalXMLSignature(valContext); //System.out.println("XMLSignature class: " + signature.getClass()); // Austrian specific signature //org.apache.xml.security.signature.XMLSignature signature_ = null; // try { // signature_ = new org.apache.xml.security.signature.XMLSignature(signatureElement, ""); // } catch (Exception e) { // // throw new DSSException(e); // } // signature.addResourceResolver(new XPointerResourceResolver(signatureElement)); //signature_.getSignedInfo().verifyReferences();//getVerificationResult(1); /** * In case of org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI() provider, the ID attributes need to be set * manually.<br> * The DSSXMLUtils.recursiveIdBrowse(...) method do not take into account the XML outside of the Signature * tag. It prevents some signatures to be validated.<br> * * Solution: the following lines where added: */ final Document document = signatureElement.getOwnerDocument(); final Element rootElement = document.getDocumentElement(); if (rootElement.hasAttribute(DSSXMLUtils.ID_ATTRIBUTE_NAME)) { valContext.setIdAttributeNS(rootElement, null, DSSXMLUtils.ID_ATTRIBUTE_NAME); } DSSXMLUtils.recursiveIdBrowse(valContext, rootElement); /** * Validating the XML Signature<br> * Now we are ready to validate the signature. We do this by invoking the validate method on the * XMLSignature object, and pass it the validation context as follows: */ boolean coreValidity = false; try { coreValidity = signature.validate(valContext); } catch (XMLSignatureException e) { scv.setErrorMessage("Signature validation: " + e.getMessage()); } boolean signatureValidity = coreValidity; boolean dataFound = true; boolean dataHashValid = true; /** * If the XMLSignature.validate method returns false, we can try to narrow down the cause of the failure. * There are two phases in core XML Signature validation: <br> * - Signature validation (the cryptographic verification of the signature)<br> * - Reference validation (the verification of the digest of each reference in the signature)<br> * Each phase must be successful for the signature to be valid. To check if the signature failed to * cryptographically validate, we can check the status, as follows: */ try { signatureValidity = signature.getSignatureValue().validate(valContext); } catch (XMLSignatureException e) { scv.setErrorMessage(e.getMessage()); } @SuppressWarnings("unchecked") final List<Reference> references = signature.getSignedInfo().getReferences(); for (Reference reference : references) { boolean refHashValidity = false; try { refHashValidity = reference.validate(valContext); } catch (XMLSignatureException e) { scv.setErrorMessage(reference.getURI() + ": " + e.getMessage()); } dataHashValid = dataHashValid && refHashValidity; if (LOG.isLoggable(Level.INFO)) { LOG.info("Reference hash validity checked: " + reference.getURI() + "=" + refHashValidity); } final Data data = reference.getDereferencedData(); dataFound = dataFound && (data != null); final InputStream digestInputStream = reference.getDigestInputStream(); if (data != null && digestInputStream != null) { // The references are saved for later treatment in -A level. try { IOUtils.copy(digestInputStream, referencesDigestOutputStream); } catch (IOException e) { } } } scv.setReferenceDataFound(dataFound); scv.setReferenceDataIntact(dataHashValid); scv.setSignatureIntegrity(signatureValidity); } catch (MarshalException e) { scv.setErrorMessage(e.getMessage()); } } else { scv.setErrorMessage( "Unable to proceed with the signature cryptographic verification. There is no signing certificate!"); } return scv; }
From source file:eu.europa.ec.markt.dss.validation102853.xades.XAdESSignature.java
@Override public List<AdvancedSignature> getCounterSignatures() { // see ETSI TS 101 903 V1.4.2 (2010-12) pp. 38/39/40 try {/*w ww . ja va 2s.c o m*/ NodeList counterSigs = DSSXMLUtils.getNodeList(signatureElement, XPATH_COUNTER_SIGNATURE); if (counterSigs == null) { return null; } List<AdvancedSignature> xadesList = new ArrayList<AdvancedSignature>(); for (int i = 0; i < counterSigs.getLength(); i++) { Element counterSigEl = (Element) counterSigs.item(i); Element signatureEl = DSSXMLUtils.getElement(counterSigEl, XPATH_SIGNATURE); // Verify that the element is a proper signature by trying to build a XAdESSignature out of it XAdESSignature xCounterSig = new XAdESSignature(signatureEl, certPool); /* * Verify that there is a ds:Reference element with a Type set to: * http://uri.etsi.org/01903#CountersignedSignature (as per the XAdES spec) */ XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM"); javax.xml.crypto.dsig.XMLSignature signature = factory .unmarshalXMLSignature(new DOMStructure(signatureEl)); LOG.info("Verifying countersignature References"); for (Object refobj : signature.getSignedInfo().getReferences()) { Reference ref = (Reference) refobj; if (ref.getType() != null && ref.getType().equals(XADES_COUNTERSIGNED_SIGNATURE)) { // Ok, this seems to be a CounterSignature // Verify that the digest is that of the signature value CertificateToken certToken = xCounterSig.getSigningCertificate().getCertToken(); PublicKey publicKey = certToken.getCertificate().getPublicKey(); if (ref.validate(new DOMValidateContext(publicKey, DSSXMLUtils.getElement(signatureElement, XPATH_SIGNATURE_VALUE)))) { LOG.info("Reference verification succeeded, adding countersignature"); xadesList.add(xCounterSig); } else { LOG.warning( "Skipping countersignature because the Reference doesn't contain a hash of the embedding SignatureValue"); } break; } } } return xadesList; } catch (MarshalException e) { throw new EncodingException(MSG.COUNTERSIGNATURE_ENCODING, e); } catch (XMLSignatureException e) { throw new EncodingException(MSG.COUNTERSIGNATURE_ENCODING, e); } }
From source file:org.apache.jcp.xml.dsig.internal.dom.DOMXMLSignature.java
public boolean validate(XMLValidateContext vc) throws XMLSignatureException { if (vc == null) { throw new NullPointerException("validateContext is null"); }//from w w w . j a va 2 s .c om if (!(vc instanceof DOMValidateContext)) { throw new ClassCastException("validateContext must be of type DOMValidateContext"); } if (validated) { return validationStatus; } // validate the signature boolean sigValidity = sv.validate(vc); if (!sigValidity) { validationStatus = false; validated = true; return validationStatus; } // validate all References @SuppressWarnings("unchecked") List<Reference> refs = this.si.getReferences(); boolean validateRefs = true; for (int i = 0, size = refs.size(); validateRefs && i < size; i++) { Reference ref = refs.get(i); boolean refValid = ref.validate(vc); if (log.isDebugEnabled()) { log.debug("Reference[" + ref.getURI() + "] is valid: " + refValid); } validateRefs &= refValid; } if (!validateRefs) { if (log.isDebugEnabled()) { log.debug("Couldn't validate the References"); } validationStatus = false; validated = true; return validationStatus; } // validate Manifests, if property set boolean validateMans = true; if (Boolean.TRUE.equals(vc.getProperty("org.jcp.xml.dsig.validateManifests"))) { for (int i = 0, size = objects.size(); validateMans && i < size; i++) { XMLObject xo = objects.get(i); @SuppressWarnings("unchecked") List<XMLStructure> content = xo.getContent(); int csize = content.size(); for (int j = 0; validateMans && j < csize; j++) { XMLStructure xs = content.get(j); if (xs instanceof Manifest) { if (log.isDebugEnabled()) { log.debug("validating manifest"); } Manifest man = (Manifest) xs; @SuppressWarnings("unchecked") List<Reference> manRefs = man.getReferences(); int rsize = manRefs.size(); for (int k = 0; validateMans && k < rsize; k++) { Reference ref = manRefs.get(k); boolean refValid = ref.validate(vc); if (log.isDebugEnabled()) { log.debug("Manifest ref[" + ref.getURI() + "] is valid: " + refValid); } validateMans &= refValid; } } } } } validationStatus = validateMans; validated = true; return validationStatus; }
From source file:org.apache.juddi.v3.client.cryptor.DigSigUtil.java
private boolean verifySignature(Element element, PublicKey validatingKey, AtomicReference<String> OutReadableErrorMessage) { if (OutReadableErrorMessage == null) { OutReadableErrorMessage = new AtomicReference<String>(); }/*from www. j a va2 s .c o m*/ XMLSignatureFactory fac = initXMLSigFactory(); NodeList nl = element.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nl.getLength() == 0) { throw new RuntimeException("Cannot find Signature element"); } DOMValidateContext valContext = new DOMValidateContext(validatingKey, nl.item(0)); try { valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); XMLSignature signature = fac.unmarshalXMLSignature(valContext); boolean coreValidity = signature.validate(valContext); // Check core validation status. if (coreValidity == false) { logger.warn("Signature failed core validation"); boolean sv = signature.getSignatureValue().validate(valContext); logger.debug("signature validation status: " + sv); OutReadableErrorMessage .set("signature validation failed: " + sv + "." + OutReadableErrorMessage.get()); // Check the validation status of each Reference. @SuppressWarnings("unchecked") Iterator<Reference> i = signature.getSignedInfo().getReferences().iterator(); //System.out.println("---------------------------------------------"); for (int j = 0; i.hasNext(); j++) { Reference ref = (Reference) i.next(); boolean refValid = ref.validate(valContext); logger.debug(j); logger.debug("ref[" + j + "] validity status: " + refValid); if (!refValid) { OutReadableErrorMessage .set("signature reference " + j + " invalid. " + OutReadableErrorMessage.get()); } logger.debug("Ref type: " + ref.getType() + ", URI: " + ref.getURI()); for (Object xform : ref.getTransforms()) { logger.debug("Transform: " + xform); } String calcDigValStr = digestToString(ref.getCalculatedDigestValue()); String expectedDigValStr = digestToString(ref.getDigestValue()); logger.warn(" Calc Digest: " + calcDigValStr); logger.warn("Expected Digest: " + expectedDigValStr); if (!calcDigValStr.equalsIgnoreCase(expectedDigValStr)) { OutReadableErrorMessage.set( "digest mismatch for signature ref " + j + "." + OutReadableErrorMessage.get()); } } } else { logger.info("Signature passed core validation"); } return coreValidity; } catch (Exception e) { OutReadableErrorMessage .set("signature validation failed: " + e.getMessage() + OutReadableErrorMessage.get()); logger.fatal(e); return false; } }
From source file:org.atricore.idbus.capabilities.sso.support.core.signature.JSR105SamlR2SignerImpl.java
public void validate(RoleDescriptorType md, Document doc, Node root) throws SamlR2SignatureException { try {/* w w w . j a va 2 s .com*/ // Check for duplicate IDs among XML elements NodeList nodes = evaluateXPath(doc, "//*/@ID"); boolean duplicateIdExists = false; List<String> ids = new ArrayList<String>(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (ids.contains(node.getNodeValue())) { duplicateIdExists = true; logger.error("Duplicated Element ID in XML Document : " + node.getNodeValue()); } ids.add(node.getNodeValue()); } if (duplicateIdExists) { throw new SamlR2SignatureException("Duplicate IDs in document "); } // TODO : Check that the Signature references the root element (the one used by the application) // Keep in mind that signature reference might be an XPath expression ?! // We know that in SAML, the root element is the element used by the application, we just need to make sure that // the root element is the one referred by the signature Node rootIdAttr = root.getAttributes().getNamedItem("ID"); if (rootIdAttr == null) throw new SamlR2SignatureException("SAML document does not have an ID "); // Find Signature element NodeList signatureNodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (signatureNodes.getLength() == 0) { throw new SamlR2SignatureException("Cannot find Signature elements"); } // Create a DOM XMLSignatureFactory that will be used to unmarshal the // document containing the XMLSignature XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", provider); // Create a DOMValidateContext and specify a KeyValue KeySelector // and document context // Validate all Signature elements boolean rootIdMatched = false; for (int k = 0; k < signatureNodes.getLength(); k++) { DOMValidateContext valContext = new DOMValidateContext(new RawX509KeySelector(), signatureNodes.item(k)); // unmarshal the XMLSignature XMLSignature signature = fac.unmarshalXMLSignature(valContext); // Validate the XMLSignature (generated above) boolean coreValidity = signature.validate(valContext); // Check core validation status if (!coreValidity) { if (logger.isDebugEnabled()) logger.debug("Signature failed core validation"); boolean sv = signature.getSignatureValue().validate(valContext); if (logger.isDebugEnabled()) logger.debug("signature validation status: " + sv); // check the validation status of each Reference (should be only one!) Iterator i = signature.getSignedInfo().getReferences().iterator(); boolean refValid = true; for (int j = 0; i.hasNext(); j++) { Reference ref = (Reference) i.next(); boolean b = ref.validate(valContext); if (logger.isDebugEnabled()) logger.debug("ref[" + j + "] " + ref.getId() + " validity status: " + b); if (!b) { refValid = b; logger.error("Signature failed reference validation " + ref.getId()); } } throw new SamlR2SignatureValidationException( "Signature failed core validation" + (refValid ? " but passed all Reference validations" : " and some/all Reference validation")); } if (logger.isDebugEnabled()) logger.debug("Singnature passed Core validation"); // The Signature must contain only one reference, and it must be the signed top element's ID. List<Reference> refs = signature.getSignedInfo().getReferences(); if (refs.size() != 1) { throw new SamlR2SignatureValidationException( "Invalid number of 'Reference' elements in signature : " + refs.size() + " [" + signature.getId() + "]"); } Reference reference = refs.get(0); String referenceURI = reference.getURI(); if (referenceURI == null || !referenceURI.startsWith("#")) throw new SamlR2SignatureValidationException( "Signature reference URI format not supported " + referenceURI); if (referenceURI.substring(1).equals(rootIdAttr.getNodeValue())) rootIdMatched = true; Key key = signature.getKeySelectorResult().getKey(); boolean certValidity = validateCertificate(md, key); if (!certValidity) { throw new SamlR2SignatureValidationException("Signature failed Certificate validation"); } if (logger.isDebugEnabled()) logger.debug("Signature passed Certificate validation"); } // Check that any of the Signatures matched the root element ID if (!rootIdMatched) { logger.error("No Signature element refers to signed element (possible signature wrapping attack)"); throw new SamlR2SignatureValidationException("No Signature element refers to signed element"); } } catch (MarshalException e) { throw new RuntimeException(e.getMessage(), e); } catch (XMLSignatureException e) { throw new RuntimeException(e.getMessage(), e); } }