SSL 和 TLS 是运输层的提供安全服务的协议,TLS 是 SSL 的升级版,更为安全强大。
在此着重介绍 SSL 里用到的加解密技术和特点,以及如何利用加密原理去解决网络传输的中可能存在的安全风险。
# 安全风险 ↵
因为现代计算机网络的信道是公开的而且 IP 包的传输是分组交换的,所以会产生下面的这些问题。
- 窃听风险,通信内容会被截获
- 篡改风险,通信内容会被修改
- 冒充风险,通信双方可以被冒充
在 web 领域,也有上述的这三种安全风险,SSL 可以解决上面的三个问题,使得在其之上的服务变得很安全,比如 https。
要理解 SSL,得先知道一些关于加密解密的知识。
# 对称加密 ↵
对称加密很容易理解,就是用密码去加密数据,而且只能用这个密码去解密,这就是对称性的体现。
这个密码,一般称作密钥。
工业界比较常用的对称加密是 AES 标准,npm 上有开源的包可以用。
公式:
E(明文, 密钥) = 密文
D(密文, 密钥) = 明文
D(密文, 密钥) = 明文
其中,E 是加密函数,D 是解密函数。
# 非对称加密 ↵
相比对称加密,非对称加密里有两把钥匙(密码),以下是公式:
E(明文, 公钥) = 密文
D(密文, 私钥) = 明文
D(密文, 私钥) = 明文
也可以用私钥来加密,用公钥来解密。
E(明文, 私钥) = 密文
D(密文, 公钥) = 明文
D(密文, 公钥) = 明文
其中 E 是加密函数,D 是解密函数。
总之,如果用其中一把钥匙加密生成密文,那就只能用另外一把来解这个密文得到明文,这是非对称性的体现。
至于如何生成公钥私钥,以及加解密函数是什么样的,这是数学家的问题,工业上常用 RSA 和椭圆算法来完成非对称加密。
# 数字签名 ↵
数字签名可以用来防止被篡改,利用了非对称加密来做,给将要传送的消息签个名,接收方验证这个签名就可以确认消息是否完整。
以下是数字签名的过程:
假设 Alice 准备发送一个 msg 给 Bob
- Alice 计算出将要发送的 msg 的 md5 哈希值 M
- Alice 用 Bob 的公钥加密 M,得到 MCode
- Alice 将 [MCode, msg] 发给 Bob (注意 msg 依然是明文,但是带了一个头)
- Bob 接收到了 [MCode, msg] 之后,计算 msg 的哈希值 M2
- Bob 用私钥解密 MCode 得到 Alice 计算得到的 M 跟 M2 比对一下
- 如果不一致,说明内容已经被篡改,否则说明内容未被篡改
这一套机制叫做数字签名,它保证了传输的内容不会被篡改,被篡改的消息会失效。
但是,这样的话 msg 不就是明文了吗?那有什么用?
带着疑问继续往下看。
# CA 和证书 ↵
CA 是证书颁发机构。
Bob 如果想要提供 SSL 服务,得去找 CA 申请一个证书。 一个证书至少包含如下数据:
- Bob 的域名
- Bob 的公钥
- CA 的公钥
- 创建时间和过期时间
- 其他的信息(如用什么哈希算法等等,在此不是重点)
- 数字签名(很重要,用来防伪)
可是这样的证书有什么用?很简单,CA 和证书的作用是让可信的权威第三者介入通信。比如在 web 里,浏览器请求一个 https 的 URL 的时候,会首先取得服务方提供的证书,证书里有一些服务器的参数,利用这些参数才能完成 SSL 的初始化工作(握手),而具体如何初始化,后文有介绍,请继续往下读。
既然证书是服务器发送的,有没有可能被截获,被篡改之后发回给客户端?当然有,这里就要对证书做一些防伪措施了。
# 证书防伪 ↵
为了防止证书被伪造和篡改,得给证书加数字签名以保证证书的完整性。
CA 有自己的一对非对称加密钥匙,CA 在创建一个证书的时候,会计算出证书的哈希值 M,然后用私钥将其加密得到数字签名。
Alice 在得到证书之后会计算证书的哈希 M1,然后利用证书里 CA 的公钥解出数字签名的哈希 M2,然后对比 M1 和 M2 如果一致,说明证书有效,否则无效。 (因为数字签名是用私钥加密的,攻击者不知道私钥,故无法伪造)
这里要求证书是明文可见的,其明文特征还是有用的,尤其是在第三方介入的时候。
此外很多地方都有用到数字签名,比如某些应用程序的可执行文件会带有数字签名以保障完整性。
# 解决窃听风险 ↵
要解决被窃听的风险,我们只需把我们要传输的内容加密即可,让对方将其解密读取。
这里会产生一个新问题,那就是,这个加密要用对称加密还是用非对称加密。
答案是对称加密,因为非对称加密性能很差,只适合小体积的加密,那么既然使用了对称加密,就要让双方都知道密钥,而信道是公开的,肯定是不能在信道上明文传输密钥的,这样很危险,既然如此,通信双方是怎么协商好密钥的?
到此为止,解决窃听风险已经有了一个思路,那就是传输的时候将数据加密再发送,等接收方接收了之后自行解密读取。
我们将窃听问题化简为协商问题了。
# 如何协商密钥 ↵
以前也常常在想,既然信道不可靠,那么明文传密钥肯定是不安全的,如果用对称加密,对方又如何知道你的密钥?
后来我学习了非对称加密,才知道非常简单,协商密钥得借助非对称加密才行。
假设现在 Alice 和 Bob 准备协商密钥,而且,Bob 有一对公钥和私钥,以下是密钥协商的过程:
- Alice 向 Bob 请求获取 Bob 的公钥 pub_key
- Bob 把公钥 pub_key 告诉了 Alice (第一第二步在 SSL 里由证书提供)
- Alice 随机生成一个密钥 abc
- Alice 用公钥 pub_key 加密 abc, 最后得到被公钥加密过的密钥 Code
- Alice 将 Code 发给 Bob
- 因为只有 Bob 有私钥,所以 Code 只能被 Bob 解开。
- Bob 解开了 Code,得到 abc 这个密钥,密钥协商完成
这样就完成了密钥协商,数据传输被窃听的风险解决了。
对了,这里的密钥在 SSL 里叫做会话密钥。
# 解决篡改风险 ↵
有两种方案可以防止被篡改。
一种是将明文加密成密文,然后传输密文给对方,即便攻击者篡改了密文,接收方也无法将其解密,就不会造成误会,因此只需要加密传输的数据就可以解决被篡改的风险。
还有一种就是数字签名
# 解决冒充风险 ↵
有这样一种可能,比如 Alice 发了 hello 给 Bob,密文被 C 截获。
第二天, C 重新把密文发给 Bob,这时候密文可以被解为 hello,Bob 并不能知道密文来自于谁。 别人可以重放这个密文达到扰乱的效果。
相反,Bob 发给 Alice 的密文也可以被截获重放,也会产生一样的问题。
以上就是冒充,要解决它,关键在于发送方和接收方的互相认证。
# 重放的问题 ↵
解决重放,可以在每次传消息的时候带上一个序号,接收方会记录它,如果再次收到这个包,无视即可。
也可以带上时间戳和过期时间,防重放的方法有很多。
# Alice 认证 Bob ↵
Bob 要证明它就是 Bob,只需要证明它有私钥就可以了。
比如 Alice 访问 Bob 的域名的时候,首先得取得 Bob 提供的 CA 证书,上面记录着 Bob 提供的公钥。 (CA 是可信的,所以公钥可信,故将安全的责任加在 CA 上)
Alice 用这个公钥将 hello 加密后发给 Bob,如果 Bob 能返回 hello,则说明 Bob 确实是 Bob 。
在 SSL 里,Alice 认证 Bob 的过程是在初始化阶段(握手阶段),利用证书里的参数进行,后文会补充描述。
# Bob 认证 Alice ↵
Alice 要证明自己是自己,只需证明他有会话密钥即可。
即:Alice 用 Bob 的公钥加密会话密钥发送给 Bob,Bob 解密后对比自己的会话密钥即可。
当然,在 web 里,一般只需要 Alice 认证 Bob 即可(只需要单向认证就可以了)。Bob 认证 Alice 可以靠 Session / Cookie。
# SSL 协议过程 ↵
完整的 SSL 由三个协议构成,分别是:
- SSL 握手协议:协商会话密钥、加密算法,验证证书有效性,双方身份认证等
- SSL 记录协议:保证传输内容的机密性和完整性
- SSL 报警协议:告知实体(浏览器、服务器)通信中可能的错误,比如证书错误,证书过期,传输内容校验失败等等。
以下是 SSL 简要的握手过程。
- Alice 发送 hello 给 Bob,并要求要求使用 SSL 创建安全连接
- Bob 响应 hello, 返回证书给 Alice
- Alice 验证证书的有效性(利用数字签名)
- Alice 用证书里 Bob 的公钥加密握手包发送给 Bob,握手包里包含会话密钥
- Bob 收到后利用他的私钥解开 Alice 发送过来的加密包,得到会话密钥,并用它来加密响应握手包发送给 Alice
- Alice 收到,验证 Bob 发送的加密响应包,若有效则握手阶段结束,进入加密通信阶段。
注意事项:
- 服务器也可以要求验证客户端,这里不做介绍
- 当中任何一步都可以触发 SSL 报警
- 省略了很多细节,可以参阅 维基百科 - 传输层安全性协议
带证书的 SSL 双向认证握手过程
# TL;DR ↵
SSL 里面采用的加密算法在理论上破解是几乎不可能的,只要增加密钥的长度就可以让密码的安全性得到指数倍的增长。
通常针对 SSL 的攻击主要是针对握手阶段,比如利用 DNS 污染和伪造 CA 证书让客户机相信证书的有效性,从而达到中间人攻击等。
也可以直接去机房把 Bob 的私钥黑到手,这样就更容易做中间人了。