gpt4 book ai didi

java - X509 认证路径验证

转载 作者:行者123 更新时间:2023-12-02 02:33:46 25 4
gpt4 key购买 nike

在我开发的应用程序中,我检查客户端在传入消息中发送的证书:除了基本证书有效性检查(证书签名、到期日期...)之外,我还检查客户端是否可信。

为此,我创建了一个仅包含受信任证书的 keystore :如果收到的证书不在列表中,我将拒绝传入的消息。客户端证书位于证书路径中,我检查了所有证书路径。

对于认证路径验证,我使用以下算法:(wikipedia)

1)从客户端证书开始

2) 虽然当前证书不是根证书:

3) 在 keystore 中搜索父证书:为此,我在 keystore 中搜索证书,其中SubjectDN = 当前证书的IssuerDN。如果没有找到,则测试的证书无效

4)使用父证书的公钥检查当前证书的签名

因此,整个路径都已验证

这里是 validator 的完整代码:(感谢this article的作者)

请注意,此处吊销列表 (CRL) 检查已禁用。

 public class CertificateChainValidator {
private static Logger logger = Logger.getLogger(CertificateChainValidator.class);

/**
* path of the keystore.
*/
private static final String TRUSTED_KEYSTORE = "/trusted.jks";

/**
* password for opening the keystore.
*/
private static final char[] TRUSTED_KEYSTORE_PWD = new char[] { '$' , '$' , '$','$','$','$','$'};

/**
* the keystore loaded.
*/
private static KeyStore trustedKeystore;

/**
* Validate keychain
*
* @param client
* is the client X509Certificate
* @param keyStore
* containing all trusted certificate
* @return true if validation until root certificate success, false
* otherwise
* @throws KeyStoreException
* @throws CertificateException
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
public static boolean validateKeyChain(final X509Certificate client, final KeyStore keyStore)
throws KeyStoreException, CertificateException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException, NoSuchProviderException {
X509Certificate[] certs = new X509Certificate[keyStore.size()];
int i = 0;
Enumeration<String> alias = keyStore.aliases();

while (alias.hasMoreElements()) {
certs[i++] = (X509Certificate) keyStore.getCertificate(alias.nextElement());
}

return validateKeyChain(client, certs);
}

/**
* Validate keychain
*
* @param client
* is the client X509Certificate
* @param trustedCerts
* is Array containing all trusted X509Certificate
* @return true if validation until root certificate success, false
* otherwise
* @throws CertificateException
* @throws InvalidAlgorithmParameterException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
@SuppressWarnings("unchecked")
private static boolean validateKeyChain(final X509Certificate client, final X509Certificate... trustedCerts)
throws CertificateException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchProviderException {
boolean found = false;
int i = trustedCerts.length;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
TrustAnchor anchor;
@SuppressWarnings("rawtypes")
Set anchors;
CertPath path;
@SuppressWarnings("rawtypes")
List list;
PKIXParameters params;
CertPathValidator validator = CertPathValidator.getInstance("PKIX");

while (!found && i > 0) {
anchor = new TrustAnchor(trustedCerts[--i], null);
anchors = Collections.singleton(anchor);

list = Arrays.asList(new Certificate[] { client });
path = cf.generateCertPath(list);

params = new PKIXParameters(anchors);
params.setRevocationEnabled(false);

if (logger.isDebugEnabled()) {
logger.debug(String.format("Test certificate chain : client=%s IssuerDN=%s", client.getIssuerDN(),
trustedCerts[i].getSubjectDN()));
}

if (client.getIssuerDN().equals(trustedCerts[i].getSubjectDN())) {

if (logger.isDebugEnabled()) {
logger.debug(String.format("Validation certificate : IssuerDN=%s", trustedCerts[i].getSubjectDN()));
}

try {
validator.validate(path, params);
if (isSelfSigned(trustedCerts[i])) {
// found root ca
if (logger.isDebugEnabled()) {
logger.debug(String.format("certificate root validated : IssuerDN=%s",
trustedCerts[i].getSubjectDN()));
}
found = true;
} else if (!client.equals(trustedCerts[i])) {
// find parent ca
if (logger.isDebugEnabled()) {
logger.debug(String.format("certificate intermerdiart validated : IssuerDN=%s",
trustedCerts[i].getSubjectDN()));
}
found = validateKeyChain(trustedCerts[i], trustedCerts);
}
} catch (CertPathValidatorException e) {
// validation fail, check next certifiacet in the
// trustedCerts array
}
}
}

return found;
}

/**
*
* @param cert
* is X509Certificate that will be tested
* @return true if cert is self signed, false otherwise
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
*/
private static boolean isSelfSigned(final X509Certificate cert)
throws CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
try {
PublicKey key = cert.getPublicKey();

cert.verify(key);
return true;
} catch (SignatureException sigEx) {
return false;
} catch (InvalidKeyException keyEx) {
return false;
}
}

/**
* donne le trusted keystore (le charge une seule fois).
*
* @return
* @throws CertificateIsabelSignatureVerificationException
*/
private synchronized static KeyStore getTrustedKeystore() throws CertificateIsabelSignatureVerificationException {
if (trustedKeystore == null) {
trustedKeystore = loadKeystore(TRUSTED_KEYSTORE, TRUSTED_KEYSTORE_PWD);
}
return trustedKeystore;
}

/**
* chargement du keystore spécifié.
*
* @param path
* chemin du keystore, dans le classpath.
* @return le keystore chargé.
* @throws CertificateIsabelSignatureVerificationException
*/
private static KeyStore loadKeystore(final String path, final char[] passsword)
throws CertificateIsabelSignatureVerificationException {
try {

if (logger.isDebugEnabled()) {
logger.debug(String.format("loading keystore %s ...", path));
}

KeyStore ks = KeyStore.getInstance("JKS");
ks.load( //
CertificateChainValidator.class.getResourceAsStream(path) //
, passsword //
);

return ks;
} catch (Exception ex) {
throw new CertificateIsabelSignatureVerificationException(
String.format("Echec lecture du keystore %s", path), ex);
}
}

/**
* Valide le certificat client : s'assure qu'il est valide et vérifie qu'il
* est bien associé à un certifact root connu (dans trusted.jks).
*
* @param certEncoded
* @throws CertificateIsabelSignatureVerificationException
*/
public static void validateClientCertificate(final byte[] certEncoded)
throws CertificateIsabelSignatureVerificationException {

try {
// le keystore contenant tous les certificats reconnus
KeyStore ks = getTrustedKeystore();

// récupère le certificat client
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificat = (X509Certificate) certFactory
.generateCertificate(new ByteArrayInputStream(certEncoded));

if (logger.isDebugEnabled()) {
logger.debug(String.format("certificate validation : IssuerDN=%s", certificat.getSubjectDN()));
}

boolean valid = validateKeyChain(certificat, ks);
if (logger.isDebugEnabled()) {
logger.debug(String.format("certificate valid : %s", valid));
}
if (!valid) {
throw new CertificateIsabelSignatureVerificationException("The certificate is not valid");
}

} catch (CertificateIsabelSignatureVerificationException ex) {
throw ex;
} catch (Exception ex) {
throw new CertificateIsabelSignatureVerificationException("Error during validation", ex);
}
}

}

最佳答案

您无法比较颁发者DN,因为任何人都可以使用该字符串创建证书。

每个证书都已使用颁发者的私钥进行了数字签名,因此您需要使用信任库中现有证书的公钥来验证客户端证书的签名。如果存在匹配,则您的证书是“受信任的”,但会继续证书链中的下一个证书。

注意:我没有检查你的代码。您可能想查看建议的链接

关于java - X509 认证路径验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46709158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com