【发布时间】:2016-11-01 13:39:33
【问题描述】:
我有一系列 X509Certificates 以用户证书开头并以受信任的 CA 证书结尾。为了测试,我正在尝试使用 Google 证书。
我想检查证书链中每个证书的吊销状态。
我正在使用以下代码:
public static boolean isCertChainValid(ArrayList<X509Certificate> certificateList) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
CertPath certPath = certificateFactory.generateCertPath(certificateList);
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
KeyStore keystore = KeyStore.getInstance("JKS");
InputStream is = new FileInputStream(System.getProperty("java.home") + "/lib/security/" + "cacerts");
keystore.load(is, "changeit".toCharArray());
PKIXParameters params = new PKIXParameters(keystore);
params.setRevocationEnabled(true);
Security.setProperty("ocsp.enable", "true");
System.setProperty("com.sun.net.ssl.checkRevocation", "true");
System.setProperty("com.sun.security.enableCRLDP", "true");
PKIXCertPathValidatorResult r = (PKIXCertPathValidatorResult) validator.validate(certPath, params);
return true;
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch (CertPathValidatorException e) {
throw new RuntimeException(e);
}
}
这是我获取证书列表的方式:
public static void main(String args[]) throws Exception {
CertVal certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.pem"), "X.509");
X509Certificate cert = (X509Certificate) certVal.getCert();
certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.int.pem"), "X.509");
X509Certificate int_cert = (X509Certificate) certVal.getCert();
certVal = new CertVal(new File("/home/varun/Documents/SampleCerts/google.root.pem"), "X.509");
X509Certificate root_cert = (X509Certificate) certVal.getCert();
System.out.println(cert.toString());
ArrayList<X509Certificate> cList = new ArrayList<>();
cList.add(cert);
cList.add(int_cert);
cList.add(root_cert);
System.out.println(isCertChainValid(cList));
}
google.pem, google.int.pem, google.root.pem 分别是浏览器中通过导出选项获得的最终证书、中间证书和根证书。
CertVal 是我制作的一个类,它将从文件中导入证书,其方法将返回证书对象。它工作正常,并且很好地打印了最终证书,如下所示:
[ [ 版本:V3 主题:CN=*.google.com,O=Google Inc,L=Mountain 查看,ST=加利福尼亚,C=美国签名算法:SHA256withRSA,OID = 1.2.840.113549.1.1.11
密钥:Sun EC 公钥,256 位公共 x 坐标: 46177506158937302063723158048612066903199153823785912505310712817097913459047 公共 y 坐标: 113809014154880901150321029617294838083005712679903474974082163637608868220331 参数:secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7) 有效期:[来自:2016 年 6 月 16 日星期四 14:07:32 IST, 至:Thu Sep 08 13:59:00 IST 2016] 发行人:CN=Google Internet Authority G2,O=Google Inc,C=US 序列号:[
51e47ed1 28a4436e]证书扩展:9 [1]:ObjectId:1.3.6.1.5.5.7.1.1 Criticality=false AuthorityInfoAccess [ [ accessMethod: caIssuers 访问位置:URIName:http://pki.google.com/GIAG2.crt,
accessMethod: ocsp accessLocation: URIName: http://clients1.google.com/ocsp]][2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [ 密钥标识符 [ 0000: 4A DD 06 16 1B BC F6 68 B5 76 F5 81 B6 BB 62 1A J......h.v....b. 0010: BA 5A 81 2F
.Z./]][3]:ObjectId:2.5.29.19 Criticality=true BasicConstraints:[
CA:false PathLen: 未定义][4]:ObjectId:2.5.29.31 Criticality=false CRLDistributionPoints [
[分发点: [URIName:http://pki.google.com/GIAG2.crl]]][5]:ObjectId:2.5.29.32 Criticality=false CertificatePolicies [
[CertificatePolicyId: [1.3.6.1.4.1.11129.2.5.1] [] ]
[CertificatePolicyId: [2.23.140.1.2.2] [] ] ][6]:ObjectId:2.5.29.37 Criticality=false ExtendedKeyUsages [
serverAuth clientAuth ][7]:ObjectId:2.5.29.15 Criticality=false KeyUsage [
数字签名][8]:ObjectId:2.5.29.17 Criticality=false SubjectAlternativeName [
DNSName:*.google.com DNSName:*.android.com DNSName: *.appengine.google.com DNSName:*.cloud.google.com DNSName:*.google-analytics.com DNSName:*.google.ca DNSName:*.google.cl DNSName:*.google.co.in DNSName: *.google.co.jp DNS 名称: *.google.co.uk DNSName: *.google.com.ar DNSName: *.google.com.au DNSName: *.google.com.br DNSName: *.google.com.co DNSName: *.google.com.mx DNSName:*.google.com.tr DNSName:*.google.com.vn DNSName:*.google.de DNSName:*.google.es DNSName:*.google.fr
DNSName:*.google.hu DNSName:*.google.it DNSName:*.google.nl
DNSName:*.google.pl DNSName:*.google.pt DNSName: *.googleadapis.com DNSName:*.googleapis.cn DNSName:*.googlecommerce.com DNSName:*.googlevideo.com DNSName:*.gstatic.cn DNSName:*.gstatic.com DNSName:*.gvt1.com DNSName:* .gvt2.com DNSName:*.metric.gstatic.com DNSName:*.urchin.com DNSName:*.url.google.com DNSName:*.youtube-nocookie.com DNSName: *.youtube.com DNSName:*.youtubeeducation.com DNSName:*.ytimg.com DNSName:android.clients.google.com DNSName:android.com DNSName: g.co DNSName:goo.gl DNSName:google-analytics.com DNSName: google.com DNS 名称:googlecommerce.com DNS 名称:urchin.com
DNSName: www.goo.gl DNSName: youtu.be DNSName: youtube.com
DNS 名称:youtubeeducation.com][9]:ObjectId:2.5.29.14 关键性 = 假 SubjectKeyIdentifier [ 密钥标识符 [ 0000: EE 4B 83 40 44 28 0A 6A 01 4D 55 D0 A4 A7 5F 1E .K.@D(.j.MU..._. 0010: DF 60 F2 1E
.`.. ] ]] 算法:[SHA256withRSA] 签名:0000:38 89 81 D8 57 DA 3C C7 60 EA BA 6B 08 D4 92 47 8...W.<.>..k...G 0010: 60 AA B1 4B 39 34 1C E4 7B CC 71 1F 28 8F 07 82..K94....q.(... 0020: D7 04 3F CC 12 B7 9E DF 9F 13 D4 5A 5A 30 31 1F ..?........ZZ01。 0030: A5 41 BE 9A 60 27 EE AF 28 A8 BC 21 2F 65 31 BF .A..
'..(..!/e1. 0040: A5 7D D6 D4 86 89 27 7F F6 3B 28 D6 16 AA 60 31 ......'..;(...1 0050:3D CD 67 97 84 22 43 2F B0 53 84 87 8C 47 44 5C =.g.."C/.S...GD\ 0060: EF 16 7A 73 2F 37 CB 39 48 3C F2 87 C5 77 82 A0 ..zs/7.9H<...w.. c6 a8 cc .. c1 bc b1 bb b6 ..........z.4... c4 db ae b7 f9 e7 .7 ce b0 f2 ac c2 ...u.h.9...h.... e8 d4 d0 fb ......ei cf d6 e6 f4 ...... f8 c5 df a5 i.. e1 a2 a1 c8 bf e4 . eb d7 bd.......>]
正如在证书例外 9:[1] 和 [2] 中看到的,OSCP URL 和 CRL URL 都可用于证书。这两个东西也在中间证书中,但它们在根证书中没有,这是合理的,因为它们不需要它们。
我的问题是当我运行上面的程序时,它给了我以下错误。
线程“主”java.lang.RuntimeException 中的异常: java.security.cert.CertPathValidatorException:证书没有 指定 OCSP 响应者 test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157) 在 test_data.ImportAndTestCert.main(ImportAndTestCert.java:72) 引起 通过:java.security.cert.CertPathValidatorException:证书确实 不指定 OCSP 响应者 sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) 在 sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219) 在 sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) 在 sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) 在 java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) 在 test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126) ... 1 更多
如果我评论Security.setProperty("ocsp.enable", "true");,它会给我以下错误:
线程“主”java.lang.RuntimeException 中的异常: java.security.cert.CertPathValidatorException:无法确定 撤销状态 test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:157) 在 test_data.ImportAndTestCert.main(ImportAndTestCert.java:72) 引起 作者:java.security.cert.CertPathValidatorException:无法确定 撤销状态 sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:135) 在 sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:219) 在 sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:140) 在 sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79) 在 java.security.cert.CertPathValidator.validate(CertPathValidator.java:292) 在 test_data.ImportAndTestCert.isCertChainValid(ImportAndTestCert.java:126) ... 1 更多
我错过了什么吗?
感谢您的帮助。
【问题讨论】:
标签: java security ssl certificate x509certificate