Android:对于套接字来说,传递“对等方的证书与预期主机名不匹配”错误的最安全方法?

问题描述 投票:0回答:2

总结:

当我们收到“对等方的证书与预期主机名不匹配”错误时,如何使用通配符证书创建到服务器的套接字?


基本上,我想为具有通配符证书的服务器创建一个安全的 websocket (wss)。我正在使用这个 websocket 库。现在,当我想连接到网站时,连接会立即关闭并显示以下错误日志:

2021-03-16 13:14:16.221 21027-21097/com.....app W/System.err:com.neovisionaries.ws.client.HostnameUnverifiedException:对等方的证书与预期的主机名不匹配( sthsth.sthsth.ir) 2021-03-16 13:14:16.221 21027-21097/com.....app W/System.err: 在 com.neovisionaries.ws.client.SocketConnector.verifyHostname(SocketConnector.java:281) 2021-03-16 13:14:16.222 21027-21097/com.....app W/System.err: 在 com.neovisionaries.ws.client.SocketConnector.doConnect(SocketConnector.java:246) 2021-03-16 13:14:16.222 21027-21097/com.....app W/System.err: 在 com.neovisionaries.ws.client.SocketConnector.connect(SocketConnector.java:190) 2021-03-16 13:14:16.222 21027-21097/com.....app W/System.err: 在 com.neovisionaries.ws.client.WebSocket.connect(WebSocket.java:2351) 2021-03-16 13:14:16.223 21027-21097/com.....app W/System.err: 在 com.....app.network.GeneralSocketService$1.run(GeneralSocketService.java:167)

2021-03-16 13:14:15.895 21027-21097/com.....app E/Conscrypt: ------------------不可信链: ---------------------- 2021-03-16 13: 14:15.896 21027-21097/com.....app E/Conscrypt: == Chain0 == 版本: 3 2021-03-16 13:14:15.897 21027-21097/com.....app E/Conscrypt: 序列号: e63f80cf7a1220146cc8fd96d8468a4 2021-03-16 13:14:15.900 21027-21097/com.....app E/Conscrypt: 主题DN:CN=*.sthsthnet.ir,C=US 2021-03-16 13:14:15.908 21027-21097/com.....app E/Conscrypt: IssuerDN: CN=Certum Domain 验证 CA SHA2、OU=Certum 证书颁发机构、O=Unizeto Technologies S.A.,C=PL 2021-03-16 13:14:15.914 21027-21097/com.....app E/Conscrypt:不要在以下时间之前获取:7 月 30 日星期二 10:35:53 GMT+04:30 2019 2021-03-16 13:14:15.916 21027-21097/com.....app E/Conscrypt:不要在以下时间之后获取:7 月 29 日星期四 10:35:53 GMT+04:30 2021 2021-03-16 13:14:15.918 21027-21097/com.....app E/Conscrypt: Sig ALG 名称: SHA256withRSA 2021-03-16 13:14:15.921 21027-21097/com.....app E/Conscrypt: 签名:
22bc2d40a15e881292c19f5b47ca610cc3efb90e998b7eddf08ab108f56ec3df1b7ea7f2ac25b8df74cc49735f3fe7f509fe87ea42c080424f450f8f1bf04a35e4c97d ac79ee2df66cde96f4a7a1fb6b62f5640f0a111a157feb7ef5ceab2588cad1731bbf22434d2ee3e0fcbec8ff74ad194d0c2a5ab113b4d00302e62721052b7d0afacc6cda129c3ff 99db165d3836a1e2900dd66f8eb3b05f4aab6f42de2a85a60c5382d8bf229c3b866a662326606444685f62673cfbe5fd6a4dc21aa8b18e36c9e13423917aabf79b81 7011a757262f7b16629745a44162eb9a58ebab4adeefb4710a439f34844b0489f44d3afe0a1ba2e0f78dd5fc04009b0096e1837 2021-03-16 13:14:16.213 21027-21097/com.....app E/Conscrypt:公开 关键:

 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03
 82 01 0f 00 30 82 01 0a 02 82 01 01 00 9d b2 14 d0 11 c4 8f
 29 42 7a ee 09 1e 30 2e 62 dd 14 b8 6b 7b 1b 6b fe 03 ba 6a
 07 6b 6c 69 b3 07 58 51 cf c0 4c 67 15 7e 0f 46 45 33 2b f5
 50 20 db 2c 45 f7 8a 52 29 d2 a0 10 65 31 1d 9f d9 90 2f 83
 e9 d7 c1 ee 1a a6 e8 47 3d 89 fb 8b cf d0 d7 7f ac de d1 39
 ec 4b 8d 43 a4 d5 c2 95 e4 ab 4e 6e 2b a6 b7 24 f7 62 1b 3e
 4a 27 ca a0 d7 9f 22 c3 25 d8 bd 54 39 27 51 99 d5 fa 13 ed
 88 8a 64 9c ce 60 38 ae ea 7e 5f ee ed b1 ff cf 30 56 6d 5c
 01 ad 0c d8 87 f0 4f c7 89 85 e0 d1 08 89 e8 69 dc 6e 35 c0
 7d fc e6 37 33 00 a9 c8 7b 88 9e eb 98 02 bc 6c 9c f4 b7 6b
 87 ca 15 1d 31 37 95 07 8e d2 c8 6a db 92 e0 93 35 4b f8 b0
 29 b9 8f 21 d8 70 0a 5d 91 c5 fb 9c 51 b2 3e a8 6e 53 78 64
 5c e5 c3 06 02 ab e5 0e 11 96 ea a9 f4 99 ea f2 66 d2 c2 6b
 86 eb 90 0d f1 85 3f ef 51 02 03 01 00 01

现在使用我知道使用:

WebSocketFactory.setVerifyHostname(false);

导致另一个错误,我不想更改我的代码,因此它会验证各种证书或自签名证书,如下所示:

TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] myTrustedAnchors = new X509Certificate[0];
return myTrustedAnchors;
}

@Override
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
}

@Override
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
}
}};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new SecureRandom());
factory.setSSLContext(sslContext);
socket = factory.createSocket(API_SOCKET);TooTallNate/Java-WebSockethttps://github.comTooTallNate/Java-WebSockethttps://github.com

也不是这个:

SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
                    factory.setSSLContext(sslContext);
                    socket = factory.createSocket(API_SOCKET);

我也不想在我的应用程序中存储服务器的证书,因为它可能会不时更改并且维护会失控:

    //1. Get the cert file from the server 
    //2. Converted the cert to a BKS format
    
    
     // loading CAs from an InputStream 
CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
InputStream cert = context.getResources().openRawResource(R.raw.my_cert); 
Certificate ca;
 try {
 ca = cf.generateCertificate(cert);
 } finally {
 cert.close();
 } 
// creating a KeyStore containing our trusted CAs 
String keyStoreType = KeyStore.getDefaultType(); 
KeyStore keyStore = KeyStore.getInstance(keyStoreType); 
keyStore.load(null, null); 
keyStore.setCertificateEntry("ca", ca); 
// creating a TrustManager that trusts the CAs in our KeyStore 
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
tmf.init(keyStore); 
// creating an SSLSocketFactory that uses our TrustManager 
SSLContext sslContext = SSLContext.getInstance("TLS"); 
sslContext.init(null, tmf.getTrustManagers(), null); 

是否有另一种解决方案可以仅通过主机验证问题而不影响安全性或维护?

java android websocket ssl-certificate wildcard
2个回答
0
投票

以前也遇到过同样的问题,发现大公司签署的证书受到设备的信任,所以当其他人尝试制作自己的证书时,这是非常危险的,因为(在这种情况下)android无法确定您的数据加密良好

您要么应该拥有正确的证书,要么信任所有证书。第二种解决方案适合开发,但永远不应该在生产中使用


0
投票

答案:与自定义证书相反,通配符证书受到 Android 设备的信任。 Android部分代码没有问题 问题是我们的后端人员只在代码中包含了一个证书文件,而不是证书链(链上的顶级证书而不是其他证书),这就是我们的

WebSocket
库产生该错误的原因。 另外,对于自定义证书,最好的方法是在 Android 应用程序上固定证书或包含服务器 CA(证书颁发机构)文件,并在清单文件中引用它,但该应用程序很容易被篡改,需要安全措施。

© www.soinside.com 2019 - 2024. All rights reserved.