43

文章同步于 Github/blog

人们会用 Web 事务来处理一些很重要的事情。如果没有强有力的安全保证,人们就 无法安心地进行网络购物或使用银行业务。如果无法严格限制访问权限,公司就不 能将重要的文档放在 Web 服务器上。Web 需要一种安全的 HTTP 形式。

目前已存在一些提供认证(基本认证摘要认证 )和报文完整性检查(摘要 qop="auth-int")的轻量级方法。对很多网络事务来说,这些方法都是很好用的, 但对大规模的购物、银行事务,或者对访问机密数据来说,并不足够强大。这些更 为重要的事务需要将 HTTP 和数字加密技术结合起来使用,才能确保安全。

HTTP 的安全版本要高效、可移植且易于管理,不但能够适应不断变化的情况而且还应 该能满足社会和政府的各项要求。我们需要一种能够提供下列功能的 HTTP 安全技术。

  • 服务器认证 (客户端知道它们是在与真正的而不是伪造的服务器通话)。
  • 客户端认证 (服务器知道它们是在与真正的而不是伪造的客户端通话)。
  • 完整性 (客户端和服务器的数据不会被修改)。
  • 加密 (客户端和服务器的对话是私密的,无需担心被窃听)。
  • 效率 (一个运行的足够快的算法,以便低端的客户端和服务器使用)。
  • 普适性 (基本上所有的客户端和服务器都支持这些协议)。
  • 管理的可扩展性 (在任何地方的任何人都可以立即进行安全通信)。
  • 适应性 (能够支持当前最知名的安全方法)。
  • 在社会上的可行性 (满足社会的政治文化需要)。

数字加密

术语

在这个数字加密技术的入门介绍中,我们会讨论以下内容。

  • 密钥:改变密码行为的数字化参数。
  • 对称密钥加密系统:编 / 解码使用相同密钥的算法。
  • 不对称密钥加密系统:编 / 解码使用不同密钥的算法。
  • 公开密钥加密系统:一种能够使数百万计算机便捷地发送机密报文的系统。
  • 数字签名:用来验证报文未被伪造或篡改的校验和。
  • 数字证书:由一个可信的组织验证和签发的识别信息。

密码

密码学基于一种名为密码(cipher)的秘密代码。密码是一套编码方案——一种特 殊的报文编码方式和一种稍后使用的相应解码方式的结合体。加密之前的原始报文通常被称为 明文(plaintext 或 cleartext)。使用了密码之后的编码报文通常被称作 密文(ciphertext)

用密码来生成保密信息已经有数千年了。传说 尤利乌斯·凯撒(Julius Caesar) 曾使用过一种三字符循环移位密码,报文中的每个字符都由字母表中三个位置之后的字符来取代。在现代的字母表中,“A”就应该由“D”来取代,“B”就应该由“E” 来取代,以此类推。

密钥

随着技术的进步,人们开始制造一些机器,这些机器可以用复杂得多的密码来快速、 精确地对报文进行编解码。这些密码机不仅能做一些简单的旋转,它们还可以替换 字符、改变字符顺序,将报文切片切块,使代码的破解更加困难。

往往在现实中,编码算法和编码机都可能会落入敌人的手中,所以大部分机器上都有一些号盘,可以将其设置为大量不同的值以改变密码的工作方式。即使机器被盗,没有正确的号盘设置(密钥值),解码器也无法工作。

这些密码参数被称为 密钥(key)。要在密码机中输入正确的密钥,解密过程才能正确进行。密码密钥会让一个密码机看起来好像是多个虚拟密码机一样,每个密码机 都有不同的密钥值,因此其行为都会有所不同。

给定一段明文报文 P、一个编码函数 E 和一个数字编码密钥 e,就可以生成一段经 过编码的密文 C。通过解码函数 D 和解码密钥 d,可以将密文 C 解 码为原始的明文 P。当然,编 / 解码函数都是互为反函数的,对 P 的编码进行解码 就会回到原始报文 P 上去。

image

对称密钥加密技术

很多数字加密算法都被称为 对称密钥(symmetric-key) 加密技术,这是因为它们在编码时使用的密钥值和解码时 一样(e=d)。我们就将其统称为密钥 k。

image

流行的对称密钥加密算法包括:DESTriple-DESRC2RC4

保持密钥的机密状态是很重要的。在很多情况下,编 / 解码算法都是众所周知的,因此密钥就是唯一保密的东西了。好的加密算法会迫使攻击者试遍每一个可能的密钥,才能破解代码。用暴力去尝试 所有的密钥值称为 枚举攻击(enumeration attack)

缺点

对称密钥加密技术的缺点之一就是发送者和接收者在互相对话之前,一定要有一个共享的保密密钥

比如 Alice(A)、Bob(B)和 Chris(C)都想与 Joe 的 五金商店(J) 对话。A、B 和 C 都要建立自己与 J 之间的保密密钥。A 可能需要密钥 KAJ,B 可能需要密钥 KBJ,C 可能需要密钥 KCJ。每对通信实体都需要自己的私有密钥。如果有 N 个节点, 每个节点都要和其他所有 N-1 个节点进行安全对话,总共大概会有 N2 个保密密钥: 这将是一个管理噩梦

公开密钥加密技术

公开密钥加密技术没有为每对主机使用单独的加密 / 解密密钥,而是使用了两个非对称密钥一个用来对主机报文编码,另一个用来对主机报文解码

RSA

所有公开密钥非对称加密系统所面临的共同挑战是,要确保即便有人拥有了下面所有的线索,也无法计算出保密的私有密钥:

  • 公开密钥 (是公有的,所有人都可以获得);
  • 一小片拦截下来的密文 (可通过对网络的嗅探获取);
  • 一条报文及与之相关的密文 (对任意一段文本运行加密器就可以得到)。

RSA算法 就是一个满足了所有这些条件的流行的公开密钥加密系统,它是在 MIT 发明的,后来由 RSA 数据安全公司将其商业化。即使有了公共密钥、任意一段明文、用公共密钥对明文编码之后得到的相关密文、RSA 算法自身,甚至 RSA 实现 的源代码,破解代码找到相应的私有密钥的难度仍相当于对一个极大的数进行质因数分解的困难程度,这种计算被认为是所有计算机科学中最难的问题之一。因此, 如果你发现了一种能够快速地将一个极大的数字分解为质因数的方法,就不仅能够入侵瑞士银行的账户系统,而且还可以获得图灵奖了。

混合加密系统和会话密钥

任何人只要知道了其公开密钥,就可以向一台公共服务器发送安全报文,所以非对称的公开密钥加密系统是很好用的。两个节点无须为了进行安全的通信而先交换私有密钥。

但公开密钥加密算法的计算可能会很。实际上它混合使用了对称和非对称策略。 比如,比较常见的做法是在两节点间通过便捷的公开密钥加密技术建立起安全通信, 然后再用那条安全的通道产生并发送临时的随机对称密钥,通过更快的对称加密技 术对其余的数据进行加密。(SSH和HTTPS都是这样的)

数字签名

除了加 / 解密报文之外,还可以用加密系统对报文进行签名(sign),以说明是谁编写的报文,同时证明报文未被篡改过。这种技术被称为数字签名(digital signing)

数字签名是附加在报文上的特殊加密校验码。数字签名通常是用 非对称公开密钥技术产生的。因为只有所有者才知道其私有密钥, 所以可以将作者的私有密钥当作一种“指纹”使用。

image

RSA 加密系统将解码函数 D 作为签名函数使用,是因为 D 已经将私有密钥作为输入使用了。注意, 解码函数只是一个函数,因此,可以将其用于任意的输入。同样,在 RSA 加密系统中,以任意顺序 应用 D 和 E 函数时,两者都会相互抵消。因此 E(D(stuff)) = stuff,就像 D(E(stuff)) = stuff 一样。

注意

私钥和公钥是一对,都可以加解密,配对使用。RSA 的原理,两个大质数(p,q)乘积(n)难以逆向求解,所以 pq 是对等的,公钥和私钥也是对等的。

  1. 私钥加密公钥解密,能证明“私钥拥有者” 的唯一身份,用于签名。
  2. 公钥加密私钥解密,确保发送的信息,只有有“私钥拥有者” 能够解密,(如果用私钥加密,传递数据,则会被公钥持有者(可能有很多持有者) 解密,失去对信息的保护)

数字证书

因特网上的“ID 卡”——数字证书。数字证书(通常被称作“certs”,有点像 certs 牌薄荷糖)中包含了由某个受信任组织担保的用户或公司的相关信息。

数字证书中还包含一组信息,所有这些信息都是由一个官方的 证书颁发机构(CA) 以数字方式签发的。

而且,数字证书通常还包括对象的公开密钥,以及对象和所用签名算法的描述性信息。任何人都可以创建一个数字证书,但并不是所有人都能够获得受人尊敬的签发 权,从而为证书信息担保,并用其私有密钥签发证书。典型的证书结构如图所示。

image

X.509 v3证书

不幸的是,数字证书没有单一的全球标准。就像不是所有印刷版 ID 卡都在同样的位 置包含了同样的信息一样,数字证书也有很多略有不同的形式。 不过好消息就是现 在使用的大多数证书都以一种标准格式—— X.509 v3,来存储它们的信息。X.509 v3 证书提供了一种标准的方式,将证书信息规范至一些可解析字段中。不同类型的证 书有不同的字段值,但大部分都遵循X.509 v3结构。

基于 X.509 证书的签名有好几种,(其中)包括 Web 服务器证书、客户端电子邮件 证书、软件代码签名证书和证书颁发机构证书。

用证书对服务器进行认证

通过 HTTPS 建立了一个安全 Web 事务之后,现代的浏览器都会自动获取所连接服 务器的数字证书。如果服务器没有证书,安全连接就会失败。

浏览器收到证书时会对签名颁发机构进行检查。如果这个机构是个很有权威的公共签名机构,浏览器可能已经知道其公开密钥了(浏览器会预先安装很多签名颁发机构的证书)。

如果对签名颁发机构一无所知,浏览器就无法确定是否应该信任这个签名颁发机构, 它通常会向用户显示一个对话框,看看他是否相信这个签名发布者。签名发布者可 能是本地的 IT 部门或软件厂商。

HTTPS

HTTPS 是最流行的 HTTP 安全形式。它是由网景公司首创的,所有主要的浏览器和 服务器都支持此协议。

使用 HTTPS 时,所有的 HTTP 请求和响应数据在发送到网络之前,都要进行加密。 HTTPS 在 HTTP 下面提供了一个传输级的密码安全层——可以使用 SSL,也可以使用其后继者—— 传输层安全(Transport Layer Security,TLS)。由于 SSL 和 TLS 非常类似,所以我们不太严格地用术语 SSL 来表示 SSL 和 TLS。

image

SSL/TLS

不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,带来了三大风险。

  • 窃听风险(eavesdropping):第三方可以获知通信内容。
  • 篡改风险(tampering):第三方可以修改通信内容。
  • 冒充风险(pretending):第三方可以冒充他人身份参与通信。

SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

  • 所有信息都是加密传播,第三方无法窃听。
  • 具有校验机制,一旦被篡改,通信双方会立刻发现。
  • 配备身份证书,防止身份被冒充。

SSL(Secure Socket Layer)是安全套接层TLS(Transport Layer Security)是传输层安全协议,建立在SSL3.0协议规范,是 SSL3.0 的后续版本。SSL 直到 3.0版本才大规模的部署和应用。 TLS 版本相比于 SSL 变化明显的是支持的加密算法不同。当前最新使用的是TLS1.2协议。1.3版本还在草案阶段。

image

HTTPS方案

现在,安全 HTTP 是可选的。请求一个客户端(比如 Web 浏览器)对某 Web 资源执行某事务时,它会去检查 URL 的方案:

  • 如果URL的方案为http,客户端就会打开一条到服务器端口80(默认情况下) 的连接,并向其发送老的 HTTP 命令。
  • 如果URL的方案为https,客户端就会打开一条到服务器端口443(默认情况下) 的连接,然后与服务器“握手”,以二进制格式与服务器交换一些 SSL 安全参数, 附上加密的 HTTP 命令。

SSL 是个二进制协议,与 HTTP 完全不同,其流量是承载在另一个端口上的(SSL 通常是由端口 443 承载的)。如果 SSL 和 HTTP 流量都从端口 80 到达,大部分 Web 服务器会将二进制 SSL 流量理解为错误的 HTTP 并关闭连接。将安全服务进一步整 合到 HTTP 层中去就无需使用多个目的端口了,在实际中这样不会引发严重的问题。

SSL握手

开始加密通信之前,客户端和服务器首先必须建立连接和交换参数,这个过程叫做握手(handshake)。假定客户端叫做爱丽丝,服务器叫做鲍勃,整个握手过程可以用下图说明。

image

握手阶段分成五步:

  1. 爱丽丝给出协议版本号、一个客户端生成的 随机数(Client random),以及客户端支持的加密方法。
  2. 鲍勃确认双方使用的加密方法,并给出数字证书、以及一个 服务器生成的随机数(Server random)
  3. 爱丽丝确认数字证书有效,然后生成一个新的 随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。
  4. 鲍勃使用自己的私钥,获取爱丽丝发来的随机数(即Premaster secret)。
  5. 爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成 对话密钥(session key),用来加密接下来的整个对话过程。

上面的五步,画成一张图,就是下面这样:

image

握手阶段有三点需要注意:

  1. 生成对话密钥一共需要三个随机数。
  2. 握手之后的对话使用 对话密钥(session key) 加密(对称加密),服务器的公钥和私钥只用于加密和解密 对话密钥(session key)(非对称加密),无其他作用。
  3. 服务器公钥放在服务器的数字证书之中。

DH算法的握手阶段

整个握手阶段都不加密(也没法加密),都是明文的。因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于 第三个随机数(Premaster secret)能不能被破解。

虽然理论上,只要服务器的公钥足够长(比如2048位),那么 Premaster secret 可以保证不被破解。但是为了足够安全,我们可以考虑把握手阶段的算法从默认的 RSA算法,改为 Diffie-Hellman算法(简称DH算法)

采用 DH算法 后,Premaster secret 不需要传递,双方只要交换各自的参数,就可以算出这个随机数。

image

上图中,第三步和第四步由传递 Premaster secret 变成了传递 DH算法 所需的参数,然后双方各自算出 Premaster secret。这样就提高了安全性。

服务器证书

SSL 支持双向认证,将服务器证书承载回客户端,再将客户端的证书回送给服务器。 而现在,浏览时并不经常使用客户端证书。大部分用户甚至都没有自己的客户端证书。服务器可以要求使用客户端证书,但实际中很少出现这种情况。

站点证书的有效性

SSL 自身不要求用户检查 Web 服务器证书,但大部分现代浏览器都会对证书进行简 单的完整性检查,并为用户提供进行进一步彻查的手段。网景公司提出的一种 Web 服务器证书有效性算法是大部分浏览器有效性验证技术的基础。验证步骤如下所述:

  • 日期检测 首先,浏览器检查证书的起始日期和结束日期,以确保证书仍然有效。如果证书 过期了,或者还未被激活,则证书有效性验证失败,浏览器显示一条错误信息。
  • 签名颁发者可信度检测 每个证书都是由某些 证书颁发机构(CA) 签发的,它们负责为服务器担保。证书有不同的等级,每种证书都要求不同级别的背景验证。比如,如果申请某个电 子商务服务器证书,通常需要提供一个营业的合法证明。
    任何人都可以生成证书,但有些 CA 是非常著名的组织,它们通过非常清晰的流 程来验证证书申请人的身份及商业行为的合法性。因此,浏览器会附带一个签名颁发机构的受信列表。如果浏览器收到了某未知(可能是恶意的)颁发机构签发的证书,那它通常会显示一条警告信息。
  • 签名检测 一旦判定签名授权是可信的,浏览器就要对签名使用签名颁发机构的公开密钥, 并将其与校验码进行比较,以查看证书的完整性。
  • 站点身份检测 为防止服务器复制其他人的证书,或拦截其他人的流量,大部分浏览器都会试着 去验证证书中的域名与它们所对话的服务器的域名是否匹配。服务器证书中通常 都包含一个域名,但有些 CA 会为一组或一群服务器创建一些包含了服务器名称 列表或通配域名的证书。如果主机名与证书中的标识符不匹配,面向用户的客户 端要么就去通知用户,要么就以表示证书不正确的差错报文来终止连接。

HTTPS客户端

SSL 是个复杂的二进制协议。除非你是密码专家,否则就不应该直接发送原始的 SSL 流量。幸运的是,借助一些商业或开源的库,编写 SSL 客户端和服务器并不十 分困难。

OpenSSL 是 SSL 和 TLS 最常见的开源实现。OpenSSL 项目由一些志愿者合作开发, 目标是开发一个强壮的、具有完备功能的商业级工具集,以实现 SSL 和 TLS 协议以 及一个全功能的通用加密库。可以从 http://www.openssl.org 上获得 OpenSSL 的相 关信息,并下载相应软件。

后记

强烈推荐一本书:HTTP 权威指南

参考


Pines_Cheng
6.5k 声望1.2k 粉丝

不挑食的程序员,关注前端四化建设。