Example usage for javax.xml.crypto.dsig XMLSignature getKeySelectorResult

List of usage examples for javax.xml.crypto.dsig XMLSignature getKeySelectorResult

Introduction

In this page you can find the example usage for javax.xml.crypto.dsig XMLSignature getKeySelectorResult.

Prototype

KeySelectorResult getKeySelectorResult();

Source Link

Document

Returns the result of the KeySelector , if specified, after this XMLSignature has been signed or validated.

Usage

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 {// ww  w  .j a  va2  s .c  o  m

        // 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);
    }
}