我需要验证已签名的 xml 文档。作为验证的一部分,我需要检查通过签名证书传递的证书是否是受信任的证书。
所有受信任的证书都被添加到名为 trusted.keystore
的 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
上。我在哪里遍历 keystore 中的所有别名,并检查它与传递的证书在哪里相同。
正如类名所暗示的那样,它只处理 X509 类型的证书。
谢谢
最佳答案
有一种更简单的方法可以使用一开始可能不太明显的方法来检查它。 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;
}
关于java - 如何检查 keystore 中是否存在证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4487445/