https原理及实践

2,345 阅读11分钟

网站的证书快要过期了,索性就总结下 HTTPS 相关的东西吧。

前提

HTTPS 说白了就是加密传输信息,防止信息泄露,需要提前了解几个概念:

加密

先说说最简单的加密,替换法,每个字符都对应到一个新的字符:

image-20230116081932963

比如明文是 windliang ,通过上边的映射关系密文就是 pbgwebtgz

古代就使用过这种加密算法,但通过词频的分析,暴力枚举很容易被破解,因此现代已经不会用这种算法了。

不管什么加密算法,都可以分为明文,密文,和密钥、算法三部分。

image-20230116083309471

这里的密钥就可以理解为上边的映射表,算法就是直接映射。

现代的加密算法,密钥一般就是一个字符串,算法就比较复杂了,会进行各种计算,或操作、与操作,分组等,然后再应用各种数学知识,质数、模相等... ,大学的时候有学过,这里也忘光了,下边只介绍简单概念了。

对称加密

和古代的加密算法流程是一样的

image-20230116083309471

只是其中的算法相对于简单的替换会更加复杂。常用的有 DES 算法、AES 算法、3DES 算法、TDEA 算法、Blowfish 算法、RC5 算法、IDEA 算法等。其特点是,加密和解密使用同一密钥

非对称加密

与之前最大的不同之处是包含了两个密钥,一个称之为公钥,一个称之为私钥。并且算法相对于对称加密会更加复杂。

image-20230116220615109

公钥和私钥都能进行加密,用公钥加密后只能用私钥解密,用私钥加密后只能用公钥解密。

常见非对称加密算法包括 DSA 算法、RSA 算法、Elgamal 算法、背包算法、Rabin 算法、D-H 算法、ECC 算法等。由于算法非常复杂,因此非对称加解密会非常耗时

哈希算法

可以看做一种特殊的加密。

image-20230116221214098

它是单向的,加密后无法再还原。可以将任意长度的明文串映射为较短的(通常是固定长度的)二进制串(Hash 值),并且不同的明文很难映射为相同的 Hash 值。

目前常见的 Hash 算法包括国际上的 Message Digest(MD)系列和 Secure Hash Algorithm(SHA)系列算法,以及国内的 SM3 算法。

利用这个特性,我们就可以快速比对文本是否被篡改,将明文和 hash 值一起传输给对方,收到后将明文重新生成 Hash 值,再和收到的 Hash 值比对,如果 Hash 值不同就说明被篡改过了。

传纸条

假设教室中第一排的小明想给最后一排的小红传纸条。

直接传

第一种最简单的方法就是想传啥直接写到纸上,然后叠起来,让教室中间的人帮助传递过去即可。

但存在一个最大的问题,不安全,中间的某一个同学如果突发好奇,直接拆开纸条,内容就一览无余了。

对称加密

小明想了想那我和小红约定一个对称加密算法吧,我先把密钥写到纸上传给小红,之后我都加密后写到纸上传给小红,这样就安全了吧。

中间传纸条的小刚突发好奇,拆开了纸条但这次好奇心没有得到满足,发现纸上写的由于加密过了已经完全看不懂了。

但小华拆开纸条却突然笑出了声,因为他读懂了纸条内容,在小明第一次传写有密钥的纸条的时候小华就已经拆开并且偷偷记下来了。所以后续的传递,只要小华想看,拆开以后通过密钥解密一下就可以了。

非对称加密

小明和小红想这可不行啊,于是两个人说干脆我们用非对称加密吧,我们的纸条内容都用对方的公钥加密,拿到纸条后用自己的私钥进行解密。这样纸条被别人看到也无所谓了,因为私钥只有我们自己有。

于是第一次传纸条的时候,小明把自己的公钥写好传给了小红,小红以后拿着这个公钥加密后再写到纸条上。小红也把自己的公钥写好传给了小明,小明以后拿着这个公钥加密后再写到纸条上。

小明收到小红写的纸条内容后,因为纸条是用小明的公钥加密过的,小明只需要用自己的私钥解密一下即可正常阅读了。

小红也是同样的道理。

小华在小红和小明第一次传纸条的时候同样又把两个公钥记了下来,但后续小红和小明的聊天小华却没办法解密了,因为纸条内容都是经过公钥加密的,如果想要解密必须通过私钥,但私钥在小红和小明各自的手里,其他人都无能为力了。

但小刚此时却偷偷笑出了声,因为第一次用纸条传公钥的时候,小刚偷偷动了手脚。

小明将公钥传给小红的时候,小刚偷偷将纸条换成了写有自己公钥的纸条,因此小红拿到的是小刚的公钥。

小红传公钥给小明的时候,小刚同样的将小红的公钥换成了自己的,因此小明拿到的是小刚的公钥。

当小明用收到的公钥加密后传递到小刚这里的时候,小刚就用自己的私钥进行了解密,然后用小红的公钥进行了加密发给了小红。小红和小明以为在安全的通信,其实被小刚一览无余了。

签名证书

此时小红和小明遇到的问题就是无法确认收到的公钥是否是对方的。

小亮此时站出说,我来把证书内容用我的私钥签名,公钥我直接写到黑板上,具体过程如下:

证书上写好你们自己的名字和你们的公钥,我会把证书上的内容做一次 Hash,然后把这个 Hash 用我的私钥加密,将加密后的内容也放到证书上。

现在证书上有你们的名字和你们的公钥,外加一个加密后的 Hash 值。

你们拿到别人的证书后,先看下名字是不是你们要的人,然后计算一下证书上的内容得到 Hash 值,再用黑板上的公钥把证书上加密的 Hash 值进行解密,看一下这两个值是否相同,如果相同的话就证明证书没有被篡改过,证书上的公钥可以放心使用。

image-20230120181352297

证书链

自从有了证书,小刚拿到小明传给小红的证书后就无能为力了。

第一不能修改证书上的任何内容,一修改就会导致最终的 Hash 值不一样,就会被别人发现造假。

第二他也不能把证书替换成自己的,因为证书写了自己的名字,证书传过去以后小红一看这是小刚的证书那直接暴露。

班上的同学发现这也太棒了 ,再也不会有人读到纸条内容了,但小亮就变的太忙了,越来越多的人跟他要证书。小亮想要不我给小杨发个证书,以后让小杨给别人发证书。

于是后边的人就找小杨发证书,这样传递纸条的时候,除了自己的证书,也要把小杨的证书写上。收到的人用小杨的证书上的公钥来验证收到的证书是不是真的,而小杨的证书用黑板上的写的小亮的公钥来验证是否是真的。

未来小杨也觉得太忙了,她可能也授权某个人也能给别人发证书,这样第一次传递纸条的时候就需要把整个链条上的证书都写上,依次确认真假,但最后一次证书一定使用黑板上的公钥来确认,因为这个是大家都能看见的,一定不会是假的。

非对称加密结合对称加密

课堂上大家传纸条一段时间后发现过程中用非对称算法加密解密实在是太费时间了,本来原文写了 10 个字,加密加密可能得用一小时,虽然安全但太麻烦了。

于是小明对小红说:我们是不是能结合下对称加密算法。当我收到你的证书后,并且验证证书是可信的,我就生成一个对称加密的密钥,用证书上你的公钥加密后写到纸条上传给你。你收到后用自己的私钥解密,拿到对称加密算法的密钥后,以后写纸条都通过对称加密进行加密传给我。这样就既保证了传输的安全性,也节省了加解密的时间。

即使中间有人拿到了加密后的密钥,因为没有你的私钥,他也无能为力。

小红:赞!就这样搞。

HTTPS 实际情况

关于证书

image-20230120173638956

实际证书会包含更多的东西,域名信息,有效期,以及之前说的签名等等。

image-20230120173744353

以及上边的图里的证书链,会通过证书上公钥依次验证证书的有效性。而根证书就相当于黑板上写的公钥,这个会提前内置到系统中,如下图所示,是系统中所有的根证书。

image-20230120174128365

浏览器确认当前域名和证书上的域名一致,并且证书是有效的,就会有一个通过的锁,否则会有一个危险提示。

image-20230120174301762

关于对称加密的密钥

实际过程中对称加密算法的密钥会通过多次传输最终拼接出一个密钥,过程可以参考 SSL / TLS 工作原理和详细握手过程

image-20230120183519392

对称加密的密钥由 client randomserver randompremaster secret 三部分结合后生成。

实践

以阿里云为例,记录下整个过程:

打开阿里云的 证书网站,点击创建证书:

image-20230115204319376

每年免费 20 个额度:

image-20230115204518817

点击立即购买,并且完成后续的支付流程。

image-20230115204632274

购买结束后,回到控制台,点击「创建证书」,会在页面中多了一条待申请的证书,接着点击证书申请:

image-20230115205205575

填写自己的域名,然后点击「提交审核」。

image-20230115205413799

如果是阿里云的域名,DNS 记录里会自动加一条下边的 TXT 记录。

image-20230115205938916

可以到自己的 DNS 解析控制台看一眼:

image-20230115210039243

接着只需要等邮箱通知就可以:

image-20230115210232162

刷新一下列表,证书就变为了已签发:

image-20230115210337924

点击右边的下载,会弹出页面选择证书类型,这里我下载 nginx 的:

image-20230115210510184

下来好的两个文件,.pem 就是我们的证书,.key 是我们的私钥。

image-20230115210823709

接下来登录自己的服务器,前提是你已经按照 搭建网站 这个教程配置好了网站。

我们可以先把上边的两个文件重命名,并且通过任意的方式上传到自己的服务器,我是用 FTP 传上去。

接着通过 ssh 登录自己的服务器,ssh -p22 root@你的服务器 ip,将刚传上来的服务器证书和密钥移动到 nginx 的相应位置:

mv -f /var/ftp/pub/windliang.pem /etc/nginx/cert/
mv -f /var/ftp/pub/windliang.key /etc/nginx/cert/

/var/ftp/pub/windliang.pem/var/ftp/pub/windliang.key 需要改成你自己的文件地址。

还需要在网站的 nginx 的配置文件中加入 https 的配置,监听 443 端口:

server {
        listen 443 ssl;   #SSL协议访问端口号为443。此处如未添加ssl,可能会造成Nginx无法启动。
        server_name windliang.wang;  #将localhost修改为您证书绑定的域名,例如:www.example.com。
        root html;
        index index.html index.htm;
        ssl_certificate cert/windliang.pem;   #替换成您证书的文件名。
        ssl_certificate_key cert/windliang.key;   #替换成您证书的密钥文件名。
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;  #使用此加密套>
件。
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   #使用该协议进行配置。
        ssl_prefer_server_ciphers on;
        location / {
                root /root/myblog;   #站点目录。
                index index.html index.htm;
        }
}
server {
    listen 80;
    server_name www.windliang.wang;
    return 301 $scheme://windliang.wang$request_uri;
}

接下来重启 nginx

nginx -s reload

此时重新打开网站证书就设置成功了:

image-20230116063503733