java 通过SSL/TLS加密https建立连接
来源:互联网 发布:python3防止sql注入 编辑:程序博客网 时间:2024/06/04 18:35
这个项目是基于与Ruby客户端进行通信,经过查看源代码,发现对方是经过TLS加密通信。第一次调试,尝试用serversocket与对方进行沟通,可以收到数据,但是无法获取http的包头数据,因此,将先对socket通信进行处理。
一、根据原有软件进行沟通,可以找到原来生成的rcs-db.key、rcs-db.crt文件,可知rcs-db.crt为证书,rcs-db.key为秘钥。因为并没有任何思路来处理这两个文件,我就先打开看一看。发现秘钥的内容如下:
-----BEGIN RSA PRIVATE KEY-----MIICWwIBAAKBgQDBajNHgexQbClBGOxJgTkevfZU4R/OmI2BZUgt3DD4RNO4cXtG...........................................................................-----END RSA PRIVATE KEY-----
可知使用的是RSA公钥加密算法。并且根据源码可知,是用OpenSSL加密的。开始我就根据http://blog.csdn.net/chaijunkun/article/details/7275632/这篇文章所讲将公钥和私钥都解了出来,可是并不知道怎么去使用。
然后查了一下,要通过一下步骤可以将key和certificate应用在Java里面。
安装好openssl。
首先将.key、crt文件转换成.jks文件及一对公私钥存储在新建的PKCS12 keystore中。
# Create PKCS12 keystore from private key and public certificate.openssl pkcs12 -export -name myservercert -in selfsigned.crt -inkey server.key -out keystore.p12# Convert PKCS12 keystore into a JKS keystorekeytool -importkeystore -destkeystore mykeystore.jks -srckeystore keystore.p12 -srcstoretype pkcs12 -alias myservercert
然后可以用这个命令来查看keystore中的jks。注意这里我们将jks的别名起为myservercert。crt,p12记得加上地址。
keytool -list -v -keystore mykeystore.jks
但是要保证是自签证的证书,否则需要按此步骤顺着证书链找到可信赖的证书。
相关概念:Keytool 是一个有效的安全钥匙和证书的管理工具。Java 中的 keytool.exe (位于 JDK\Bin 目录下)可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的一条证书包含该条证书的私钥,公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件,数字证书文件只包括主体信息和对应的公钥。 Keytool 把钥匙和证书储存到一个keystore.默任的实现keystore的是一个文件.它用一个密码保护钥匙。
因为是需要双向认证的,因此我们需要生成truststore。JSSE使用Truststore和Keystore文件来提供客户端和服务器之间的安全数据传输。keytool是一个工具可以用来创建包含公钥和密钥的的keystore文件,并且利用keystore文件来创建只包含公钥的truststore文件。我们通过下面的5步简单的创建truststore和keystore文件:
生成一个含有一个私钥的keystore文件
验证新生成的keystor而文件
导出凭证文件
把认凭证件导入到truststore文件
验证新创建的truststore文件
导出凭证文件 在这一步,你可以导出自我签署凭证或是Verisign或其他的认证机构的商业凭证的。这里只说导出自我签署的凭证: 通过执行下面的命令把自我签署的凭证保存到 “selfsignedcert.cer”文件 :
keytool -export -alias certificatekey -keystore keystore.jks -rfc -file selfsignedcert.cer
把认凭证件导入到truststore文件 执行下面的命令:
keytool -import -alias myservercert -file selfsignedcert.cer -keystore truststore.jks
最后验证新创建的truststore文件 执行下面的命令 :
keytool -list -v -keystore truststore.jks二、至此,我们已经将Truststore和Keystore全部倒入keytool中了。因为我需要解析包头。全部的代码如下:
package com.cms.listener;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.net.URLDecoder;import java.security.KeyStore;import java.util.ArrayList;import java.util.StringTokenizer;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocket;import javax.net.ssl.SSLServerSocketFactory;import javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManagerFactory;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;/** * Application Lifecycle Listener implementation class WorkerListener * */public class WorkerListener implements ServletContextListener {//调用线程池ApplicationContext ctx = new ClassPathXmlApplicationContext("config/spring/applicationContext.xml"); ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor)ctx.getBean("taskExecutor");//定义端口号public static final int SERVER_PORT = 442; /** * @see ServletContextListener#contextDestroyed(ServletContextEvent) */ public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub }/** * @see ServletContextListener#contextInitialized(ServletContextEvent) */ public void contextInitialized(ServletContextEvent arg0) { // TODO Auto-generated method stub try { String serverKeyStoreFile = "c:\\Windows\\System32\\mykeystore.jks"; String serverKeyStorePwd = "changeit"; String catServerKeyPwd = "changeit"; String serverTrustKeyStoreFile = "c:\\RCS\\DB\\config\\certs\\truststore.jks"; String serverTrustKeyStorePwd = "changeit"; KeyStore serverKeyStore = KeyStore.getInstance("JKS"); serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray()); KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS"); serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(serverKeyStore, catServerKeyPwd.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(serverTrustKeyStore); SSLContext sslContext = SSLContext.getInstance("TLSv1"); //第二个参数TrustManager[] 是认证管理器,在需要双向认证时使用 sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT); //sslServerSocket.setNeedClientAuth(true); while (true) { SSLSocket s = (SSLSocket)sslServerSocket.accept(); Accepter accepter = new Accepter(s); accepter.service(); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } } class Accepter { private SSLSocket socket; public Accepter(SSLSocket socket) { this.socket = socket; System.out.println("连接到服务器的用户:" + socket); } public void service() { taskExecutor.execute(new Runnable() {public void run() {//这里编写处理业务代码synchronized (this) {try { // 第一阶段: 打开输入流 InputStream is = socket.getInputStream(); System.out.println("客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>"); // 读取第一行, 请求地址 String line = readLine(is, 0); //打印请求行 System.out.print(line); // < Method > < URL > < HTTP Version > <\r\n> 取的是URL部分 String line2 = line; String httpversion = line2.substring(line2.length()-10).trim(); httpversion = URLDecoder.decode(httpversion, "UTF-8");//反编码 URL 地址 String resource = line.substring(line.indexOf('/'), line.lastIndexOf('/') - 5); //获得请求的资源的地址 resource = URLDecoder.decode(resource, "UTF-8");//反编码 URL 地址 String method = new StringTokenizer(line).nextElement().toString();// 获取请求方法, GET 或者 POST int contentLength = 0;//如果为POST方法,则会有消息体长度 // 读取所有浏览器发送过来的请求参数头部信息 do { line = readLine(is, 0); //如果有Content-Length消息头时取出 if (line.startsWith("Content-Length")) { contentLength = Integer.parseInt(line.split(":")[1].trim()); } //打印请求部信息 System.out.print(line); //如果遇到了一个单独的回车换行,则表示请求头结束 } while (!line.equals("\r\n")); //如果是POST请求,则有请求体 if ("POST".equalsIgnoreCase(method)) { //注,这里只是简单的处理表单提交的参数,而对于上传文件这里是不能这样处理的, //因为上传的文件时消息体不只是一行,会有多行消息体 System.out.print(readLine(is, contentLength)); System.out.println(); } System.out.println("客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<"); System.out.println("用户请求的资源是(uri):" + resource); System.out.println("请求的类型是: " + method); System.out.println("请求的http版本是: " + httpversion); System.out.println("连接到服务器的用户:" + socket.getRemoteSocketAddress()); } catch (Exception e) { // replace with other code e.printStackTrace(); } }}}); } }/* 这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后 才返回,否则如果没有读取,则一直阻塞,这就导致如果为POST请求时,表单中的元素会以消息体传送, 这时,消息体最末按标准是没有回车换行的,如果此时还使用BufferedReader来读时,则POST提交 时会阻塞。如果是POST提交时我们按照消息体的长度Content-Length来截取消息体,这样就不会阻塞 */ private String readLine(InputStream is, int contentLe) throws IOException { ArrayList lineByteList = new ArrayList(); byte readByte; int total = 0; if (contentLe != 0) { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); total++; } while (total < contentLe);//消息体读还未读完 } else { do { readByte = (byte) is.read(); lineByteList.add(Byte.valueOf(readByte)); } while (readByte != 10); } byte[] tmpByteArr = new byte[lineByteList.size()]; for (int i = 0; i < lineByteList.size(); i++) { tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue(); } lineByteList.clear(); String tmpStr = new String(tmpByteArr, "UTF-8"); /* http请求的header中有一个Referer属性,这个属性的意思就是如果当前请求是从别的页面链接过 来的,那个属性就是那个页面的url,如果请求的url是直接从浏览器地址栏输入的就没有这个值。得 到这个值可以实现很多有用的功能,例如防盗链,记录访问来源以及记住刚才访问的链接等。另外,浏 览器发送这个Referer链接时好像固定用UTF-8编码的,所以在GBK下出现乱码,我们在这里纠正一下 */ if (tmpStr.startsWith("Referer")) {//如果有Referer头时,使用UTF-8编码 tmpStr = new String(tmpByteArr, "UTF-8"); } return tmpStr; } }
- java 通过SSL/TLS加密https建立连接
- https 中的SSL/TLS 加密
- 如何通过抓包查看客户端https连接中ssl/tls加密所采用的秘钥位数
- iOS访问https ssl和tls双向加密
- iOS访问https ssl和tls双向加密
- iOS访问https ssl和tls双向加密
- HTTPS加密协议详解(四):TLS/SSL握手过程
- https SSL TLS
- SSL,TLS,HTTPS
- HTTPS详解SSL/TLS
- HTTPS详解SSL/TLS
- Https SSL/TLS详解
- HTTPS详解SSL/TLS
- TLS/SSL 及 HTTPS
- HTTPS/SSL/TLS
- TLS/SSL加密协议
- ssl/tls加密通信
- 解决java连接SQLSERVER数据库之驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:Could not generate DH keypair”。
- Android控件之Fragment
- 九度OJ题目1176:树查找
- 一个跨平台随机数生成函数
- 循环队列以及full/empty条件的判断
- Intellij IDEA maven编译中文乱码
- java 通过SSL/TLS加密https建立连接
- 3.3(1.委托 2.事件 3.字典)
- adb shell 相关,持续更新
- ubuntu16.04 apt-get 速度慢问题
- 第五届蓝桥杯java程序设计 c组决赛试题 年龄巧合
- CJOJ 1217 【HAOI2005】路由选择问题
- Codeforces Round #408 (Div. 2) A.Buying A House【模拟】水题~
- UICollectionView拾遗
- 数据结构课下复习1