使用SSL基础架构:
我们有一个有效的客户端/服务器设置,其中Android版本4.2和4.4的手机充当客户端,必须通过其自签名SSL证书验证服务器.
问题:
只要设备在尝试连接之前至少有一次互联网访问权限,服务器证书验证就会起作用.但是,如果执行恢复出厂设置且设备直接连接到没有Internet连接的专用网络,则证书验证将失败.
重现行为:
>出厂重置手机
>重新启动而不选择连接到具有Internet访问权限的WiFi
>尝试验证自签名SSL证书 – >失败
>连接到可上网的WiFi
>重新连接到原始专用网络
>尝试验证自签名SSL证书 – >作品
从技术上讲,设备不应该需要Internet访问来验证自签名证书.在进行任何SSL服务器验证之前,是否存在某种必须加载的黑名单?我可以阻止这种行为吗?
创建SSL上下文:
//Using a client certificate String password = "clientpass"; KeyStore keyStore = KeyStore.getInstance("PKCS12"); InputStream is = context.getResources().openRawResource(R.raw.client); keyStore.load(is,password.tocharArray()); is.close(); KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); kmf.init(keyStore,password.tocharArray()); KeyManager[] keyManagers = kmf.getKeyManagers(); // Using self signed certificate CertificateFactory cf = CertificateFactory.getInstance("X.509"); is = context.getResources().openRawResource(R.raw.cacert); InputStream caInput = new BufferedInputStream(is); Certificate ca; try { ca = cf.generateCertificate(caInput); Log.i("CA","ca=" + ((X509Certificate) ca).getSubjectDN()); } finally { caInput.close(); } // Create a KeyStore containing our trusted CAs KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null); trustStore.setCertificateEntry("ca",ca); // Create a TrustManager that trusts the CAs in our KeyStore TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(trustStore); TrustManager[] trustManagers = tmf.getTrustManagers(); // Create an SSLContext that uses our Trustmanager and Keymanager SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(keyManagers,trustManagers,null); //create a socket to connect with the server SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(serverAddr,port); socket.setUseClientMode(true); socket.addHandshakeCompletedListener(this); socket.startHandshake();
在startHandshake中出现异常失败:
javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: null
解决方法
确保设备上的时间正确,证书具有有效期,并且不会验证日期是否设置为过去(通常在出厂重置后的2000年1月1日)或将来.设备将通过NTP自动同步,但是当没有可用的Internet连接时,这显然不起作用.