/**
   * Search the given Set of TrustAnchor's for one that is the issuer of the given X509 certificate.
   * Uses the specified provider for signature verification, or the default provider if null.
   *
   * @param cert the X509 certificate
   * @param trustAnchors a Set of TrustAnchor's
   * @param sigProvider the provider to use for signature verification
   * @return the <code>TrustAnchor</code> object if found or <code>null</code> if not.
   * @throws AnnotatedException if a TrustAnchor was found but the signature verification on the
   *     given certificate has thrown an exception.
   */
  protected static TrustAnchor findTrustAnchor(
      X509Certificate cert, Set trustAnchors, String sigProvider) throws AnnotatedException {
    TrustAnchor trust = null;
    PublicKey trustPublicKey = null;
    Exception invalidKeyEx = null;

    X509CertSelector certSelectX509 = new X509CertSelector();
    X500Principal certIssuer = getEncodedIssuerPrincipal(cert);

    try {
      certSelectX509.setSubject(certIssuer.getEncoded());
    } catch (IOException ex) {
      throw new AnnotatedException("Cannot set subject search criteria for trust anchor.", ex);
    }

    Iterator iter = trustAnchors.iterator();
    while (iter.hasNext() && trust == null) {
      trust = (TrustAnchor) iter.next();
      if (trust.getTrustedCert() != null) {
        if (certSelectX509.match(trust.getTrustedCert())) {
          trustPublicKey = trust.getTrustedCert().getPublicKey();
        } else {
          trust = null;
        }
      } else if (trust.getCAName() != null && trust.getCAPublicKey() != null) {
        try {
          X500Principal caName = new X500Principal(trust.getCAName());
          if (certIssuer.equals(caName)) {
            trustPublicKey = trust.getCAPublicKey();
          } else {
            trust = null;
          }
        } catch (IllegalArgumentException ex) {
          trust = null;
        }
      } else {
        trust = null;
      }

      if (trustPublicKey != null) {
        try {
          verifyX509Certificate(cert, trustPublicKey, sigProvider);
        } catch (Exception ex) {
          invalidKeyEx = ex;
          trust = null;
          trustPublicKey = null;
        }
      }
    }

    if (trust == null && invalidKeyEx != null) {
      throw new AnnotatedException(
          "TrustAnchor found but certificate validation failed.", invalidKeyEx);
    }

    return trust;
  }