在Java中针对CAvalidationX.509证书

可以说我有这样的东西(客户端代码):

TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } } }; SSLContext sslc = SSLContext.getInstance("TLS"); sslc.init(null, trustAllCerts, null); SocketFactory sf = sslc.getSocketFactory(); SSLSocket s = (SSLSocket) sf.createSocket("127.0.0.1", 9124); 

这段代码是完整的function,但我真的无法弄清楚,如何根据我在pem文件中提供的一个具体CA证书validation服务器的证书。

所有证书都由我的自签名CA签名,它是我需要validation的CA(仅针对此证书)。

每个答案都表示赞赏。

编辑:

回应jglouie (非常感谢你这样做 – 不能投票给你答案)。

我创立了解决方案:

 new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) throws CertificateException { InputStream inStream = null; try { // Loading the CA cert URL u = getClass().getResource("tcp/cacert.pem"); inStream = new FileInputStream(u.getFile()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate ca = (X509Certificate) cf.generateCertificate(inStream); inStream.close(); for (X509Certificate cert : certs) { // Verifing by public key cert.verify(ca.getPublicKey()); } } catch (Exception ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); } finally { try { inStream.close(); } catch (IOException ex) { Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); } } } } }; 

我假设您的CA的自签名证书已按如下方式加载:

 CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream finStream = new FileInputStream("CACertificate.pem"); X509Certificate caCertificate = (X509Certificate)cf.generateCertificate(finStream); 

然后在检查证书的方法中:

 @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws CertificateException { if (certs == null || certs.length == 0) { throw new IllegalArgumentException("null or zero-length certificate chain"); } if (authType == null || authType.length() == 0) { throw new IllegalArgumentException("null or zero-length authentication type"); } //Check if certificate send is your CA's if(!certs[0].equals(caCertificate)){ try { //Not your CA's. Check if it has been signed by your CA certs[0].verify(caCertificate.getPublicKey()) } catch(Exception e){ throw new CertificateException("Certificate not trusted",e); } } //If we end here certificate is trusted. Check if it has expired. try{ certs[0].checkValidity(); } catch(Exception e){ throw new CertificateException("Certificate not trusted. It has expired",e); } } 

免责声明:甚至没有尝试编译代码

接受的答案非常不正确。 它不会以加密方式validation服务器证书与受信任的证书颁发机构之间的任何连接。 通常,您几乎不需要实现自己的TrustManager,这样做非常危险。

正如EJP所说,没有必要实现自己的TrustManager,您可以使用默认的TrustManager,并确保已将可信CA证书添加到您的默认TrustStore。 有关更多信息,请参阅此问题 。

查看JDK中的CertPathValidator类,它通过受信任的CAvalidation服务器自己的证书的连续信任链。 有关证书链validation的介绍,请参阅Oracle的文档 。

此代码完全正常运行

此代码完全失效。 它完全不安全,甚至不符合自己的规格。 很少需要提供您自己的TrustManager,默认的工作正常。

您需要做的就是确保您拥有的CA证书存在于您的信任库中,然后将系统属性javax.net.ssl.trustStore设置为指向它,如果它不是默认的Java信任库文件。 如果不通过命令行-D选项设置它,则除了可能的System.setProperty()之外,您根本不需要编写任何代码。

编辑您的“解决方案”肯定不会起作用。 它假定链中的每个证书都由您的证书签名。 如果签名证书=您的证书,则对于长度为1的链或长度为2的链只能为真。