没有以前的互联网连接,无法验证Android自签名证书

时间:2014-08-12 13:34:18

标签: android ssl https certificate self-signed

使用SSL基础架构:

我们有一个有效的客户端/服务器设置,其中Android版本4.2和4.4的手机充当客户端,必须通过其自签名SSL证书验证服务器。

问题:

只要设备在尝试连接之前至少有一次互联网访问权限,服务器证书验证就会起作用。但是,如果执行恢复出厂设置且设备直接连接到没有Internet连接的专用网络,则证书验证将失败。

重现行为:

  1. 出厂重置手机
  2. 重新启动而不选择连接到具有互联网访问权限的WiFi
  3. 尝试验证自签名SSL证书 - >的失败
  4. 连接到可上网的WiFi
  5. 重新连接到原始专用网络
  6. 尝试验证自签名SSL证书 - >的 WORKS
  7. 从技术上讲,设备不应该需要互联网访问来验证自签名证书。在进行任何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
    

1 个答案:

答案 0 :(得分:32)

确保设备上的时间正确,证书具有有效期,并且不会验证日期是否设置为过去(通常在出厂重置后的2000年1月1日)或将来。设备将通过NTP自动同步,但是当没有可用的Internet连接时,这显然不起作用。