如何检查密钥库中是否存在证书

时间:2010-12-20 06:43:19

标签: java security ssl cryptography keystore

我需要验证签名的xml文档。作为验证的一部分,我需要检查通过签名证书传递的证书是否是可信证书。

所有受信任的证书都会添加到名为trusted.keystore的密钥库中。

如何检查传递的证书是否为有效证书?

我写过以下KeySelector,但它无效

import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Iterator;

import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.KeySelectorException;
import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.X509Data;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class X509KeySelector extends KeySelector {
    private static Log log = LogFactory.getLog(X509KeySelector.class);

    private KeyStore trustedStore;

    public void setTrustedStore(KeyStore trustedStore) {
        this.trustedStore = trustedStore;
    }

    @SuppressWarnings("rawtypes")
    public KeySelectorResult select(KeyInfo keyInfo,
            KeySelector.Purpose purpose, AlgorithmMethod method,
            XMLCryptoContext context) throws KeySelectorException {
        if (log.isDebugEnabled()) {
            log.debug("Selecting key for algorithm: " + method.getAlgorithm());
        }

        Iterator ki = keyInfo.getContent().iterator();
        while (ki.hasNext()) {
            XMLStructure info = (XMLStructure) ki.next();
            if (log.isDebugEnabled()) {
                log.debug("Found xml structure: " + info.toString());
            }

            if (!(info instanceof X509Data)) {
                if (log.isTraceEnabled()) {
                    log.trace("Ignoring xml structure since it is not a X509Data.");
                }
                continue;
            }

            X509Data x509Data = (X509Data) info;
            Iterator xi = x509Data.getContent().iterator();
            if (log.isDebugEnabled()) {
                log.debug("Iterating X509Data: Size: "
                        + x509Data.getContent().size());
            }

            while (xi.hasNext()) {
                Object o = xi.next();
                if (log.isDebugEnabled()) {
                    log.debug("Found object: " + o);
                }

                if (!(o instanceof X509Certificate)) {
                    if (log.isTraceEnabled()) {
                        log.trace("Ignoring object since it is not a X509Certificate");
                    }
                    continue;
                }
                X509Certificate cert = (X509Certificate) o;
                if (!isTrustedCertificate(cert)) {
                    log.warn("Ignoring certificate since it is not a valid certificate. Certificate: "
                            + cert);
                    continue;
                }

                final PublicKey key = cert.getPublicKey();

                // Make sure the algorithm is compatible
                // with the method.
                if (algEquals(method.getAlgorithm(), key.getAlgorithm())) {
                    KeySelectorResult keySelectorResult = new KeySelectorResult() {
                        public Key getKey() {
                            return key;
                        }
                    };
                    return keySelectorResult;
                } else {
                    log.warn("Ignoring certificate since the algorithms "
                            + method.getAlgorithm() + " and "
                            + key.getAlgorithm() + " does not match.");
                }
            }
        }

        log.error("Unable to find a valid certificate.");
        throw new KeySelectorException("No key found!");
    }

    private boolean isTrustedCertificate(X509Certificate cert) {
        if (trustedStore == null) {
            return true;
        }

        boolean trusted = false;
        try {
            Enumeration<String> aliases = trustedStore.aliases();
            while (aliases.hasMoreElements()) {
                String alias = aliases.nextElement();

                Certificate[] certificates = this.trustedStore
                        .getCertificateChain(alias);
                if (certificates == null) {
                    Certificate certificate = this.trustedStore
                            .getCertificate(alias);
                    if (certificate != null) {
                        certificates = new Certificate[] { certificate };
                    }
                }

                if (certificates != null) {
                    for (Certificate certificate : certificates) {
                        if (!(certificate instanceof X509Certificate)) {
                            continue;
                        }

                        if (cert.getSignature().equals(
                                ((X509Certificate) certificate).getSignature())) {
                            trusted = true;
                            break;
                        }
                    }
                    if (trusted) {
                        break;
                    }
                }
            }
        } catch (KeyStoreException e) {
            log.error(e.toString(), e);
        }
        return trusted;
    }

    static boolean algEquals(String algURI, String algName) {
        if ((algName.equalsIgnoreCase("DSA") && algURI
                .equalsIgnoreCase(SignatureMethod.DSA_SHA1))
                || (algName.equalsIgnoreCase("RSA") && algURI
                        .equalsIgnoreCase(SignatureMethod.RSA_SHA1))) {
            return true;
        } else {
            return false;
        }
    }
}

问题出在方法isTrustedCertificate上。我在迭代密钥库中的所有别名并检查它与传递的证书的位置相同。

正如类名所示,它仅处理X509类型证书。

谢谢

2 个答案:

答案 0 :(得分:2)

有一种更简单的方法可以使用一开始可能不明显的方法来检查。 KeyStore类有一个名为getCertificateAlias(Certificate cert)的方法。如果您传入要检查的证书并且没有获得空返回,则该证书位于KeyStore中。

尝试这样的事情:

private boolean isTrustedCertificate(X509Certificate cert) {

  if (trustedStore == null) {
       return true;
  }

  boolean trusted = false;
  try {

     if (cert != null) {

        // Only returns null if cert is NOT in keystore.
        String alias = trustedStore.getCertificateAlias(cert);

        if (alias != null) {
           trusted = true;
        }
     }
  }  catch (KeyStoreException e) {
        log.error(e.toString(), e);
     }

  return trusted;
}

答案 1 :(得分:1)

我想我的方向错了,

我在Certificate对象中找到了verify(PublicKey)方法,如果证书不匹配,它将java.security.SignatureException: Signature does not match.异常。