我正在尝试使用Java安全性验证证书路径。但我似乎无法让它发挥作用。
我有4张证书:CA
,CA1
,alice
和bob
。 CA1
和bob
都由CA
签名。 Alice
已由CA1
签署。
以下测试类有许多测试。 testPath()
尝试确保证书实际上具有我认为他们拥有的关系。此测试成功。
然后接下来的3次测试尝试为CA1,alice和bob创建证书路径,并将CA作为可信任的ca.
bob
和CA1
成功,alice
失败。
看起来像我的路径构建器在中间证书正在运行时失败。
我的考试班
package test.project;
import test.project.CertificateValidationException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class CertificateTest {
static X509Certificate CA, CA1, alice, bob;
static CertificateStore certStorage;
public CertificateTest () {
}
@BeforeClass
public static void setUpClass() throws GeneralSecurityException, IOException{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
certStorage = new CertificateStore ();
try(InputStream stream = AbstractCentralCertificateStorageTest.class.getResourceAsStream("/ca.crt")){
CA = (X509Certificate)certStorage.certFactory.generateCertificate(stream);
}
try(InputStream stream = AbstractCentralCertificateStorageTest.class.getResourceAsStream("/ca-int1.crt")){
CA1 = (X509Certificate)certStorage.certFactory.generateCertificate(stream);
}
try(InputStream stream = AbstractCentralCertificateStorageTest.class.getResourceAsStream("/alice.crt")){
alice = (X509Certificate)certStorage.certFactory.generateCertificate(stream);
}
try(InputStream stream = AbstractCentralCertificateStorageTest.class.getResourceAsStream("/bob.crt")){
bob = (X509Certificate)certStorage.certFactory.generateCertificate(stream);
}
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of validate method.
*/
@Test
public void testValidate_X509Certificate1() throws Exception {
certStorage.setCAs(Arrays.asList(new X509Certificate[]{CA1}));
certStorage.setTrustedCAs(Arrays.asList(new X509Certificate[]{CA}));
certStorage.validate(alice);
}
@Test
public void testValidate_X509Certificate1() throws Exception {
certStorage.setCAs(Arrays.asList(new X509Certificate[]{CA1}));
certStorage.setTrustedCAs(Arrays.asList(new X509Certificate[]{CA}));
certStorage.validate(bob);
}
@Test
public void testValidate_X509Certificate1() throws Exception {
certStorage.setCAs(Arrays.asList(new X509Certificate[]{CA1}));
certStorage.setTrustedCAs(Arrays.asList(new X509Certificate[]{CA}));
certStorage.validate(CA1);
}
@Test
public void testPath() throws Exception{
alice.verify(CA1.getPublicKey());
bob.verify(CA.getPublicKey());
CA1.verify(CA.getPublicKey());
alice.checkValidity();
bob.checkValidity();
CA.checkValidity();
CA1.checkValidity();
assertEquals(alice.getIssuerX500Principal(), CA1.getSubjectX500Principal());
assertEquals(bob.getIssuerX500Principal(), CA.getSubjectX500Principal());
assertEquals(CA1.getIssuerX500Principal(), CA.getSubjectX500Principal());
}
}
testPath测试成功,bob和CA1测试成功,但alice测试没有。它抛出CertPathBuilderException。
抛出异常的方法是:
public PKIXCertPathBuilderResult buildPath(X509Certificate cert) throws CertificateValidationException, CertPathBuilderException {
X509Certificate cert;
X509Certificate[] intermediateCerts = new X509Certificate[0];
if(certChain != null && certChain.length>0){
cert = certChain[0];
if(certChain.length > 1){
intermediateCerts = Arrays.copyOfRange(certChain, 1, certChain.length);
}
}else{
throw new CertificateValidationException(null, "Could not validate Certificate Chain. Chain was empty or Null");
}
logger.debug("Building path for "+cert+" with intermediates: "+Arrays.asList(intermediateCerts));
X509CertSelector selector = new X509CertSelector();
selector.setIssuer(cert.getIssuerX500Principal());
selector.setSerialNumber(cert.getSerialNumber());
// Specify root CAs
Set<TrustAnchor> trustAnchors = new HashSet<>();
for (X509Certificate trustedRootCert : this.getTrustedCAs()) {
trustAnchors.add(new TrustAnchor(trustedRootCert, null));
}
// Configure the PKIX certificate builder algorithm parameters
PKIXBuilderParameters pkixParams;
try {
pkixParams = new PKIXBuilderParameters(trustAnchors, selector);
} catch (InvalidAlgorithmParameterException ex) {
throw new CertificateValidationException(cert, "Could not validate certificate. An invalid algorithm was speficied.", ex);
}
pkixParams.setMaxPathLength(6);
// Disable CRL checks. We have enough complexity thanks...
pkixParams.setRevocationEnabled(false);
// Specify a list certificates. Add both CA's trustedCAs and target
CertStore intermediateCertStore;
try {
Set<X509Certificate> certificates = new HashSet<>();
certificates.addAll(this.getTrustedCAs()); //Gets the trustedCAs set in the test (CA)
certificates.addAll(this.getCAs()); //Gets the CAs set in the test (CA1)
certificates.add(cert); //Sets the certificate target
intermediateCertStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certificates));
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException ex) {
throw new CertificateValidationException(cert, "Could not validate certificate. Exception caught when creating intermediate cert store", ex);
}
pkixParams.addCertStore(intermediateCertStore);
// Build and verify the certification chain
CertPathBuilder builder;
try {
builder = CertPathBuilder.getInstance("PKIX");
} catch (NoSuchAlgorithmException ex) {
throw new CertificateValidationException(cert, "Could not validate certificate. Exception caught when creating CertPathBuilder", ex);
}
//Log a lot of stuff
for(TrustAnchor anchor : pkixParams.getTrustAnchors()){
logger.debug("trustedCA: "+anchor.getTrustedCert());
}
for(CertStore store : pkixParams.getCertStores()){
try {
for(Certificate c : store.getCertificates(null)){
logger.debug("CA: store: "+store.getType()+"["+store.getProvider().getName()+"]: "+c);
}
} catch (CertStoreException ex) {
logger.debug("Could not retrieve cert");
}
}
PKIXCertPathBuilderResult result;
try {
result = (PKIXCertPathBuilderResult) builder.build(pkixParams);
} catch (InvalidAlgorithmParameterException ex) {
throw new CertificateValidationException(cert, "Could not validate certificate. Exception caught when building Certificate path", ex);
}
return result;
}
方法getTrustedCAs
和getCAs
返回可信证书颁发机构和证书颁发机构。日志告诉我证书&#34; CA&#34;由getTrustedCAs()和&#34; CA1&#34;返回由getCAs()返回。
testPath
测试显示alice由CA1(中级)签名,bob由CA(可信CA)签名,CA1由CA签名。
我可以在日志中看到所有证书都在日志和调试器中加载到intermediateCertstore中。
有人可以告诉我我做错了什么吗?为什么该方法适用于由CA直接签名的bob和CA1,而不适用于由CA1签名的alice?我误解了有关证书的问题,还是我遇到了代码问题?
所有证书均未被撤销,或在有效期之外。
证书打印到字符串:
23:48:14.949 [main] DEBUG c.P.l.u.AbstractCentralCertificateStorage - CA: store: Collection[SUN]: [0] Version: 3
SerialNumber: -87661101532789169401713647165930791168
IssuerDN: CN=CAROOT
Start Date: Tue Jul 14 23:48:14 CEST 2015
Final Date: Sun Jul 19 23:48:14 CEST 2015
SubjectDN: CN=CAROOT
Public Key: RSA Public Key
modulus: f7ae28c17658d97636b292da645280f84a058184efbf79102ae9c90866e42f3724c6078ed57f71ef608e50afb58594b901ff9dba7ae987c7925119d35f8d292e343ea54ce5a6098526f7f42ee05f9c4c7addf64d445a2747510beefff5aa12208e6a5442836f63e0454a083893a255cb6425f24e34113926a62ef38b0978903d543120baa66a98deb165de0c4da060585f3301fff2f7c9c6df412234887fac8dfeb6664a2f2c6ecdc8cca449d321177412390c9fc5f1045ec5ef5fdb009a672466669044e162a69e6ff495bc64070ccdae564f2aac4ca777199a25e5731435c37bb8fb7bfdc90549abe35f459f01f3c36d69a5580c31548f6d98895bc3fc82d1
public exponent: 10001
Signature Algorithm: SHA1WITHRSA
Signature: a63b11692c4115f316619dbc703104c0cd14ff7a
011fdc6822cf9f46bd951a58d6d9bba321422141
2c7fae53828f8e65d2f27e4ecd5392b91df18bdb
e78eea91b7d1e18e3b221b4c5e0d6d8cc8bfd0d9
b86f42f12ce64b0ea19752aff813cbaec267f522
81298e823b05cc76913a03967b735c03517ee4bd
d44a2de561a1a9fa4b120b08fa7fbdc112f88d20
b3dffbae75155d3fcc8427da7ffdd8fca4d6329c
163d15c0a23673634a54ad9ee131445e6f543e57
194eb6d0b2cb40cdd4248ddaa18d1c78105f6704
4202db4e2882daeed7376210e3a9638d0a6f01b5
65e0e87c853600907c1a6451f19251d91b3825dd
7d07ce0350a9606eebcccf950caefde7
Extensions:
critical(false) 2.5.29.14 value = DER Octet String[20]
critical(false) 2.5.29.35 value = Sequence
Tagged [0] IMPLICIT
DER Octet String[20]
critical(false) KeyUsage: 0x6
critical(false) 2.5.29.37 value = Sequence
ObjectIdentifier(2.5.29.37.0)
critical(false) 2.5.29.17 value = Sequence
Tagged [6] IMPLICIT
DER Octet String[19]
critical(false) 1.3.6.1.5.5.7.1.1 value = Sequence
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.2)
Tagged [6] IMPLICIT
DER Octet String[14]
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.1)
Tagged [6] IMPLICIT
DER Octet String[16]
critical(false) 2.5.29.31 value = Sequence
Sequence
Tagged [0]
Tagged [0]
Tagged [6] IMPLICIT
DER Octet String[15]
23:48:14.952 [main] DEBUG c.P.l.u.AbstractCentralCertificateStorage - CA: store: Collection[SUN]: [0] Version: 3
SerialNumber: 126038779198800081330846530986414066668
IssuerDN: CN=CAROOT
Start Date: Tue Jul 14 23:48:14 CEST 2015
Final Date: Sun Jul 19 23:48:14 CEST 2015
SubjectDN: CN=INTERMEDIATE
Public Key: RSA Public Key
modulus: be9326abb13f09cf601efc4ae4f3f5577132339f4263a838ba28f3a57e77ff069a134f344502936a273087047b424fa6360d42b58b4907ba9ff86b34fe368e8ad8a3884e29fbb7ea793c0f7fa07456d47fe7bcd3577bd8c792683883193f3b9af66b0bb6d646b99de322659184d07a9f9a6d2a8f588534feb43c87d83252099ad8cc901143e40839cec7969850b2188a6c795663277afb63fe1fc44035e0d467e174ca47e17989213c11379df41978244f1fc6e9888a366cf6636631edb21baf5ce02de6653552eb3b88a9af021dcb93975f60a5b50f6f1709a3c3b9ef5c75abdb2e4dc08c3f6bae087daf84314ab14d22c8e20d1351b543568282529325c41f
public exponent: 10001
Signature Algorithm: SHA1WITHRSA
Signature: 2acefadb8d9669e305723b4f6e0c2da00cae588d
a8a390c2bd9abaa830f8f68f07ae6df06d1a9b2a
9c7d342e80e114c9ff7aa829beab84c35fdf9cc9
cb6b37ce66824e87bc4f42289a9e52ac13cb3d57
02c3fc7f0b86138cc3a844bb80235ea1091e8354
de7f5f1b1581aacb5527f331a7bc706d2b1e6d22
74a428eed280905b86e631a5bc9546433df90033
e6e4a66e367fe50f249aa32529d7b7343d2c9a42
ed6109356ae6241812145ef4a83c537038a00ecb
68a86fda20bcbb072801dbb4d8e547a356948a65
a417b87a64ccd244eac23cc0ef9dd24ac071d9e1
40750eda7be97728c293c36cbd692c44415fec15
fa658d80d231602cb6762e509aade70a
Extensions:
critical(false) 2.5.29.14 value = DER Octet String[20]
critical(false) 2.5.29.35 value = Sequence
Tagged [0] IMPLICIT
DER Octet String[20]
critical(false) KeyUsage: 0x6
critical(false) 2.5.29.37 value = Sequence
ObjectIdentifier(2.5.29.37.0)
critical(false) 2.5.29.17 value = Sequence
Tagged [6] IMPLICIT
DER Octet String[19]
critical(false) 1.3.6.1.5.5.7.1.1 value = Sequence
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.2)
Tagged [6] IMPLICIT
DER Octet String[14]
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.1)
Tagged [6] IMPLICIT
DER Octet String[16]
critical(false) 2.5.29.31 value = Sequence
Sequence
Tagged [0]
Tagged [0]
Tagged [6] IMPLICIT
DER Octet String[15]
23:48:14.954 [main] DEBUG c.P.l.u.AbstractCentralCertificateStorage - CA: store: Collection[SUN]: [0] Version: 3
SerialNumber: -144831244968902948917803188139978579108
IssuerDN: CN=INTERMEDIATE
Start Date: Tue Jul 14 23:48:14 CEST 2015
Final Date: Sun Jul 19 23:48:14 CEST 2015
SubjectDN: DC=DC2,DC=DC1,OU=OU2,OU=OU1,CN=Alice
Public Key: RSA Public Key
modulus: 9abc857e092b81a48db05cc3bb162860f2b0ff120daf3bd5edb808b202ae2bcb7264d60c7fc59da080fbf9ef6a2800a6078d7cbd1e79abe1cf6f72e54ab1f85c4a8211707babd034258dae1adf7b1fa8de064124cee0afe1e7cf2cdab5ae68661054da5ed6c7e29528bf8a6e16e32701e98ac2e6a13be960c9db24ac30911dabacccb28d5dda16b7ae809b9076870290b1ec9226f9e291e295f310a493a326b8c3acba980e67e1aaa732ddad582c6a20a41878667742daecdb0698c5425ad8cb2843420c805be62e09d19199c7231718339243fae313e1cc367f70054c3141d520993e12cc5ae1cca8449d9cdf51b59aae7a544135c4fcdb97c6e98e75cdc66b
public exponent: 10001
Signature Algorithm: SHA1WITHRSA
Signature: 3ddb0118a9651c9b18aab7ef75abe307ac02b589
66b10eaf36c9b565185cca3e4f04d81b7bb97a27
1d644ce3f0756c76881598e55f14ddfeaa5843c9
4268814b067e422bca234efc314b51b1620bb7cd
a7cc1dd3b6f6fb15f4a81d175e9f2a07df6fa698
96817780bd15d7abf086fb86962da9022a1f489f
a70cfc68acda2c3afb19a270663df282cfd58efb
15dfc3eb00ce3933488d699717248f14aaba7058
c11630f67134d2c740e78cea2f67a75141cf3690
109bd9ea112192c2ec35836cd5d6bc1f2484abd0
e1597bc8540be4bdb95935b2020b72c028a0893b
525e0059749f7cbb0141b09740778d5dbdcbcd69
f66c353e70c1419602e98b3be2a30a82
Extensions:
critical(false) 2.5.29.14 value = DER Octet String[20]
critical(false) 2.5.29.35 value = Sequence
Tagged [0] IMPLICIT
DER Octet String[20]
critical(false) KeyUsage: 0xb0
critical(false) 2.5.29.32 value = Sequence
Sequence
ObjectIdentifier(2.5.29.32.0)
critical(false) 1.3.6.1.5.5.7.1.1 value = Sequence
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.2)
Tagged [6] IMPLICIT
DER Octet String[14]
Sequence
ObjectIdentifier(1.3.6.1.5.5.7.48.1)
Tagged [6] IMPLICIT
DER Octet String[16]
critical(false) 2.5.29.31 value = Sequence
Sequence
Tagged [0]
Tagged [0]
Tagged [6] IMPLICIT
DER Octet String[15]