1. 理论知识
1.1 什么是https
传统的 HTTP 协议以明文方式进行通信,不提供任何方式的数据加密,很容易被中间攻击者破解通信内容或者伪装成服务器与客户端通信,在安全性上存在很大问题。
HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。
关于非对称加密以及公钥私钥相关知识不在赘述,可自行了解。
PS: TLS 是传输层加密协议,前身是由网景公司1995年发布的 SSL 协议,不过在很多场合还是用 SSL 指代 TLS/SSL。
1.2 https的通信过程
下图来源:菜鸟教程
1、客户端发起 HTTPS 请求
用户访问 https 网址,连接到服务器的 443 端口,请求信息中包含了客户端支持的对称加密算法列表。
2、服务端的配置
支持 HTTPS 协议的服务器必须要有包含自己认证信息和公钥的数字证书以及自己的私钥。
3、下发证书
服务器下发自己的数字证书,这一步其实还包括从客户端支持的对称加密算法列表中选出来用于双向通信的算法,因为非对称加密是一个很耗费资源的过程,所以一般只用来协商之后用于通信的对称加密算法。
当然这一步只是明文协商了对称加密算法的名字,后面会用非对称加密来传输用于对称加密算法的秘钥,由于非对称加密的有效性,这个秘钥是不会被破解的,后续的对称加密传输也就不会被破解。
4、客户端验证证书有效性
客户端验证证书的有效性,如果证书没有问题,那么就生成一个随机值(对称加密秘钥),然后用证书中的公钥对该随机值进行加密。
5、传送用于对称通信的秘钥
用公钥加密的随机值被发送到服务端。
6、服务端解密秘钥
服务端用自己的私钥解密后,得到了客户端传过来的随机值(对称加密秘钥)。
7、双向对称加密通信
接下来就使用之前协商好的对称加密算法以及加密传输的秘钥进行通信即可。
1.3 SSL证书的签发流程
上面的 https 通信过程中,最关键的一步就是客户端如何验证服务端下发证书的有效性,因为下发证书是一个明文传输的过程,证书可能在传输过程中被拦截,被调包,被篡改,那么客户端怎么确定自己收到的就是自己想访问的网站的证书呢?
由于客户端是发起通信的一方,双方没有协商好的加密算法,服务端也不可能持有客户端的公钥信息,所以证书不能被加密发送,那么要解决这个问题就必须引入第三方可信机构(CA),客户端信任它,它就可以对服务器证书做出认证,具体来说就是使用自己的私钥对服务器证书进行签名,签名后的信息包含在证书内,这样客户端只需要持有各个 CA 的公钥,便可以对签名信息进行解密来验证证书的有效性。
上图就是 SSL 证书的签发流程:
-
浏览器需要记住各大CA。浏览器是怎么样记住CA的呢?在浏览器开发的时候,各个CA就把自己的根证书交给了浏览器,那么 CA 根证书中最重要的信息就是该 CA 机构的公钥了,此外还有 CA 机构的标识信息以便匹配服务器证书中声明对它签名的机构。
-
各大网站,如支付宝,将自己的证书交给CA。CA此时需要做的事情是,通过各种法定机构,验证网站的身份。如果CA确定该网站是真的,那么就需要用自己的私钥给网站的证书签名。网站交给 CA 的证书中除了包含自己的 URL 等标识信息外,还必须有网站自己的公钥信息,因为签完名之后证书就不能动了,而后面客户端需要服务器的公钥来加密信息。
-
此处就回到了之前的 https 通信过程,浏览器拿到证书后首先根据该证书的信息,如哪个 CA 对它进行了签名,结合浏览器已有的 CA 的根证书列表,对该证书进行验证,具体来说就是用对应 CA 的公钥对证书中的签名信息进行解密,再与证书信息进行比对,如果验证通过,那么就可以确定这个证书的有效性。
2. 搭建https服务
本机环境:Ubuntu 20.04,openssl 1.1.1h
明白了 https 工作过程后,我们便可以利用开源的安全传输层密码库 openssl 来自建一个实验性的 https 服务。
想一想我们需要什么?
- 一个提供 https 服务的服务器需要有经过 CA 认证的数字证书和自己的公钥私钥(公钥放在证书里)
- CA 认证是需要收费的,所以我们需要自建一个 CA 机构
- 自建的 CA 机构需要有标识自己身份的根证书(包含公钥),以及用来对服务器证书进行签名的私钥
- 一个 https 站点,收到客户端访问时下发自己的数字证书
- 客户端需要持有 CA 的根证书,所