欢迎来到无限飞翔,在这里,你会找到许多有趣的技术 : )

从对称加密到非对称加密再到认证中心:https 的证书申请

开发者头条 56℃ 0评论

作者 | 马启航

杏仁后端工程师。「我头发还多,你们呢?」

前言

本来觉得也就是一个普通的博客网站,用不用 HTTPS 似乎也没什么大不了。但是在网络上各种信息的狂轰乱炸下,还是决定把这个问题解决一下。在这件事之前笔者还遇到了一个很恶心的问题,那就是我被勒索了。事情是这样的,某一个美好的周六的上午,突然收到一封来自俄罗斯的邮件,这就让我很疑惑了,怎么会有老毛子发邮件给我?带着疑惑打开邮件,右键大致内容是说他已经完全控制了我的设备(不过我并没有发现任何设备的异常),要我转 2000 刀到他的比特币账户上面,否则就巴拉巴拉。好吧,对于我这种穷人来说,别说 2000 刀,200 刀我都出不起,所以就忽略掉了,令人欣慰的是到最后似乎也没有怎么样,我的各种设备也都还是正常的,但是这个事也让我深切的体会到信息安全的重要性。

那么废话不多说,进入正题~

对称加密 vs 非对称加密

先来看两个基础的概念,这是本文的基础,希望读者仔细看一下这一块。

  • 对称加密
    对称加密 (https://zh.m.wikipedia.org/zh-hans/對稱密鑰加密) 就是通讯双方持有相同的密钥(和加密方式),然后 A 方通过密钥将明文进行加密得到密文,B 端使用相同的密钥将密文进行解密,得到明文。

优点:对称加密的优点是加密速度非常快;

缺点:由于通讯双方需要使用相同的密钥进行通讯,那么在通讯之前通讯双方需要约定密钥,在互联网中,双方是不认识的,如何安全的约定密钥是一个很难解决的问题。并且在约定密钥的过程中密钥一旦被泄露,那么之后通讯中的信息就可能会被别人获取。

所以说,如何安全的约定密钥是对称加密的一个关键点。

  • 非对称加密非对称加密 (https://zh.wikipedia.org/wiki/公开密钥加密) 是需要生成一对密钥,分别叫做公钥和私钥。顾名思义,私钥自己拥有,而公钥是公开的。特点:
  • 使用公钥加密的密文只有对应的私钥才能解密(就连公钥子集也无法解密自己加密的信息);
  • 相反的,使用私钥加密的信息,也只有对应的公钥才能解密(同样的,私钥也不能解密自己加密的信息)。

从上面的公式可以看到这里和对称加密有所区别了。对称加密是只有拥有密钥,明文可以变成密文,密文也可以变成明文。而非对称加密是明文通过公钥加密之后只有私钥可以解密,通过私钥加密只能通过公钥进行解密。

使用公钥加密的密文只有对应的私钥才能解密(就连公钥自己也无法解密自己加密的信息);

相反的,使用私钥加密的信息,也只有对应的公钥才能解密(同样的,私钥也不能解密自己加密的信息)。

我们先看左边这个公式,明文使用公钥进行加密,然后只能使用私钥解密,这有什么用呢?试想一下,如果我把我的公钥给别人,然后让别人用公钥加密信息发送给我,由于只有我自己拥有私钥,所以这个信息是完全安全的。而对比对称加密,我要把对称加密的密钥给别人,然后让别人使用这个密钥加密信息然后发送给我,看起来也蛮安全的。

这两者都要把密码给别人,但是区别就是,如果使用非对称加密时,我完全不担心在给别人公钥时被暴露公钥,因为即使有其他人获取到了我的公钥,也没什么用但是如果是对称加密的密钥就不行了,完全不能暴露。

这就说明了一个问题:使用公钥加密的的信息只有私钥能够解密,而私钥只有密钥对的拥有者才拥有,也就意味着只有密钥对的拥有者才能解密使用公钥加密的信息

我们再看一下第二个公式,明文使用私钥进行加密,然后只能用公钥解密。这下读者可能就疑惑了,诶,那不出大事了吗?上面不是说公钥是公开的吗,那你使用私钥加密的内容不是人人可见?

诶,对了,这就对了。因为用私钥加密信息不是为了信息保密,只是为了证明身份

试想一下,如果我用私钥加密,然后别人拿着我的公钥进行解密,哎哟,竟然解开了,那说明什么?你想啊,既然能够用我的公钥解密,那是不是意味着这个信息是我的私钥进行加密的?那谁拥有我的私钥呢?当然是我本人了。那是不是就说明了,这个信息是来自于我?因为别人没有我的私钥,所以别人无法伪造。

这又说明了一个问题:如果使用公钥能够解密私钥加密后信息(这里公钥私钥是配对的),那就意味着这个信息确实是密钥对拥有者发送的信息

读到这儿不知道读者有没有觉得这个算法很厉害,反正笔者是觉得算法的发明者真的是个天才。那你说这个算法这么厉害,就没有缺点吗?有利就有弊,非对称加密算法相比对称加密来说速度非常慢,而且特别消耗 cpu,所以说,非对称加密虽然好,但是不可以滥用。说到这个滥用,我就不得不吐槽一下,最近对接的一个第三发,让他们出文档,加密算法用的就是 RSA,我的天,一次请求光数据加密都要 0.5s,Unbelievable…

这么厉害的算法,原理是啥呢?笔者才疏学浅就不再继续展开讨论了,感兴趣的小伙伴可以看一下

阮一峰

(http://http//www.ruanyifeng.com)

老师写的RSA算法原理(一)

(http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html) 和RSA算法原理(二) (http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html)

这两篇文章,写的很详细。

那么我们简单的进行一下总结,敲黑板,划重点了!

总结一下非对称加密的作用:

1.使用公钥加密只有私钥才能解密,可以用来信息加密安全传输。

2.使用私钥加密只有公钥才能解密,可以用来身份认证。只要你能确定这个公钥是我的公钥,那么不管这个信息来自于哪里,只要能解密,就意味着是我发出的。

    • 对比

通过上面的介绍,可以发现:1、对称加密,速度快,但是安全性不够高,如果能解决公钥的安全性,那就完美了。2、非对称加密,安全性非常高,但是性能较差,不适合大规模使用

所以有以下思路,那就是先使用非对称加密来传递用于对称加密的公钥,然后后续全部使用对称加密进行通讯,这样就不仅能够保证足够的安全性,同时加密的开销也会不会很大。

使用密文进行传输

HTTP 协议是明文传输,容易被偷看和篡改,而 HTTPS 使用加密传输,所以更加安全。

HTTPS 是 HTTP 协议再加上一层 SSL/TSL 安全协议来保证安全的,除了安全,HTTPS 协议的网站也能够提升在搜索引擎中的排名(SEO),简单来说就是更容易在搜索引擎搜到你的网站的内容。

使用 HTTP 协议进行通讯是用的明文,容易被偷看和篡改,所以不安全,那么不使用明文不就解决问题了吗?

根据前面提到的对称加密,我们可以使用对称加密对通讯内容进行加密,然后服务端用相同的密钥进行解密。这个方案的痛点就在于,在互联网中,通讯双方如何安全的传递公钥呢?

可以先使用非对称加密对公钥进行传递,然后后续双方使用公钥进行通讯。这个思路很不错,而且非常安全。我们模拟一下现在的通讯流程:

用户 A 请求服务 B,服务端 B 发送自己的公钥 pub_key 给 A,A 生成密钥key 并使用 pub_key 进行加密然后发送给服务端 B,服务端使用private_key 进行解密拿到密钥 key,然后后续使用该密钥进行通讯。

这个流程也是有问题的,问题就在于,在服务端发送自己公钥给 A 的时候,如果此时 C 进行了拦截,并且将自己的公钥给到了 A,而 A 以为这个就是 B 的公钥,那么后续通讯过程实际上就是 A 与 C 进行通讯,A 的隐私信息全部都暴露给了 C。

看一下上面被拦截的流程,关键点在于,A 收到 C 的公钥之后误以为是 B 的,才会发生后面泄露隐私的问题。所以,如果能够让 A 识别服务端的公钥,那么这个问题就可以被解决。那么接下来,认证中心就登场了。

认证中心

在现实生活中,你去火车站买票,或者去银行办理一些业务,经常遇到一件事,那就是请出示身份证。诶,为什么非要身份证呢?因为身份证能证明你的身份。诶,既然身份证就能证明我的身份,那我自己写一张假的身份证,那我不就换身份了么?那肯定不行,因为身份证是具有公信力权威机构(比如说公安局)颁发的,是无法伪造(理想状态下,即使伪造也会被识别,所以不要杠这个问题)的。

那么以上关键点,具有公信力的权威机构无法伪造。那么相同的道理,如果找个权威的机构,然后为这个公钥颁发一个其他人无法伪造证书,上面就标明了,这个公钥确实隶属于 xxx 服务端,那么当客户端拿到这个公钥和证书的时候,不就可以确定这个公钥确实属于我要访问的服务器了么,那么后续就可以安全又愉快的通讯了。

CA (https://zh.wikipedia.org/wiki/证书颁发机构) 是 Certificate Authority,即证书颁发机构,也称为电子商务认证中心、电子商务认证授权机构,是负责发放和管理数组证书的权威机构,并作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任。

认证中心比较好解决,具有公信力的权威机构都可以,但是如何做到无法伪造呢?如果能够轻易伪造,那么上诉仍然不成立。

回头看一下,我们前面说非对称加密作用时候的总结:

使用私钥加密只有公钥才能解密,可以用来身份认证。只要你能确定这个公钥是我的公钥,那么不管这个信息来自于哪里,只要能解密,就意味着是我发出的。

诶,非对称加密可以用作身份认证,那这里认证中心(CA)需要的就是身份认证,CA 需要告诉客户端,这个证书就是他颁发的。

所以流程就是这样,CA 使用私钥对证书进行加密,然后颁发给服务端,服务端在下次通讯的时候就会把自己的公钥和证书一并下发给客户端,诶,你看这个公钥就是我的,证书在此,别人无法伪造,放心用吧。那么客户端使用 CA 的公钥对证书进行解密,如果可以解密并且证书信息正确,那么就说明一切正常,然后客户端继续上面我们说的流程进行通讯。perfect~~

这里可能有人又会提疑问了,诶,那客户端怎么对证书进行解密呢?那不得先知道 CA 的公钥么?那我获取 CA 的公钥的时候怎么确定这个公钥不是伪造的呢?这个其实不用担心,因为在操作系统,甚至某些浏览器中就已经保存了受信任的 CA 的信息。我们可以简单理解为 CA 的公钥,其实是有顶级认证中心的,也就是认证中心要去顶级认证中心去进行认证,然后认证中心也会有证书,这些证书预装在操作系统里面,所以给自己电脑装证书的时候务必谨慎,否则坑的是自己。

那么到这里,整个流程就都是安全的了。接下来,我们看一看如何为自己的网站申请证书。

证书的申请

目前 CA 有很多,但是大都收费,感兴趣的自己百度就行。

本文只提一种解决方案 Let’s Encrypt,免费的,真香。

Let’s Encrypt 是一个于2015年三季度推出的数字证书认证机构,旨在以自动化流程消除手动创建和安装证书的复杂流程,并推广使万维网服务器的加密连接无所不在,为安全网站提供免费的SSL/TLS证书。

这玩意最厉害的地方在于,它不仅免费,还提供了超级简单的自动化工具 Certbot  (https://certbot.eff.org/),小白用户不用这个简直天理难容。

Certbot 官网提供了教程教你一步一步怎么做,一般用 Nginx 或者 Apache 服务器的小伙伴直接对着教程就能轻松搞定,因为这个工具有一种模式叫做 “Standalone”,可以检测到你的服务器,然后给你服务器进行一些配置,全自动完成。或者你也可以选择 “Webroot”模式,自己配置。

Let’s Encrypt 现在的版本已经支持通配符域名证书的发放,简单来说就是你的所有二级域名都可以通过一张证书来完成认证。不过笔者没那个需求,所以本文只申请了单个域名的证书。

  • 最简单的方式安装(以 Nginx 为例)1. 安装 Certbot 插件
# 如果是 Ubuntu,换 apt-get 即可,root 用户可以不加 sudo
sudo yum update
sudo yum install certbot python-certbot-nginx

2.安装证书

sudo certbot --nginx

这个命令执行之后,certbot 会自动检测你的服务器配置文件,然后让你选择要开启的站点,选择之后,certbot 会下载证书并且为你更新配置文件的配置。

3.重启服务器

nginx -s reload
  • Webroot 模式(官方称为插件)的大致步骤
    1.安装 Certbo
  • sudo yum update
    sudo yum install certbot python-certbot-nginx

    2.修改配置文件,在 server 模块增加以下内容

    location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root     /usr/share/nginx/html;
    }
    
    location = /.well-known/acme-challenge/ {
    return 404;
    }

    3.重启,然后安装证书

    # 将第一个参数 arg0 改为你的静态资源目录,第二个参数 arg1 改为你的域名
    
    sudo certbot certonly --webroot -w [arg0] -d [arg1]
    

    4.新增 443 端口的配置

    # 同上,注意修改参数。arg0 改为静态资源目录,arg1 改为域名
    server {
         listen 443 ssl http2;
         server_name [arg1];
    
         ssl_certificate /etc/letsencrypt/live/[arg1]/fullchain.pem;
         ssl_certificate_key /etc/letsencrypt/live/[arg1]/privkey.pem;
    
         location / {
                 root [arg0];
         }
         // 复制其他你自定义的配置
    }
    

    5.设置定时任务,定时更新证书(证书有效期 90 天)

    sudo crontab -e
    # 添加以下内容,每周一 2:30 执行一次更新,并且将日志存放在指定目录
    30 2 * * 1 certbot renew  >> /var/log/le-renew.log
    
  • Docker

    这个算是比较折腾的玩儿法,可偏偏笔者就是爱折(zhuo)腾(si),我的 nginx 是 docker 部署的,为什么非要用 docker 呢?主要是我不想让自己主机一大堆乱七八糟的东西,所有东西都放 docker 里面,不需要了,直接整个容器扔掉。

    这里其他配置不变,nginx 的配置文件仍然按照上面配置,静态资源目录就用你容器的静态资源目录映射宿主机的目录就行,然后主要的就是再增加一个目录映射,将你的证书文件映射到容器里面,让 nginx 能够读取到就可以了,如下:

  • -v /etc/letsencrypt:/etc/letsencrypt
    

    其他大同小异,根据自己主机情况进行修改。

    如果不知道该怎么改,思考一下申请证书的原理应该就清楚了。

    大致流程是 CA 会给你下发一些任务,然后如果你能够完成这些任务,就代表着你是域名的拥有者,那么就可以颁发证书,详见参考文章。

    总结

    文章写到这里差不多也就结束了,这里进行一个小小的总结。为了数据安全,所以我们需要进行数据加密,然后分别提到了对称加密非对称加密,虽然非对称加密安全性特别好,但是效率太低,不适合大量使用,所以使用非对称加密来传输对称加密所需的密钥就成了更加合适的方案,而这么做还有一个问题就是公钥的传输问题,从而引入了认证中心来对公钥进行认证,也就是说告诉客户端,这个公钥确实属于某某域名,不是第三发伪装的,到这里一切问题就解决了。


    最最后,分享一个更香的。如果你的域名是从阿里云购买的,阿里云为每个域名提供 20 张免费的证书,通过认证之后可以下载下来,然后直接放到服务器就一切搞定了,教程在这里 (https://help.aliyun.com/product/28533.html?spm=a2c4g.11186623.6.540.4fc23de35ePYn3) ,官方提供了各种情况下的文档,真的是太太太香了~~~

    参考

    1.Let’s Encrypt

    https://letsencrypt.org/

    2.Certbot

    https://certbot.eff.org/

    3.如何免费的让网站启用HTTPS — 酷 壳 – CoolShell

    如何免费的让网站启用HTTPS

    4.Let’s Encrypt是如何工作的

    https://blog.csdn.net/canghaiguzhou/article/details/79945001

    5.手把手教你在Nginx上使用CertBot

    https://segmentfault.com/a/1190000005797776


    全文完


    以下文章您可能也会感兴趣:

    我们正在招聘 Java 工程师,欢迎有兴趣的同学投递简历到 rd-hr@xingren.com 。

    转载请注明:无限飞翔 » 从对称加密到非对称加密再到认证中心:https 的证书申请

    喜欢 (0)or分享 (0)
    发表我的评论
    取消评论
    表情