- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我开发的应用程序中,我检查客户端在传入消息中发送的证书:除了基本证书有效性检查(证书签名、到期日期...)之外,我还检查客户端是否可信。
为此,我创建了一个仅包含受信任证书的 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/
问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可
我正在玩 Rank-N-type 并尝试输入 x x .但我发现这两个函数可以以相同的方式输入,这很不直观。 f :: (forall a b. a -> b) -> c f x = x x g ::
这个问题已经有答案了: How do you compare two version Strings in Java? (31 个回答) 已关闭 8 年前。 有谁知道如何在Java中比较两个版本字符串
这个问题已经有答案了: How do the post increment (i++) and pre increment (++i) operators work in Java? (14 个回答)
下面是带有 -n 和 -r 选项的 netstat 命令的输出,其中目标字段显示压缩地址 (127.1/16)。我想知道 netstat 命令是否有任何方法或选项可以显示整个目标 IP (127.1.
我知道要证明 : (¬ ∀ x, p x) → (∃ x, ¬ p x) 证明是: theorem : (¬ ∀ x, p x) → (∃ x, ¬ p x) := begin intro n
x * x 如何通过将其存储在“auto 变量”中来更改?我认为它应该仍然是相同的,并且我的测试表明类型、大小和值显然都是相同的。 但即使 x * x == (xx = x * x) 也是错误的。什么
假设,我们这样表达: someIQueryable.Where(x => x.SomeBoolProperty) someIQueryable.Where(x => !x.SomeBoolProper
我有一个字符串 1234X5678 我使用这个正则表达式来匹配模式 .X|..X|X. 我得到了 34X 问题是为什么我没有得到 4X 或 X5? 为什么正则表达式选择执行第二种模式? 最佳答案 这里
我的一个 friend 在面试时遇到了这个问题 找到使该函数返回真值的 x 值 function f(x) { return (x++ !== x) && (x++ === x); } 面试官
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: Isn't it easier to work with foo when it is represented b
我是 android 的新手,我一直在练习开发一个针对 2.2 版本的应用程序,我需要帮助了解如何将我的应用程序扩展到其他版本,即 1.x、2.3.x、3 .x 和 4.x.x,以及一些针对屏幕分辨率
为什么案例 1 给我们 :error: TypeError: x is undefined on line... //case 1 var x; x.push(x); console.log(x);
代码优先: # CASE 01 def test1(x): x += x print x l = [100] test1(l) print l CASE01 输出: [100, 100
我正在努力温习我的大计算。如果我有将所有项目移至 'i' 2 个空格右侧的函数,我有一个如下所示的公式: (n -1) + (n - 2) + (n - 3) ... (n - n) 第一次迭代我必须
给定 IP 字符串(如 x.x.x.x/x),我如何或将如何计算 IP 的范围最常见的情况可能是 198.162.1.1/24但可以是任何东西,因为法律允许的任何东西。 我要带198.162.1.1/
在我作为初学者努力编写干净的 Javascript 代码时,我最近阅读了 this article当我偶然发现这一段时,关于 JavaScript 中的命名空间: The code at the ve
我正在编写一个脚本,我希望避免污染 DOM 的其余部分,它将是一个用于收集一些基本访问者分析数据的第 3 方脚本。 我通常使用以下内容创建一个伪“命名空间”: var x = x || {}; 我正在
我尝试运行我的test_container_services.py套件,但遇到了以下问题: docker.errors.APIError:500服务器错误:内部服务器错误(“ b'{” message
是否存在这两个 if 语句会产生不同结果的情况? if(x as X != null) { // Do something } if(x is X) { // Do something } 编
我是一名优秀的程序员,十分优秀!