我正在尝试使用 SSLCertificateSocketFactory.setHostname 添加 SNI 支持,使用 wireshark 我看到客户端和启用 SNI 的服务器之间的通信,CLIENT HELLO 转到服务器(设置正确的主机名),服务器以 Server Hello 响应并将证书发送到客户端但是在该客户端没有发送证书并且通信/握手停止之后,通过openssl命令openssl s_client -connect theclient -servername thehostname -cert thecertificate 一切顺利,握手成功..
我正在使用套接字,并且在 socket.startHandshake 上出现异常:IOException:javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚。
final SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
socket = (SSLSocket) sslSocketFactory.createSocket(InetAddress.getByName("theserver"), 443);
socket.setEnabledProtocols(socket.getSupportedProtocols());
String[] cipherArray = socket.getEnabledCipherSuites();
for(int i = 0; i<cipherArray.length; i++) {
Log.e("","Available Cipher:"+cipherArray[i]);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
sslSocketFactory.setHostname(socket, "thehostname");
} else {
try {
java.lang.reflect.Method setHostnameMethod = socket.getClass().getMethod("setHostname", String.class);
setHostnameMethod.invoke(socket, "thehostname");
} catch (Exception e) {
Log.w("", "SNI not useable", e);
}
}
socket.setSoTimeout(20000);
socket.setUseClientMode(true);
Log.i(getClass().toString(), "Connected.");
socket.startHandshake();
SSLSession session = socket.getSession();
boolean secured = session.isValid();
这个IOexception SSLHANDSHAKEEXCEPTION对android开发者的解决方案是https://developer.android.com/training/articles/security-ssl.html#CommonProblems:
“从 InputStream 中获取特定的 CA,使用它来创建 KeyStore,然后使用它来创建和初始化 TrustManager。TrustManager 是系统用来验证来自服务器的证书,并且通过从 KeyStore 创建一个或更多 CA——这些将是该 TrustManager 信任的唯一 CA。
给定新的 TrustManager,该示例初始化一个新的 SSLContext,它提供了一个 SSLSocketFactory,您可以使用它来覆盖 HttpsURLConnection 中的默认 SSLSocketFactory。这样,连接将使用您的 CA 进行证书验证。”
现在 sslcontext 返回 SSLSOCKETFACTORY,我想使用 SSLCertificateSocketFactory (用于 sethostname 方法)做什么.. 我希望问题很清楚,如果不让我知道或随时让我更清楚