问题 如何通过Android访问SSL连接?


我开始关注一个没有安装Android的教程,并得到了这个:

    System.setProperty("javax.net.ssl.trustStore", "truststore");
    System.setProperty("javax.net.ssl.trustStorePassword", "password");

    SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    try {
        Socket s = ssf.createSocket("192.168.2.11", 6543);
        PrintWriter out = new PrintWriter(s.getOutputStream());
        while (true){
            out.println("SSL TEST");
            Log.d("DATA", "DATA SENT");
        }



    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

我想这归结为几个问题:

  1. 我没有创建自己的信任库,但是在线搜索教程和内容,我不知道如何创建一个。有没有办法可以创建或修改信任存储以获得我需要的证书? (如果有任何区别,我使用的是自签名证书)

  2. 如何使SSL握手顺利运行?现在,我得到的错误是:

    javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚。
    

    老实说,我真的不明白这意味着什么。

  3. 我需要在Android设备上修改哪些设置或文件才能确保可以进行此连接?


8365
2018-06-22 14:01


起源

您可能应该从Android方式开始,而不是尝试修改非Android技术。 - Matt Ball
我也尝试从我的服务器放置我的密钥库文件并将其放在我的jdk / jre / lib / security文件夹中,然后更改信任存储位置和密码以匹配它,我得到了相同的异常。 - Matt
等待!什么是“Android的做法”? - Matt
如果我大声呼救,这是否意味着人们会更快地回答我的问题?此外,我目前的方法是尝试从SSLContext获取SSLSocketFactory,我试图用我的密钥库初始化。仍在解决这里的问题,但它可能很有希望。 - Matt


答案:


1)这取决于。您是否在服务器端拥有自签名证书,并且您正在尝试验证您的身份到Android设备?或者你是否在android端试图验证你的服务器的理由?如果是前者,那么请看这个链接: http://www.codeproject.com/KB/android/SSLVerification_Android.aspx?display=Mobile

您需要特别注意它创建KeyStore文件的位置。

2)您收到该错误的原因是因为它不信任您正在连接的服务器,因为您没有正确创建信任库或者您正在连接到尚未将证书添加到信任库的服务器。你究竟要连接到什么?

3)确保你有 <uses-permission android:name="android.permission.INTERNET" /> 在manifest.xml中。

编辑 道歉,请看我对第一段所做的更改。

以下是初始化密钥库和信任库的部分

SSLcontext sslContext = SSLContext.getDefault();

KeyStore trustSt = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = this.getResources().openRawResource(R.raw.truststore);
trustSt.load(trustStoreStream, "<yourpassword>".toCharArray());
trustManagerFactory.init(trustStre);

KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = this.getResources().openRawResource(R.raw.keystore);
keyStore.load(keyStoreStream, "<yourpassword>".toCharArray());
keyManagerFactory.init(keyStore, "<yourpassword>".toCharArray());

sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

10
2018-06-22 14:14



[+1] 1)我会调查一下(在查看本网站之前),我不确定我是否理解密钥库和信任库之间的区别。 2)我可能没有正确创建信任存储...我在JRE中使用了keytool功能3)看起来我至少得到了这个部分:0) - Matt
嗨,对不起,我在第一段中犯了一个错误,请查看更改。 - Otra
我想到信任存储和密钥库之间的区别的方式是信任存储是我信任的证书列表,所以如果我在android端,我想在我的信任存储中拥有服务器证书。密钥库是我保存凭据以验证服务器的地方。在服务器端,信任存储区是我保存我信任的客户端列表的位置,密钥库是我保留自己凭据的位置。 - Otra
你在做客户端身份验证吗? (Android设备是否需要证书?)一旦我知道这一点,我就可以用一些代码编辑我的回复。 - Otra
叹 这没有解决它,我仍然得到我原来的帖子中详述的相同的异常。所以现在怎么办? - Matt


除非对等方使用自签名证书,否则您不需要自己的信任库。 JRE附带一个默认使用的信任库,它信任所有主要CA颁发的证书。


1
2018-06-23 01:03



但我使用的是自签名证书...... - Matt
@Matt所以你需要创建一个信任库。从JDK复制一个;将服务器证书导出到文件中;并将其导入新的信任库。 - user207421