public List<X509Certificate> verifySAMLProtocolSignature(ConversationID id)
     throws SamlSignatureException {
   Document document = getSAMLDocument(id);
   if (null == document) {
     throw new SamlSignatureException("DOM parser error");
   }
   Element protocolSignatureElement = findProtocolSignatureElement(document);
   if (null == protocolSignatureElement) {
     throw new SamlSignatureException("No protocol XML signature present");
   }
   XMLSignature xmlSignature;
   try {
     xmlSignature = new XMLSignature(protocolSignatureElement, "");
   } catch (XMLSignatureException ex) {
     throw new SamlSignatureException("Invalid protocol XML Signature", ex);
   } catch (XMLSecurityException ex) {
     throw new SamlSignatureException("XML security error", ex);
   }
   KeyInfo keyInfo = xmlSignature.getKeyInfo();
   X509Certificate signingCertificate;
   try {
     signingCertificate = keyInfo.getX509Certificate();
   } catch (KeyResolverException ex) {
     throw new SamlSignatureException("X509 certificate not present", ex);
   }
   boolean signatureValid;
   try {
     signatureValid = xmlSignature.checkSignatureValue(signingCertificate);
   } catch (XMLSignatureException ex) {
     throw new SamlSignatureException("signature error: " + ex.getMessage());
   }
   if (false == signatureValid) {
     throw new SamlSignatureException("invalid");
   }
   List<X509Certificate> certificateChain = new LinkedList<X509Certificate>();
   if (false == keyInfo.containsX509Data()) {
     throw new SamlSignatureException("no X509 data in KeyInfo");
   }
   for (int x509DataItemIdx = 0; x509DataItemIdx < keyInfo.lengthX509Data(); x509DataItemIdx++) {
     try {
       X509Data x509Data = keyInfo.itemX509Data(x509DataItemIdx);
       if (false == x509Data.containsCertificate()) {
         continue;
       }
       int certificateCount = x509Data.lengthCertificate();
       for (int certificateIdx = 0; certificateIdx < certificateCount; certificateIdx++) {
         XMLX509Certificate xmlX509Certificate = x509Data.itemCertificate(certificateIdx);
         X509Certificate certificate = xmlX509Certificate.getX509Certificate();
         certificateChain.add(certificate);
       }
     } catch (XMLSecurityException ex) {
       throw new SamlSignatureException("X509 data error", ex);
     }
   }
   return certificateChain;
 }
  /**
   * Verifies signatures in entity descriptor represented by the <code>Document</code>.
   *
   * @param doc The document.
   * @throws SAML2MetaException if unable to verify the entity descriptor.
   */
  public static void verifySignature(Document doc) throws SAML2MetaException {
    NodeList sigElements = null;
    try {
      Element nscontext =
          org.apache.xml.security.utils.XMLUtils.createDSctx(doc, "ds", Constants.SignatureSpecNS);
      sigElements = XPathAPI.selectNodeList(doc, "//ds:Signature", nscontext);
    } catch (Exception ex) {
      if (debug.messageEnabled()) {
        debug.message("SAML2MetaSecurityUtils.verifySignature:", ex);
        throw new SAML2MetaException(ex.getMessage());
      }
    }
    int numSigs = sigElements.getLength();
    if (debug.messageEnabled()) {
      debug.message("SAML2MetaSecurityUtils.verifySignature:" + " # of signatures = " + numSigs);
    }

    if (numSigs == 0) {
      return;
    }

    // If there are signatures then explicitly identify the ID Attribute, See comments section of
    // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8017265
    doc.getDocumentElement().setIdAttribute(SAML2Constants.ID, true);

    initializeKeyStore();

    for (int i = 0; i < numSigs; i++) {
      Element sigElement = (Element) sigElements.item(i);
      String sigParentName = sigElement.getParentNode().getLocalName();
      Object[] objs = {sigParentName};
      if (debug.messageEnabled()) {
        debug.message(
            "SAML2MetaSecurityUtils.verifySignature: "
                + "verifying signature under "
                + sigParentName);
      }

      try {
        XMLSignature signature = new XMLSignature(sigElement, "");
        signature.addResourceResolver(new com.sun.identity.saml.xmlsig.OfflineResolver());
        KeyInfo ki = signature.getKeyInfo();

        X509Certificate x509cert = null;
        if (ki != null && ki.containsX509Data()) {
          if (keyStore != null) {
            StorageResolver sr = new StorageResolver(new KeyStoreResolver(keyStore));
            ki.addStorageResolver(sr);
          }
          x509cert = ki.getX509Certificate();
        }

        if (x509cert == null) {
          if (debug.messageEnabled()) {
            debug.message(
                "SAML2MetaSecurityUtils.verifySignature:" + " try to find cert in KeyDescriptor");
          }
          String xpath =
              "following-sibling::*[local-name()=\""
                  + TAG_KEY_DESCRIPTOR
                  + "\" and namespace-uri()=\""
                  + NS_META
                  + "\"]";
          Node node = XPathAPI.selectSingleNode(sigElement, xpath);

          if (node != null) {
            Element kd = (Element) node;
            String use = kd.getAttributeNS(null, ATTR_USE);
            if ((use.length() == 0) || use.equals("signing")) {
              NodeList nl = kd.getChildNodes();
              for (int j = 0; j < nl.getLength(); j++) {
                Node child = nl.item(j);
                if (child.getNodeType() == Node.ELEMENT_NODE) {
                  String localName = child.getLocalName();
                  String ns = child.getNamespaceURI();
                  if (TAG_KEY_INFO.equals(localName) && NS_XMLSIG.equals(ns)) {

                    ki = new KeyInfo((Element) child, "");
                    if (ki.containsX509Data()) {
                      if (keyStore != null) {
                        KeyStoreResolver ksr = new KeyStoreResolver(keyStore);
                        StorageResolver sr = new StorageResolver(ksr);
                        ki.addStorageResolver(sr);
                      }

                      x509cert = ki.getX509Certificate();
                    }
                  }
                  break;
                }
              }
            }
          }
        }

        if (x509cert == null) {
          throw new SAML2MetaException("verify_no_cert", objs);
        }

        if (checkCert
            && ((keyProvider == null) || (keyProvider.getCertificateAlias(x509cert) == null))) {
          throw new SAML2MetaException("untrusted_cert", objs);
        }

        PublicKey pk = x509cert.getPublicKey();

        if (!signature.checkSignatureValue(pk)) {
          throw new SAML2MetaException("verify_fail", objs);
        }
      } catch (SAML2MetaException sme) {
        throw sme;
      } catch (Exception ex) {
        debug.error("SAML2MetaSecurityUtils.verifySignature: ", ex);
        throw new SAML2MetaException(
            Locale.getString(SAML2MetaUtils.resourceBundle, "verify_fail", objs)
                + "\n"
                + ex.getMessage());
      }
    }
  }