java安全(八)终极装备——HTTPS协议之SSL/TLS协议
来源:互联网 发布:四十部网络禁书名单 编辑:程序博客网 时间:2024/05/14 10:31
SSL/TLS协议我的理解就是客户端(比如浏览器)和服务器端(比如tomcat)商量他们之间数据传输用的对称加密的算法和秘钥,最后用这个算法和秘钥进行数据加密传输。
一、SSL协议的握手过程
“商量”被大牛们升华了就是握手过程.
开始加密通信之前,客户端和服务器首先必须建立连接和交换参数,这个过程叫做握手(handshake)。
假定客户端叫做爱丽丝,服务器叫做鲍勃,整个握手过程可以用下图说明。
握手阶段分成五步(实际的细节比这复杂一点)。
整个握手阶段都不加密(也没法加密),都是明文的。因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。
虽然理论上,只要服务器的公钥足够长(比如2048位),那么Premaster secret可以保证不被破解。但是为了足够安全,我们可以考虑把握手阶段的算法从默认的RSA算法,改为 Diffie-Hellman算法(简称DH算法)。采用DH算法后,Premaster secret不需要传递,双方只要交换各自的参数,就可以算出这个随机数。
(DH算法是非对称加密算法的基础,暂时不准备写关于DH的博文,如需要自行网上学习。)
二、动手操作展示握手过程
我们首先要为服务端生成一个数字证书。Java环境下,数字证书是用keytool生成的,这些证书被存储在store的概念中,就是证书仓库。我们来调用命令为服务端生成数字证书和保存它使用的证书仓库:
我的证书仓库是存放在c:/study/keysotre目录下。
keytool -genkey -v -alias bluedash-ssl-demo-server -keyalg RSA -keystore ./server_ks –dname "CN=localhost,OU=cn,O=cn,L=cn,ST=cn,C=cn" -storepass server -keypass 123123
keytool -genkey -v -alias bluedash-ssl-demo-client -keyalg RSA -keystore ./client_ks –dname "CN=localhost,OU=cn,O=cn,L=cn,ST=cn,C=cn" -storepass client -keypass 456456
keytool -import -trustcacerts -alias bluedash-ssl-demo-server -file ./server_key.cer -keystore ./client_ks
最后生成了如下3个文件:
上面3步目的是 给服务器端生成证书,并把证书安装到客户端信任证书里面。因为是自签名证书,不添加到信任证书里面则不能完成通信。
代码经过测试可以直接运行:
Server端代码:
package ssl;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.ServerSocket;import java.net.Socket;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.UnrecoverableKeyException;import java.security.cert.CertificateException;import javax.net.ServerSocketFactory;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLServerSocket;import org.apache.commons.codec.binary.Base64;public class Server { private static String SERVER_KEY_STORE ="C:/study/keyStore/server_ks"; private static String SERVER_KEY_STORE_PASSWORD ="123123"; public static void main(String args[]) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException { System.setProperty("javax.net.ssl.trustStore", SERVER_KEY_STORE); SSLContext context = SSLContext.getInstance("TLS"); KeyStore ks = KeyStore.getInstance("jceks"); ks.load(new FileInputStream(SERVER_KEY_STORE), null); KeyManagerFactory kf = KeyManagerFactory.getInstance("SunX509"); kf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray()); //打印出私钥 System.out.println(Base64.encodeBase64String(ks.getKey("bluedash-ssl-demo-server", "123123".toCharArray()).getEncoded())); context.init(kf.getKeyManagers(), null, null); ServerSocketFactory factory = context.getServerSocketFactory(); int port = 8899; ServerSocket server = factory.createServerSocket(port); //为了简单起见,所有的异常信息都往外抛 ((SSLServerSocket) server).setNeedClientAuth(false); //定义一个ServerSocket监听在端口8899上 //ServerSocket server = new ServerSocket(port); while (true) { //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的 Socket socket = server.accept(); //每接收到一个Socket就建立一个新的线程来处理它 new Thread(new Task(socket)).start(); } } /** * 用来处理Socket请求的 */ static class Task implements Runnable { private Socket socket; public Task(Socket socket) { this.socket = socket; } public void run() { try { handleSocket(); } catch (Exception e) { e.printStackTrace(); } } /** * 跟客户端Socket进行通信 * @throws Exception */ private void handleSocket() throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); StringBuilder sb = new StringBuilder(); String temp; int index; while ((temp=br.readLine()) != null) { //System.out.println(temp); if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收 sb.append(temp.substring(0, index)); break; } sb.append(temp); } System.out.println("from client: " + sb); //读完后写一句 Writer writer = new OutputStreamWriter(socket.getOutputStream()); writer.write("Hello Client."); writer.write("eof\n"); writer.flush(); writer.close(); br.close(); socket.close(); } }}
Client端:
package ssl;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.Socket;import java.util.Date;import javax.net.SocketFactory;import javax.net.ssl.SSLSocketFactory;public class Client { private static String CLIENT_KEY_STORE = "C:/study/keyStore/client_ks"; public static void main(String args[]) throws Exception { System.setProperty("javax.net.ssl.trustStore", CLIENT_KEY_STORE); System.setProperty("javax.net.debug", "ssl,handshake"); SocketFactory sf = SSLSocketFactory.getDefault(); Socket client = sf.createSocket("localhost", 8899); /* * //为了简单起见,所有的异常都直接往外抛 String host = "localhost"; //要连接的服务端IP地址 int * port = 8899; //要连接的服务端对应的监听端口 //与服务端建立连接 Socket client = new * Socket(host, port); */ // 建立连接后就可以往服务端写数据了 Writer writer = new OutputStreamWriter(client.getOutputStream()); writer.write("Hello Server."); writer.write("eof\n"); writer.flush(); // 写完以后进行读操作 System.out.println(new Date()); BufferedReader br = new BufferedReader(new InputStreamReader( client.getInputStream())); StringBuffer sb = new StringBuffer(); String temp; int index; while ((temp = br.readLine()) != null) { if ((index = temp.indexOf("eof")) != -1) { sb.append(temp.substring(0, index)); break; } sb.append(temp); } System.out.println(new Date()); System.out.println("from server: " + sb); writer.close(); br.close(); client.close(); }}
结果(部分截图):
第一次Client向服务器握手 发出它支持的加密算法 随机数等等
服务器接到请求 选择加密算法 并返回一个随机数等
参考:
1.http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
2.http://blog.csdn.net/cuishi0/article/details/6805179
3.http://blog.chinaunix.net/uid-17102734-id-2830223.html
- java安全(八)终极装备——HTTPS协议之SSL/TLS协议
- java安全(七)终极装备——HTTPS协议之HTTP协议
- 图解SSL/TLS协议(HTTPS的安全层)
- HTTPS系列之SSL/TLS协议
- HTTPS之SSL/TLS协议分析
- Http协议之Https&SSL/TLS&DNS
- Java SSL/TLS 安全通讯协议介绍
- Java SSL/TLS 安全通讯协议(SSLSocket)
- Java SSL/TLS 安全通讯协议介绍
- Java SSL/TLS 安全通讯协议介绍
- Java SSL/TLS 安全通讯协议介绍
- Java SSL/TLS 安全通讯协议介绍
- Http——HTTPS和SSL/TLS协议
- 深入浅出https协议(ssl/tls)
- HTTPS和SSL/TLS协议
- HTTPS和SSL/TLS协议
- HTTPS协议和SSL/TLS协议
- 传输层安全协议抓包分析之SSL/TLS
- js事件对象Event获取pageX,clientX,screenX,offsetX,layerX的方式与区别
- [linux]ln命令
- linux命令:ps命令
- LintCode:两两交换链表中的节点
- USB设备驱动程序-USB Gadget Driver(四)
- java安全(八)终极装备——HTTPS协议之SSL/TLS协议
- Spring Security(10)——退出登录logout
- Python的安装方法
- 移位指令
- php判断键值在数组中是否存在
- Android四大组件之BroadcastReceiver
- 51nod 1191(贪心+优先队列)
- 截取字符串
- 高效率去掉js数组中重复项