最难不过二叉树

HTTPS下的安全传输

2024-10-17

在软件架构设计中,系统安全是一个很大且很重要的话题。我们聊到的架构安全,至少包含以下问题的解决方案:

  • 认证:系统如何正确分辨操作用户的真实身份?
  • 授权:系统如何控制用户能进行哪些操作?
  • 凭证:系统如何保证它和用户之间的承诺是准确的、完整且不可抵赖的?
  • 保密:系统如何保证内部敏感数据无法被窃取和滥用?
  • 传输:系统如何保证通过网络传输的数据不会被第三方窃听和滥用?
  • 验证:系统如何确保提交的数据是合乎规则,不会对系统稳定性、数据一致性、数据正确性产生风险?

架构安全,不会直接产生经济效益,但是又不能不考虑,一旦出问题了,对于产品而言往往就是灾难性后果。以上架构安全问题都在系统架构起来时就必须考虑清楚,即使不是每一个问题又需要立即得到解决,但是至少对其隐藏的后果需要有明确的认识。

本文想聊聊架构安全中的一点,即传输安全。现在的B/S和C/S架构中,用户要跟服务器通信,就必须通过网络。网络链路的复杂性和不可控性,导致了数据在传输过程中有可能被窃听甚至被篡改。比如一个常见的用户登录操作,简单拆分为三个环节,我们的数据可能在这三个环节都可能被窃听到你的敏感信息。

image (30).png

  • 客户端:在客户端植入病毒,在你输入账密时,记录下你的输入,你的密码泄漏了
  • 网络传输:数据明文传输,你的敏感信息可能在某个路由器或者网卡中被抓包了
  • 服务器:假设账密明文存储的话,你的账密信息可以被内部人员所看到,被别有用心的人所利用

在非安全信道中,主要会面临以下三个安全风险:

  • 窃听风险: 数据在传输线路上的每个环节都可能被窃听,从而导致敏感数据泄露。
  • 篡改风险: 数据在传输过程中可能被篡改,比如网络传输中可能被抓包 ,数据包被修改后再放回传输链路。
  • 伪装风险: 攻击者可以伪装成合法的身份,例如中间人攻击。

从这么一个操作看来,你的敏感信息在任何一个环节都可能被窃听,如果不做一下安全措施,个人信息毫无安全可言。其中传输安全是最容易被窃听的一个环节,因为数据传输链路根本不受自己的掌控,其复杂性导致了网络传输总是不安全的。那么传输安全是怎么做到的呢?那就得靠基于信道的认证。当我们相信一个信道绝对安全时,我们才会在这信道上传输数据,而这里的信道认证,需要用到三项密码学技术:摘要、签名、加密

摘要:对一份数据,进行一个单向的 Hash 函数,生成一个固定长度的 Hash 值,这个值就是这份数据的摘要,也称为指纹。常见的摘要算法有 MD5、SHA-1、SHA-256 等。

保证数据不被篡改可以使用摘要的技术,保证数据不被看到可以使用加密技术。

摘要的意义是在源信息不泄露的情况下辨别真伪。易变性保证了可以从公开的特征上甄别出信息是否来自源信息(一旦对源信息有一点修改,输出就会大不相同),不可逆性保证了不会从公开的特征暴露源信息(不能从输出反推输入)。

解释签名和加密前,需要介绍一下公钥和私钥的概念。

根据加密和解密是否采用同一个秘钥,可以将对称加密算法和非对称加密算法。对称加密算法中,加密和解密都用同一个秘钥,加密解密速度都比较快。非对称加密算法的秘钥分为私钥和公钥,私钥用户自行保管,不参与通信传输,公钥则是完全公开,任何人都可以获取到,但加解密速度都比较慢,比对称加密慢数个量级。

非对称加密速度慢,这导致了这个方式不适合频繁使用,因为在高并发的互联网业务中,长时间的高延迟是不能接受的。对于一些频繁的加解密操作而言,对称加密是更好的方案,因为对称加密速度很快。但是这里引出另一个问题:如果要采取对称加密的方式进行通信,则需要将秘钥安全地交给对方,那对称加密用到的秘钥怎么安全地传递给对方呢?这就是秘钥分发的难题。

非对称加密可以从根本上解决秘钥分发的难题。非对称加密有两个典型用法,在后面提到的HTTPS中都有实际运用:

  • 公钥加密,私钥解密:这种就是加密。可以防止内容不被篡改也不被窃听。
  • 私钥加密,公钥解密:这种就是签名。可以防止内容不被篡改,但是不能防止内容被窃听。

现在一般会结合对称加密和非对称加密的优点,以混合加密来保证信道安全。具体的做法就是:

  1. 先用非对称加密来安全地传递少量数据给通信的另一方,比如传递对称加密用到的秘钥
  2. 采用对称算法安全高效地大量加密传输数据

以上就是HTTPS的最基本的传输安全的思路了,对称加密和非对称加密是其底层技术支撑,即混合加密来保证信道安全。但是在传输安全上,还有一些问题需要解决,最明显的就是中间人问题。A和B要进行通信时,B需要把自己的公钥给到A做秘钥协商。当A从网络中拿到了一个声称是B的公钥时,A怎么确定这个公钥就是B的公钥?

微信截图_20241129100745.png

网络充满了不确定性,你永远不知道网络中是否还存在着C,一直窃听着你的数据。中间人攻击表面上看是系统 A 与系统 B 建立加密连接,但是实际上数据流会被第三方重定向,让加密连接从系统 A 运行到系统 C,然后才重定向到系统 B。这让系统 C 的控制者(通常是攻击者)可以完整地查看、记录以及操纵数据流量。攻击者还通过这种方式将系统 C 作为网络服务器呈现给系统 A,并给用户端呈现错误的浏览页面。

公钥分发时也受中间人攻击的影响:C冒充了B截取了信道上B给A发的公钥,换成C自己的公钥,此时A就会使用C的公钥对消息进行加密,误以为给B发信息,其实A在给C发信息,C用自己的私钥解密A加密传输的信息,那A和B的通信内容被完全窃取了。这个例子里,C就是中间人,在AB通信过程中调包了B的公钥。

非对称加密解决了对称加密使用的秘钥传输的问题,但是自身的公钥传输问题没有解决,因此才会有中间人攻击的问题。那怎么保证这个公钥能安全传输?

这里要解决的其实是信任问题,A和B通信,怎么确定通信双方就是A和B呢?我们想一想,在现实生活中,我们两两之间是怎么达成信任的。

  • 基于共同私密信息的信任:比如有个陌生人打电话找我借钱,说他是我的同学,此时如何确定他的身份?可以问他一些只有我们俩知道的问题,如果他能回答,我就信任他。
  • 基于权威公证人的信任:比如有个陌生人找我,说他是警察,让我把钱转到一个安全账户上。此时如何确定他的身份?可以拉他去一趟公安局,公安局作为权威机构来认证他的身份。

所以在传输安全上,我们可以使用权威公证人来验证公钥发放的问题,这里的权威公证人数字证书认证中心(CA)。任何人都都可以签发证书,只是不权威罢了。CA是受信任的第三方,承担公钥体系中公钥合法性检验的责任。在网络世界上,验证公钥的合法性,就得拿着公钥通过网络去CA检验这个公钥是否合法。但是这个“拿着公钥通过网络去CA检验”这个动作本来就是不可信任的,因为你去的这个所谓的权威CA,很可能就是个伪装的CA,我们不该轻易信任他。

这个该怎么解决这个信任问题?通过操作系统和浏览器给他背书。网络传输会导致不信任的产生,那么我们就避免网络传输来建立信任。权威的CA中心在浏览器和操作系统出厂时就已经预设好或者提前安全装好,我们可以信任这批CA。所以我们这个传输安全体系的信任链起点就是浏览器和操作系统出厂时预设的CA,因为我们信任他们,整套数字签名体系才有了坚定的逻辑基础,整个传输安全体系才能构建起来。

证书是权威CA中心对特定公钥信息的公证载体,也可以理解为权威CA对特定公钥未被篡改的签名背书。因为客户的机器上已经内置了权威CA中心本身的证书,所以我们可以在不依赖网络的前提下,用根证书的公钥信息对其所颁发的证书的签名进行确认。这里就是用到非对称签名的私钥加密,公钥解密的理论,证书颁发时由权威CA的私钥进行加密,证书检验时通过内置CA的公钥进行解密,通过签名确认证书确实是权威机构所颁发的,没有被替换和篡改。

聊到这里,整个传输安全的信任链已经建立起来,每一个信任漏洞都被我们解释清楚了。要自己实现一套传输安全的解决方案十分繁琐,但传输安全又是web通信中最基本的一环,因此有必要由机构牵头去完成这么一项工作,做成一套标准化工作。而HTTPS正是传输安全的一套解决方案:HTTPS=HTTP+TLS。

TLS即安全传输层协议,TLS保证了以下三点:

  • 信息不会被第三方窃取(加密传输)
  • 信息无法篡改(一旦篡改立刻被发现)
  • 无法冒充(数字证书验证身份)

以下图为例,我们梳理TLS 1.2的建立流程

  1. 客户端发起client hello,带上可使用的TLS版本、加密算法和压缩算法列表
  2. 服务器发起server hello,带上确认使用的TLS版本、sessionID,加密算法,压缩算法、证书(公钥)
  3. 客户端验证服务器证书的合法性,取出证书中的公钥,生成一个秘钥随机数S key,用公钥进行加密得到MasterSecret。客户端发起client handshake finished。
  4. 服务器用私钥解密MasterSecret,得到S key。服务器发起server handshake finished,通知握手结束,后续信息将用双方商定的加密方式和秘钥发送。

SSL.png

至此,整个TLS握手阶段结束,一个安全的连接建立完成。每一个连接的建立都需要客户端和服务器协商很多信息,比如一个只有双方才知道的随机秘钥、传输过程中采用的对称加密算法、压缩算法等。这种处理方式对上层协议的功能完全透明,虽然在传输性能上会有所下降,但是在功能上不会感知到TLS的存在。

因为HTTPS的存在,现在谈传输安全时已经不会感到无从下手,在做网络通信设计时也不会纠结于我们的通信是否还安全,在架构设计中省了很多要考虑的点。所以在做架构设计时,一定要考虑上HTTPS,而不要通过其他方式去保证这个传输安全性,这是最基本的设计原则。