1、https介绍
1.1 https是什么?
https不是一种新的协议,它是http+SSL(TLS)的结合体,SSL是一种独立协议,所有其它协议比如smtp等也可以跟ssl结合。https改变了通信方式,它由以前的http—–>tcp,改为http——>SSL—–>tcp;https采用了共享密钥加密+公开密钥加密的方式。
1.2 为什么使用?
1.2.1 http通信存在的问题
(1)容易被监听。http通信都是明文,数据在客户端与服务器通信过程中,任何一点都可能被劫持。比如,发送了银行卡号和密码,hacker劫取到数据,就能看到卡号和密码,这是很危险的
(2)被伪装。http通信时,无法保证通行双方是合法的,通信方可能是伪装的。比如你请求www.taobao.com,你怎么知道返回的数据就是来自淘宝,中间人可能返回数据伪装成淘宝。
(3)被篡改。hacker中间篡改数据后,接收方并不知道数据已经被更改。
1.2.2 https很好的解决了http的三个缺点(被监听、被篡改、被伪装)。
(1)防监听。数据是加密的,所以监听得到的数据是密文,hacker看不懂。
(2)防伪装。伪装分为客户端伪装和服务器伪装,通信双方携带证书,证书相当于身份证,有证书就认为合法,没有证书就认为非法,证书由第三方颁布,很难伪造
(3)防篡改。https对数据做了摘要,篡改数据会被感知到。hacker即使从中改了数据也白搭。
1.3 https连接过程
1)服务器端需要认证
1、客户端发送请求到服务器端
2、服务器端返回证书和公开密钥,公开密钥作为证书的一部分而存在
3、客户端验证证书和公开密钥的有效性,如果有效,则生成共享密钥并使用公开密钥加密发送到服务器端
4、服务器端使用私有密钥解密数据,并使用收到的共享密钥加密数据,发送到客户端
5、客户端使用共享密钥解密数据
6、SSL加密建立………
2)客户端需要认证
客户端需要认证的过程跟服务器端需要认证的过程基本相同,并且少了最开始的两步。这种情况都是证书存储在客户端,并且应用场景比较少,一般金融才使用,比如支付宝、银行客户端都需要安装证书
1.4 https详细的流程
- 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。 - 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。 - 传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。 - 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。 - 传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。 - 服务段解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。 - 传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。 - 客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
2 CA证书
2.1 什么是CA证书
CA(Certificate Authority),CA 证书,顾名思义,就是CA颁发的证书。证书=公钥+申请者与颁发者信息+签名。
2.2 签发过程
a.服务方 S 向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证;
b.CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
c.如信息审核通过,CA 会向申请者签发认证文件-证书。
证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名;
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名;
d.客户端 C 向服务器 S 发出请求时,S 返回证书文件;
e.客户端 C 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;
f.客户端然后验证证书相关的域名信息、有效时间等信息;
g.客户端会内置信任 CA 的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA 的证书,证书也会被判定非法。
2.3 注意点位
1.申请证书不需要提供私钥,确保私钥永远只能服务器掌握;
2.证书的合法性仍然依赖于非对称加密算法,证书主要是增加了服务器信息以及签名;
3.内置 CA 对应的证书称为根证书,颁发者和使用者相同,自己为自己签名,即自签名证书;
2.4 CA证书制作
(1) CA机构申请(一般用于生产)
(2) 通过工具openssl、keystore生成(一般用于测试)
3 Keystore的介绍
3.1 keystore的使用
keytool是JDK自带的密钥和证书管理工具。使用keytool可以生成密钥库(keystore),密钥库中的条目类型只有两种:密钥项和可信任的证书项!
创建证书和密钥库的命令:
keytool -genkeypair -alias "coco" -keypass 123456 -keyalg "RSA" -keystore "d:\coco.keystore" -storepass 123456 -dname "CN=www.****.com, OU=anything, O=anything, L=anything, ST=anything, C=anything"
-genkeypair:
-alias:表示别名,唯一,不区分大小写。
-keypass:访问密钥库中某个条目的密码。
-keyalg:表示加密算法
-keystore:表示密钥库文件生成路径
-storepass:表示密钥库访问密码
-dname:表示证书的信息,其中CN表示项目的域名
3.2 其它命令
1、产生密钥对
keytool -genkey -alias mykeypair -keypass mykeypairpwd
2、将密钥对存放在指定的keystore中
keytool -genkey -alias mykeypair -keypass mykeypairpwd -keystore mykeystore
3、 查看keystore的内容
keytool -list -v -alias mykeypair -keystore mykeystore
4、将证书导出至证书文件
keytool -export -alias myCA -file myCA.cer -keystore myCALib -storepass 123456 -rfc
5、通过证书查看证书信息
keytool -printcert -file myCA.cer
6、把证书文件导入到指定的密钥库
keytool -import -alias myCA -file myCA.cer -keystore truststore
7、更改密钥库的密码
keytool -storepasswd -new 123456 -storepass 789012 -keystore truststore
4 SSLSocket
4.1 什么是SSLSocket?
JDK文档指出,SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字。这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了安全保护层。
4.2 SSLSocket和相关类
(1)SSLContext: 此类的实例表示安全套接字协议的实现, 它是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工厂。
(2)SSLSocket: 扩展自Socket
(3)SSLServerSocket: 扩展自ServerSocket
(4)SSLSocketFactory: 抽象类,扩展自SocketFactory, SSLSocket的工厂
(5)SSLServerSocketFactory: 抽象类,扩展自ServerSocketFactory, SSLServerSocket的工厂
(6)KeyStore: 表示密钥和证书的存储设施
(7)KeyManager: 接口,JSSE密钥管理器
(8)TrustManager: 接口,信任管理器(?翻译得很拗口)
(9)X590TrustedManager: TrustManager的子接口,管理X509证书,验证远程安全套接字
4.3 SSLContext的使用
public static void main(String[] args) {
try {
X509TrustManager x509m = new X509TrustManager() {
//返回受信任的X509证书数组
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
//该方法检查服务器的证书,若不信任该证书同样抛出异常
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
//该方法检查客户端的证书,若不信任该证书则抛出异常
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
};
// 获取一个SSLContext实例
SSLContext s = SSLContext.getInstance("SSL");
// 初始化SSLContext实例
s.init(null, new TrustManager[]{x509m},
new java.security.SecureRandom());
}catch (Exception e){
e.printStackTrace();
}
}
5 实例
5.1 生成CA证书、.keystore文件(或者.jks文件)
执行命令:
keytool -genkeypair -alias "test" -keypass 123456 -keyalg "RSA" -keystore "d:\test.keystore" -storepass 123456 -dname "CN=www.test.com, OU=anything, O=anything, L=anything, ST=anything, C=anything"
keytool -export -alias "test" -file "d:\test.cer" -keystore "d:\test.keystore" -storepass 123456 -rfc
结果如下:
5.2 客户端导入CA根证书至受信任的根证书颁发机构
双击证书–安装证书–下一步–选择“将所有的证书都放入下列存储”–选择受信任的根证书颁发机构–确定–下一步–完成
5.3 客户端修改host文件,增加ip与域名映射
打开文件目录C:\Windows\System32\drivers\etc\host,增加配置
5.4 服务端代码SSLServerSocket
public static void main(String[] arg){
try{
// key store相关信息
String keyName = "d:\\test.keystore";//密钥库
char[] keyPwd = "123456".toCharArray();//密钥库访问密码
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
// 装载当前目录下的key store. 可用jdk中的keytool工具生成keystore
InputStream in = null;
keyStore.load(in = new FileInputStream(keyName), keyPwd);
in.close();
// 初始化key manager factory
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyPwd);
// 初始化ssl context
SSLContext context = SSLContext.getInstance("SSL");
context.init(kmf.getKeyManagers(), new TrustManager[] { new MyX509TrustManager()}, new SecureRandom());
// 监听和接收客户端连接
SSLServerSocketFactory factory = context.getServerSocketFactory();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(443);
System.out.println("服务端侦听开始...");
Socket client = server.accept();
System.out.println("收到客户端请求:"+client.getRemoteSocketAddress());
// 向客户端发送接收到的字节序列
OutputStream output = client.getOutputStream();
InputStream input = client.getInputStream();
byte[] buf = new byte[1024];
int len = input.read(buf);
System.out.println(new String(buf, 0, len));
output.write(buf, 0, len);
output.flush();
}catch (Exception e){
e.printStackTrace();
}
}
5.5 客户端代码SSLSocket
public static void main(String[] arg){
try{
SSLContext context = SSLContext.getInstance("SSL");
// 初始化
context.init(null,new TrustManager[]{ new MyX509TrustManager() },new SecureRandom());
SSLSocketFactory factory = context.getSocketFactory();
SSLSocket s = (SSLSocket) factory.createSocket("www.test.com",443);
OutputStream output = s.getOutputStream();
InputStream input = s.getInputStream();
//请求内容
String sbd="hello world";
output.write(sbd.getBytes());
output.flush();
byte[] buf = new byte[1024];
int len = input.read(buf);
System.out.println("响应内容:" + new String(buf, 0, len));
}catch (Exception e){
e.printStackTrace();
}
}
5.6 运行服务端,开启侦听
服务端侦听开始...
5.7 运行客户端,发起请求;服务端接收请求
收到客户端请求:/127.0.0.1:63280
5.8 服务端处理请求;返回结果至客户端
响应内容:hello world
5.9 客户端接到响应,交互完成。
6 参考链接
6.1 CA证书介绍、https介绍、keystore介绍
https://www.cnblogs.com/handsomeBoys/p/6556336.html
https://www.cnblogs.com/xdouby/p/9035198.html
https://blog.csdn.net/liuquan0071/article/details/50318405
6.2 SSLSocket的使用
https://blog.csdn.net/a351945755/article/details/22788855
6.3 证书+私钥合成密钥库
https://blog.csdn.net/hfismyangel/article/details/83792992
6.4 SSL双向认证实例
https://www.cnblogs.com/franson-2016/p/5557259.html