2010-12-20 159 views
2

我需要驗證簽名的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類型的證書。

謝謝

回答

1

我想我是走錯了路,

我發現證書對象驗證(公鑰)方法,這將java.security.SignatureException: Signature does not match.但如果該證書不匹配。

1

有一種更簡單的方法可以使用一種可能不明顯的方法來檢查此問題。 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; 
} 
相關問題