Android TLS握手

weixin_38066919 2019-09-12 01:15:32
我想了解Android到服务器的TLS连接.任何人都可以纠正我吗? 启动TLS连接有两种.首先,只有服务器有证书,客户决定信任与否.其次,客户端和服务器都有证书.我对吗? 如何在Android设备上为TLS连接生成自定义唯一证书并将其用于连接到服务器?我发现只实现了第一种连接. 有谁能够帮我?
...全文
31 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38071769 2019-09-12
  • 打赏
  • 举报
回复
要通过TLS实现双方身份验证,您需要在服务器端和客户端上拥有密钥库. 我通常使用Portecle工具来创建密钥库,它是一个非常容易使用的基于Java的工具.您可以在portecle.sourceforge.net上下载它 您将需要使用该工具为服务器端创建JKS格式的密钥库,并为客户端创建BKS格式的另一个密钥库.格式不同,因为Android本身不支持使用JKS密钥库,只支持BKS,反之亦然. 一旦创建了两个密钥库,就需要为每个密钥库生成密钥对(公钥和私钥). Portecle在工具栏上有一个按钮,在“工具”子菜单下调用,可以执行此操作.公共密钥算法和大小是RSA 2048位.之后,您需要为证书设置一些参数,例如组织单位,名称,地点等. 现在你有两个密钥库和两个密钥对. 要允许客户端解密服务器接收的消息,必须为客户机密钥库提供服务器密钥库的公钥.要做到这一点,只需右键单击服务器密钥库上的密钥对,然后单击“导出”选项.然后选择“证书链”并在文件系统上选择一个位置来存储证书. 现在,您已准备好在客户端密钥库中导入公钥.为此,请单击“工具”工具栏并选择“导入可信证书”,然后查找在上一步中导出的证书文件.将出现一些警告消息,指示您无法建立信任路径,暂且不用担心. 因此,现在您拥有带密钥对的客户端密钥库和服务器证书.这在客户端就足够了. 现在,有必要将客户端密钥对导入服务器密钥库.在客户端密钥库上,右键单击密钥对,然后选择“导出”.在打开的弹出窗口中选择“私钥和证书”,然后选择PKCS#12格式. 然后,打开服务器密钥库并使用“工具”工具栏的“导入密钥对”子菜单,然后选择在上一步中导出的密钥对. 请记住,以BKS格式保存客户端密钥库以及以JKS格式保存服务器密钥库非常重要. 好的,这都是密钥库,现在是编码的时候了. 我们从服务器代码开始吧.下一个片段是从我运行的java Spring项目中提取的.它是一个嵌入式tomcat,所以配置是纯java,很容易找到如何在传统的tomcat配置上配置ssl连接器,所以我只会放入嵌入式版本. private Connector createSslConnector() { //print the client keystore printClientKeystore(); Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); try { //read the keystore from the jar //and write it to a tmp file Resource keystoreResource = context.getResource("classpath:config/server.keystore"); byte[] keystoreData = readKeystore(keystoreResource.getInputStream()); File tmpKeystoreFile = File.createTempFile("keystore", ""); writeKeystore(tmpKeystoreFile, keystoreData); //keystore information final String keystoreFile = tmpKeystoreFile.getAbsolutePath(); final String keystorePass = "yourKeystorePass"; final String keystoreType = "pkcs12"; final String keystoreProvider = "SunJSSE"; final String keystoreAlias = "comics_tomcat"; connector.setScheme("https"); connector.setAttribute("clientAuth", "true"); connector.setPort(HTTPS_PORT); connector.setSecure(true); protocol.setSSLEnabled(true); //keystore protocol.setKeystoreFile(keystoreFile); protocol.setKeystorePass(keystorePass); protocol.setKeystoreType(keystoreType); protocol.setProperty("keystoreProvider", keystoreProvider); protocol.setKeyAlias(keystoreAlias); //truststore protocol.setTruststoreFile(keystoreFile); protocol.setTruststorePass(keystorePass); protocol.setPort(HTTPS_PORT); return connector; } catch (IOException e) { LOGGER.error(e.getMessage(), e); throw new IllegalStateException("cant access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]", e); } } 这一切都是针对服务器端的,你有一个带有安全标志的ssl连接器,使用’setSecure(true)’方法.这允许您使用私钥/公钥验证来要求用户身份验证. 以下代码用于客户端,它加载密钥库,信任库(通过使用相同的密钥库),配置主机名验证程序以允许连接到特定域,然后打开连接. KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); //load keystore stream byte[] keystoreData = readInputStream(getAssets().open("client.keystore")); //load keystore ByteArrayInputStream bais = new ByteArrayInputStream(keystoreData); keyStore.load(bais, KEYSTORE_PASSWORD.toCharArray()); //load truststore bais = new ByteArrayInputStream(keystoreData); trustStore.load(bais, KEYSTORE_PASSWORD.toCharArray()); //load trustmanager TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); //init keymanager KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, KEYSTORE_PASSWORD.toCharArray()); //create ssl context sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { List<String> allowedHostnames = new ArrayList<String>(); allowedHostnames.add("pinterest.com"); allowedHostnames.add("192.168.1.43"); allowedHostnames.add("10.0.2.2"); return allowedHostnames.indexOf(hostname) != -1; } }; //open https connection URL url = new URL("https://" + SERVER_URL + ":" + SERVER_PORT + "/api/v1/publication/getDescriptor/" + publicationId); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); urlConnection.setHostnameVerifier(HOSTNAME_VERIFIER); //read server response byte[] serverResult = readInputStream(urlConnection.getInputStream()); 如果您有任何疑问,请告诉我!

433

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧