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

0dxa2lsx  于 2023-08-05  发布在  Android
关注(0)|答案(2)|浏览(110)

总结:

当我们得到“对等端的证书与预期的主机名不匹配”错误时,如何使用通配符证书创建到服务器的套接字?
基本上,我想创建一个安全的WebSocket(wss)到一个带有通配符证书的服务器。我用的是this websocket library现在,当我想连接到网站时,连接会立即关闭,并显示以下错误日志:
2021-03-16 13:14:16.221 21027-21097/com.....app W/System.err:com.neovisionaries.ws.client.HostnameUnverifiedException:peer的证书与预期的主机名不匹配(sthsth.sthsth.ir)2021-03-16 13:14:16.221 21027-21097/com..... app W/System.err:© 2018 - 2019 www.socketconnector.com版权所有并保留所有权利© 2018 - 2019 www.socketconnector.com版权所有并保留所有权利© 2018 - 2019 www.socketconnector.com版权所有并保留所有权利© 2018 - 2019 WebSocket版权所有并保留所有权利at 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:== Chain 0 ==版本: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:SubjectDN:CN=*.sthsthnet.ir,C=US 2021-03-16 13:14:15.908 21027-21097/com.....app E/Conscrypt:IssuerDN:CN=Certum域验证CA SHA 2,OU=Certum认证机构,O=Unizeto Technologies S.A.,C=PL 2021-03-16 13:14:15.914 21027-21097/com..... app E/Conscrypt:在以下之前获取:2019 -03-16 13:14:15.916 21027-21097/com.....app E/Conscrypt:不要在以下情况下获得:2021-03-16 13:14:15.918 21027-21097/com.....app E/Conscrypt:签名ALG名称:SHA256withRSA 2021-03-16 13:14:15.921 21027-21097/com.....app E/Conscrypt:签名:
22bc2d40a15e881292c19f5b47ca610cc3efb90e998b7eddf08ab108f56@3df1b7ea7f2ac25b8df74cc49735f3fe7f509fe87ea42c080424f450f8f1bf04a35e4c97dac79ee2df66cde96f4a7a1fb6b62f5640f0a111a157 feb7ef5ceab2588cad1731bbf22434d2ee3e0fcbec8ff74ad194d0c2a5ab1 13b4d00302e62721052b7d0afacc6cda129c3ff99db165d3836a1e2900dd66f8eb3b05f4aab6f42de2a85a60c5382d8bf229c3b866a662326606444685f62673cfbe5fd6a4dc21aa8b18e36c9e13423917aabf79b817011a757262f7b16629745a44162eb9a58ebab4a 2021-03-16 13:14:16 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);


是否有其他解决方案可以在不影响安全性或维护性的情况下仅通过主机验证问题?

p1iqtdky

p1iqtdky1#

我以前也遇到过同样的问题,发现大公司签署的证书是受设备信任的,所以当其他人试图制作自己的证书时,这是非常危险的,因为(在这种情况下)android不能确定你的数据是否经过了良好的加密
您应该拥有正确的证书或信任所有证书。第二种解决方案可以用于开发,但绝不能用于生产环境

mdfafbf1

mdfafbf12#

答:通配符证书受Android设备信任,与自定义证书相反。代码的Android部分没有问题问题,问题是我们的后端人员只在代码中包含了一个证书文件,而不是证书链(链上的顶级证书,而不是其他证书),这就是为什么我们的WebSocket库产生了这个错误。此外,在自定义证书的情况下,最好的方法是将证书固定或包括Android应用程序上的服务器CA(证书颁发机构)文件,并在清单文件中引用它,但应用程序很容易被篡改,需要采取安全措施。

相关问题