「 点击图片获取最近两年爆款好文 」
本篇将讨论 HTTPS 的加解密原理,很多人都知道 RSA,以为 HTTPS=RSA,使用 RSA 加解密数据,实际上这是不对的。
HTTPS 是使用 RSA 进行身份验证和交换密钥,然后再使用交换的密钥进行加解密数据。
身份验证是使用 RSA 的非对称加密,而数据传输是双方使用相同的密钥进行的对称加密。那么,什么是对称加密和非对称加密 ?
对称加密和非对称加密
假设隔壁小王想要约小红出来,但是他不想让小明知道,于是他想用对称加密给小红传了个小纸条。
如下图所示:他想发送的数据是"Meet at 5:00 PM"(5 点见面,如果是中文的话可以使用 UTF-8 编码),加密方式是直接在 ASCII 表进行左移或右移。
他的密钥是 3,表示在 ASCII 表往后移 3 位,就会变成"Phhw#dw#8=33#SP",这样一般人如果截获了不知道是什么意思的。
但是我们可以想一下,如果既然他可以截获你的数据,自然也可以截获你的密钥,进而进行解密。
如下图所示:所以小王打算用非对称加密,非对称加密的特点是双方都有自己的公钥和私钥对,其中公钥发给对方,密钥不交换自己保管不泄漏。
如下图所示:public_key = (N, e) = (3233, 17)
她把公钥发给了小明,她自己的私钥为:
private_key = (N, e) = (3233, 2753)
这里注意公钥和私钥都是两个数,N 通常是一个大整数,e 表示一个幂指数。现在小王想给小红发消息,于是他用小红的公钥进行加密,怎么加密呢?
他要发送的第一个字母为 t=“M”,“M”的 ASCII 编码为 77,77 的加密过程如下计算:
T = 77 ^ e % N = 77 ^ 17 % 3233 = 3123
把 77 做 e 次幂然后模以 N,便得到了 T=3123,然后把这个数发给小红(其他字母按同样方式处理)。
小红收到 T 之后便用她的私钥进行解密,计算如下:
t = T ^ e % N = 3123 ^ 2753 % 3233 = 77
计算方法是一样的,这样便把 T 还原成了 t,只要公私钥配对,便可通过一些数学公式证明上面的推算是成立的。这个就是 RSA 的加解密原理,如果无法知道私钥便无法进行正确解密。
反过来,使用私钥进行加密,公钥进行解密也是可行的。那么 HTTPS 是怎么利用 RSA 进行加解密的呢,我们从 HTTPS 连接建立过程说起。
HTTPS 连接建立过程
HTTPS 主要有以下作用:-
验证服务方身份,如我访问 google.com 的时候连的确实就是谷歌服务器
-
防止数据被劫持,例如有些运营商会给 http 的页面插入广告
-
防止敏感数据被窃取篡改等
正如 openssl 的注释所说,这是防止中间人攻击的唯一方法:
如下图所示:
在 Client Hello 里面客户端会告知服务端自己当前的一些信息,如下图所示:
服务端在 Server Hello 里面会做一些响应:
-
密钥交换使用 ECDHE
-
证书签名算法 RSA
-
数据加密使用 AES 128 GCM
-
签名校验使用 SHA256
接着服务给客户端发来了 4 个证书:
一个证书里面会有什么东西呢,我们可以展开第一个证书看一下,如下图所示:
-
tbsCertificate(to be signed certificate)待签名证书内容
-
证书签名算法
-
CA 给的签名
身份验证
我们先来看一下 tbsCertificate 里面有什么内容,如下图所示:
Amazon 的证书也具备上述结构,我们可以把 Amazon 证书的公钥拷出来,如下图所示:
然后我们用这个 CA 的公钥对 mozilla.org 的证书签名进行解密,方法和上面的类似:
接下来我们手动计算一下 tbsCertificate 的 SHA256 哈希值,方法是在 wireshark 里面把 tbsCertificate 导出一个原始二进制文件:
然后再使用 openssl 计算它的哈希值,如下所示:
liyinchengs-MBP:https liyincheng$ openssl dgst -sha256 ~/tbsCertificate.binSHA256(/Users/liyincheng/tbsCertificate.bin)= 5e300091593a10b944051512d39114d56909dc9a504e55cfa2e2984a883a827d
我们发现手动计算的哈希值和加密后的证书里的哈希值一致!说明只有知道了 Amazon 私钥的人才能正确地对 mozilla.org 的证书签名,因为公私钥是唯一匹配的。
因此我们验证了第一个证书 mozilla.org 确实是由第二个证书 Amazon 签发的,使用同样的方式,我们可以验证 Amazon 是由第三个签发的,第三个是由第四个根证书签发。
并且第四个证书是根证书,它是内置于操作系统的(通过 Mac 的 keychain 工具可以查看):
例如通过打电话或者发邮件等方式告知服务器的签名,与自己算的证书的签名是否一致,如果一致说明证书没有被篡改过(如证书的公钥没有被改为 Hacker 的公钥):
密钥交换
密钥交换的方式有两种:RSA 和 ECDHE,RSA 的方式比较简单,浏览器生成一把密钥,然后使用证书 RSA 的公钥进行加密发给服务端,服务再使用它的密钥进行解密得到密钥,这样就能够共享密钥了。 它的缺点是攻击者虽然在发送的过程中无法破解,但是如果它保存了所有加密的数据,等到证书到期没有被维护之类的原因导致私钥泄露,那么它就可以使用这把私钥去解密之前传送过的所有数据。而使用 ECDHE 是一种更安全的密钥交换算法。如下图所示,双方通过 ECDHE 进行密钥交换:
这个算法的思想如下图所示:
椭圆曲线加密
现在的证书的签名算法有两种:RSA 和新起的 EC。如下图所示,google.com 便是使用的 ECC 证书:
如下图所示,有一条椭圆曲线方程:
y ^ 3 = x ^ 2 + ax + b:
为了计算 3G 的坐标,如下图所示:
EC 的难点在于给定起点 G 和点 K:
K = kG
想要得到 K(K 足够大)是一件很困难的事情。这个 K 便是私钥,而 K=kG 便是公钥。ECC 是怎么加解密数据的呢?
假设要加密的数据为 m,把这个点当作x坐标得到在曲线上的一个点 M,取定一个随机数 r,计算点 C1=rG,C2=M+rK。
把这两个点便是加密后的数据,发给对方,对方收到后使用私钥 K 进行解密,过程如下:
M = C2 - rK = C2 - rkG = C2 - rkG = C2 - kC1
通过上面的计算便能还原得到 M,而不知道私钥 K 的人是无法解密的。更多细节可见 Medium 的这篇文章《ECC elliptic curve encryption》。这样我们便理解了 ECC 的原理,那么怎么利用 ECC 进行密钥交换呢?
ECC 密钥交换
原理很简单,如下图所示:
而曲线方程是规定好的,例如 Curve X25519 使用的曲线方程为:
y^2 = x^3 + 486662x^2 + x
在密钥交换里面会指定所使用的曲线方程,如下图所示:
HTTPS 证书的应用
那么是谁在做 HTTPS 加密呢?服务端通常是 Nginx、Apache 这些反向代理服务器做的,而具体的业务服务器不需要处理,客户端通常是浏览器等做的加解密,Chrome 是使用 boringSSL 这个库,fork 自 openssl。 我们通过 let’s encrypt 可以申请免费的 TLS 证书,每 3 个月需要手动续。 证书分为 3 种:DV、OV、EV,DV 适用于个人,OV 和 EV 需要身份审核,EV 最高端。EV 证书会在浏览器的地址栏显示证书的企业名称:
但是新版的 Chrome 似乎把这个去掉了,所以我们打开 medium 的控制台可以看到一个提示:
As part of an experiment, Chrome temporarily shows only the lock icon in the address bar. Your SSL certificate with Extended Validation is still valid.
另外我们可以用 openssl 生成一个自签名证书,执行以下命令:
openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -keyout test.com.key -out test.com.crt
便会得到两个文件,test.com.crt 是证书,test.com.key 是证书的私钥,如下图所示:
然后把这两个文件给 Nginx 使用便能使用 HTTPS 访问,如下代码所示:
server { listen 443; server_name test.com; ssl on; ssl_certificate test.com.crt; ssl_certificate_key test.com.key; }
可以把这个证书添加到系统证书里面,这样浏览器等便能信任,或者直接使用 mkcert 工具一步到位。
客户端证书
还有一种证书叫客户端证书,同样需要向 CA 机构申请一个客户端证书,和服务端 TLS 证书不一样的地方是,服务端证书通常是和域名绑定的,而客户端证书可以给本地的任意可执行文件进行签名。签名验证算法和上文讨论的 TLS 证书一致。为什么可执行文件需要签名呢,因为如果不签名的话,系统会拦截安装或者运行,如 Mac 双击一个未签名的 dmg 包的提示:
直接不让你运行了,而 Windows 也有类似的提示,Windows 是会给一个警告:
而当我们运行一个已签名的 exe 文件将会是正常的提示,如 Chrome 的提示:
作者:李银城
来源:https://zhuanlan.zhihu.com/p/75461564
最新整理的 2TB 技术干货:包括架构师实战教程、大数据、Docker容器、系统运维、数据库、redis、MogoDB、电子书、Java基础课程、Java实战项目、ELK Stack、机器学习、BAT面试精讲视频 等。只需在 「 民工哥技术之路」 微信公众号对话框回复关键字:1024 即可获取全部资料。
☆ END ☆精彩文章推荐:
点击【 阅读原文】发现更多精彩
点个在看、转发支持一下吧 ↓↓ ↓