以下是我用于测试SSLSocket
针对https://badssl.com返回的SSLCertificateSocketFactory
个实例的代码:
SSLCertificateSocketFactory factory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0);
mSocket = factory.createSocket();
factory.setHostname(mSocket, host);
mSocket.connect(new InetSocketAddress(host, 443), timeout);
mInput = mSocket.getInputStream();
mOutput = mSocket.getOutputStream();
此代码在连接到badssl.com:443
时有效,在连接到expired.badssl.com:443
或self-signed.badssl.com:443
时会按预期引发异常,但在连接到{时不会抛出 {1}}。
如果这有所不同,请注意https://badssl.com上的所有主机名似乎共享一个IP,因此需要为SNI配置wrong.host.badssl.com:443
。
PS:这是在运行Android 6.0.1的Nexus 5上观察到的。
答案 0 :(得分:1)
TL; TR:根据你的代码,它根本不会检查主机名。
来自documentation of SSLCertificateSocketFactory:
大多数SSLSocketFactory实现都不验证服务器的身份,允许中间人攻击。此实现确实检查服务器的证书主机名,但仅针对指定主机名的createSocket变体。当使用使用InetAddress的方法或返回未连接套接字的方法时,您必须自己验证服务器的身份以确保安全连接。
因此,如果您使用local_i == 0
,它应检查套接字。但如果您使用fcreateSocket(hostname,...)
,则不会检查名称,因为它不知道要检查的主机名。 createSocket()
调用仅用于设置SNI TLS扩展名。