https 的出现,为解决网络加密通信提供了完美的解决方案。现在得到了非常普遍的运用。但 https 的原理和部署方式还存在一些较迷惑的点。
一、基础数学知识
在普通的http通讯过程中,前端浏览器和服务器之间传递的都是明文,这样敏感信息就容易被第三方看得到。就像早期电台发送的电波是普发式的,不仅被接受者能接收到,其他人一样可以接收到,信息就泄露了。
后来,发展到对电波进行简单加密发送。例如,把要发送的每个字母向后移动若干位得到其他字母,接受者再往回移动若干位就得到原文。这种加密方式就早期英文报纸上的填词游戏。经过验证,这种方式还是比较容易破解的。
再后来,加密方法更进了一步。例如,使用对称加密算法(AES等)依靠共享密钥加解密的方式可以对信息进行加密,但同时需要给接受者传递密钥,密钥传输的过程本身也是明文的。这就是对称加密。就像二战中德国的恩尼格玛密码机,虽然增加了破解难度,但需要密码本,同样还是有安全漏洞,不是完美的加密通讯方案。
70 年代,美国的3个数学家基于欧拉定理提出了RSA加密算法。这个加密办法基于大整数很难分解成两个大质数乘积的原理,使用一对公钥和私钥进行加密。重点:公钥和私钥是成对出现的。
RSA 加密运算的性质:使用公钥加密的数据,可以并且只可以用对应的私钥解密;使用私钥签名的数据,也可以使用相对应的公钥进行验证;加密和签名的运算方法是一样的。公钥用来加密要传输的数据,确保只有持有私钥的人才可以看得到。私钥用来签名,来验证数据有没有被篡改,因为私钥只有服务器才有,但公钥是所有人都有的,因此私钥签名的数据通常用来验证服务器的身份。这是非对称加密。
对称加密不安全但速度比较快,非对称加密更安全但速度比较慢。
二、RSA 加密的运用
以服务器和浏览器进行一对多通信为例:
- 服务器S负责产生公钥和私钥。其中,公钥任何浏览器都可以下载。私钥,只有服务器才能拥有,是绝对保密的。
- 当浏览器B想向服务器S发送信息的时候,它首先下载S的公钥。
- 然后用公钥将想传递的数据加密,传送给服务器S,这个数据只有服务器S才能解开。
三、以上通讯方法的漏洞
以上示例中,假设服务器S是某银行,浏览器B、C、D 等都代表用户,他们只有和 S 通讯才是安全的。因为浏览器只会无脑的使用公钥加密数据。假设,有人设置了一个和 S 一模一样界面的服务器S1,也能下发公钥和私钥,那么 B、C、D 是无法辨别真假的。当B、C、D连接到假冒的服务器 S1 后,就会下载到 S1 的公钥。随后,就会把账号、密码等重要信息通过 S1 下发的公钥加密后发给 S1,S1 能够看得到了。此外,S1 还能将这些信息转发给真正的服务器 S,这中间过程用户是完全无法察觉的。
四、HTTPS证书的使用
HTTPS证书就是用来证明服务器身份用的。证书一般都是有公信力的第三方机构发放,这些机构称为CA。著名的 Let’s Encrypt 就是发放免费证书的第三方机构。有以下几个要点:
- CA有自己的私钥和公钥;
- 操作系统内置了很多CA的公钥;
- 服务器申请证书的过程。服务器在申请证书的时候,首先生成一对自己的公钥和私钥。服务器把自己的公钥和域名等相关信息发送给CA,CA会验证服务器的真实性,也就是检验当前申请者对域名所绑定的服务器是否有控制权。验证成功后,CA会把服务器发过来的信息使用自己的私钥进行签名,形成证书,返还给服务器;
- CA发放证书的过程。将网站域名、公钥等信息用哈希算法算一遍,得到一个数字指纹H;再用自己的私钥将这个H签名,得到一个签名S;然后将签名和网站信息等内容打包发还给服务器。
- 浏览器验证证书的过程。浏览器与服务器通讯的时候,会首先得到服务器的证书。证书里包含网站的基本信息和签名S。浏览器使用CA的公钥将签名打开得到一个指纹 H1。浏览器使用与CA 相同的算法将网站的基本信息哈希一遍,得到一个指纹数据H2。比较 H1 和 H2 是否相等,如果相等则通过验证。
五、Let’s Encrypt证书的申请和续期
Let’s Encrypt 免费发放证书,但他们发放的证书有效期只有 90 天。这里就有一个续期的问题,最好是自动续期。
certbot申请证书的原理
Let’s Encrypt 提供了 certbot 软件提供证书申请服务。由上文可以看出,CA 发放证书的关键一步就是要验证申请者是否对域名和服务器有控制权。certbot 通常有两种方式来验证。
- http01 方式验证。就是要求申请者在服务器上建立让Let’s Encrypt 可以正常访问的特殊链接。以 nginx 服务器为例。首先要配置 nginx,让/.well-known/acme-challenge/路径匹配。Let’s Encrypt 会要求 certbot 在/.well-known/acme-challenge/对应的路径根目录内创建一个特殊文件。特殊文件创建后,certbot 会通过 http 方式访问这个文件。如果能够正确访问,则表明验证通过。这个验证方式只支持 80 端口。
- dns 方式验证。要求为用户手动域名建立一个 txt 记录,然后Let’s Encrypt 会访问这个路径,如果成功,则验证通过。这个方法对于Let’s Encrypt 证书来说不适合,因为它的证书有效期短,经常要续期,这种方式需要手动操作,就不太方便了。
certbot申请证书的具体操作办法
在容器环境下,可以 certbot 容器申请证书。在宿主机上的具体命令如下:
dockerrun-it--rm\-v./volumes/letsencrypt:/etc/letsencrypt\-v./volumes/www-vol:/var/www/certbot\certbot/certbot certonly--webroot\-w/var/www/certbot\-d${DOMAIN_NAME}\--email${DOMAIN_EMAIL}\--agree-tos\--non-interactive# 加上非交互模式,避免脚本卡住参数解释:
–webroot:表示采用 http01 的方式申请,需要服务器上正在运行一个 http 服务器,并且开放 80 端口。
certonly:表示只申请证书,不安装证书。certbot 有自动安装证书的插件,但不建议使用,会出错。
-d:指出要申请证书的域名。
-v ./volumes/letsencrypt:/etc/letsencrypt。 certbot 会访问容器内的/etc/letsencrypt 目录,证书申请好后会把证书等一系列文件存在这个目录内。为了持久保存和分享这些重要数据,需要把这个目录映射到宿主机上。
-w /var/www/certbot。表示 http 服务器内/.well-known/acme-challenge/路径对应的根目录是/var/www/certbot。
certbot 续签证书的原理和具体办法
当证书申请成功后,申请过程中有关配置信息会被存在一个叫做renewal的目录内。续期使用 certbot 的 renew 命令。这个命令会检查当前证书到期时间是否在 30 天以内,如果是,则会按照之前申请证书的方式再次申请一个新的证书。
具体命令如下:它的参数与申请证书的时候差不多,特别是目录映射配置。
dockerrun-it--rm-v./volumes/letsencrypt:/etc/letsencrypt-v./volumes/www-vol:/var/www/certbot certbot/certbot renew--webroot-w/var/www/certbot--quiet