Ash*_*win 6 java certificate keystore x509certificate pkix
我有一个Web应用程序,要求客户端发送它的证书,服务器必须验证证书(即查看颁发者是否是有效的颁发者并出现在服务器的信任库中).这是代码:
FileInputStream fin=new FileInputStream("C:/trustedca");
KeyStore anchors = KeyStore.getInstance("JKS","SUN");
anchors.load(fin, "server".toCharArray());
X509CertSelector target = new X509CertSelector();
FileInputStream fin1=new FileInputStream("C:/client.crt");
CertificateFactory cf=CertificateFactory.getInstance("X.509");
X509Certificate cert=null;
while (fin1.available() > 0)
{
System.out.println("in while---------");
cert =(X509Certificate) cf.generateCertificate(fin1);
}
target.setCertificate(cert);
PKIXBuilderParameters params = new PKIXBuilderParameters(anchors, target);
CertPathBuilder builder = (CertPathBuilder) CertPathBuilder.getInstance("PKIX").build(params);
PKIXCertPathBuilderResult r = (PKIXCertPathBuilderResult) builder.build((CertPathParameters)params);<br>
Run Code Online (Sandbox Code Playgroud)
但我得到一个例外:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid
certification path to requested target<br>
Run Code Online (Sandbox Code Playgroud)
注意:
客户端发送的证书是client.crt,用于签署client.crt证书的证书是密钥库"trustedca"中存在的ca.crt.那为什么要给出这个例外呢?
Bru*_*uno 12
如果您期望获得客户端证书,请让JSSE为您完成所有这些工作.如果要将特定连接用于自己的信任库,请配置JSSE以使用它.检查参考文档中的Customizing JSSE部分.
以下是SSLContext使用自定义信任库构建的简短示例.(X509TrustManager也可以使用其他更复杂的s,但你很少需要它.)
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../example.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
Run Code Online (Sandbox Code Playgroud)
如果您正在使用现有的应用程序服务器,那么如何通过配置传递将取决于服务器及其预期配置方式.为此使用JSSE还将确保密钥用法属性是合适的.
如果您通过其他方式获得证书并想要验证它,则需要使用PKI API.如果您按照使用PKIX算法验证认证路径的示例,您应该得到如下内容:
X509Certificate certToVerify = ...
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath cp = cf.generateCertPath(Arrays
.asList(new X509Certificate[] { certToVerify }));
TrustAnchor trustAnchor = new TrustAnchor(caCert, null);
CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
PKIXParameters pkixParams = new PKIXParameters(
Collections.singleton(trustAnchor));
pkixParams.setRevocationEnabled(false);
cpv.validate(cp, pkixParams);
Run Code Online (Sandbox Code Playgroud)
检查来自validate的结果(当然它没有抛出验证异常).在这里,我已禁用撤销检查以简化.您还可以设置PKIXParameters策略检查的其他方面.这可能变得非常复杂(为什么最好让默认的JSSE经理为你做这件事).
您在Security.SE上询问的另一个问题的上下文中也询问了所有这些问题:证书指纹的实际价值是多少?.
假设你有两个X509Certificates:serverCert和caCert,你要验证哪个serverCert是签名的(与公钥匹配的私钥)caCert.
最简单的方法:
serverCert.verify(caCert.getPublicKey());
Run Code Online (Sandbox Code Playgroud)
如果您想手动执行此操作,请使用SignatureAPI:
System.out
.println("Signature algorithm: " + serverCert.getSigAlgName());
Signature sig = Signature.getInstance(serverCert.getSigAlgName());
sig.initVerify(caCert.getPublicKey());
sig.update(serverCert.getTBSCertificate());
System.out
.println("Verified? " + sig.verify(serverCert.getSignature()));
Run Code Online (Sandbox Code Playgroud)
假设算法是SHA1withRSA,您还可以计算摘要:
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
digest.update(serverCert.getTBSCertificate());
byte[] digestBytes = digest.digest();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, caCert.getPublicKey());
byte[] cipherText = cipher.doFinal(serverCert.getSignature());
Run Code Online (Sandbox Code Playgroud)
摘要本身将只使用结果的一部分Cipher:你得到了什么serverCert.getSignature(),其实是一个更复杂的ASN.1结构,它包括摘要算法标识符,在这种情况下,digestBytes应该用什么前缀这样的:
SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.
Run Code Online (Sandbox Code Playgroud)
(如果要正确分析ASN.1结构,BouncyCastle可能很有用.)
请注意,这些都不会验证时间有效性或任何其他属性.PKIX合规性不仅仅是检查签名(参见RFC 3820和5820).
| 归档时间: |
|
| 查看次数: |
7987 次 |
| 最近记录: |