[英]SSLHandshakeException Behavior in Certificate Chains
我已经使用此证书链的存储证书实现了证书锁定:
不过,我注意到了一个奇怪的行为:
你知道行为 2 是否是预期的,如果是,为什么? 我的印象是应该使用链中的所有证书,否则我会得到 SSLHandshakeException。 谢谢!
更新代码
class SSLPinning {
void exec() {
// Open InputStreams for each certificate
InputStream baltimoreInputStream = getClass().getResourceAsStream("baltimore.cer");
InputStream hcpmsInputStream = getClass().getResourceAsStream("hcpms_cert.cer");
InputStream verizonInputStream = getClass().getResourceAsStream("verizon.cer");
try {
// CertificateFactory has the method that generates certificates from InputStream
// Default type for getInstance is X.509
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Create Certificate objects for each certificate
Certificate baltimoreCertificate = cf.generateCertificate(baltimoreInputStream);
Certificate hcpmsCertificate = cf.generateCertificate(hcpmsInputStream);
Certificate verizonCertificate = cf.generateCertificate(verizonInputStream);
// Create KeyStore and load it with our certificates
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
//keyStore.setCertificateEntry("hcpms", hcpmsCertificate);
keyStore.setCertificateEntry("intermediate", verizonCertificate); //surprisingly, it works with just using the intermediate CA
//keyStore.setCertificateEntry("root", baltimoreCertificate);
// Create a TrustManagerFactory using KeyStore -- this is responsible in authenticating the servers
// against our stored certificates
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// Create an SSLContext using TrustManagerFactory -- this will generate the SSLSocketFactory we will use
// during HTTPS connection
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
URL url = new URL("https://account.hanatrial.ondemand.com/");
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url.openConnection();
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
httpsURLConnection.connect();
System.out.print("Server authentication successful");
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (SSLHandshakeException e) {
System.out.println("Server authentication failed");
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
}
您的主要问题是,为了验证证书,必须存在可信链(可信证书和所有中间证书,直到服务器/叶证书)。 然而,大多数 SSL/TLS 服务器不会向您发送完整的链。 您有时只能获得叶证书(没有中间证书或根证书;您可以在例如 Wireshark 流量转储中看到这一点)。
其他服务器可能会向您发送叶证书和所有/某些中间证书,但不会发送根证书。
在这种情况下,您的本地信任库包含缺少的证书以构建完整链至关重要。
根据您的观察,我假设服务器只发送没有中间证书和根证书的叶证书。 因此,为了成功验证,您的信任库必须包含中间证书作为受信任的证书才能使其工作(否则此证书将丢失)。 我建议将根证书和中间证书都包含到您的信任库中。
顺便说一句:服务器不发送中间 CA 证书也可能是服务器配置问题。 通常我会建议配置一个服务器来发送叶证书和中间证书。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.