cryptology

所有的加密算法都是公开的,而算法使用的“密钥”则必须保密。 由于 HTTPS、TLS 都运行在计算机上,所以“密钥”就是一长串的数字,但约定俗成的度量单位是“”(bit),而不是“字节”(byte)。 比如:

  • 密钥长度是 128,就是 16 字节的二进制串,

  • 密钥长度 1024,就是 128 字节的二进制串。

对称加密

“对称加密”是指加密和解密时使用的密钥都是同一个,是“对称”的。只要保证了密钥的安全,那整个通信过程就可以说具有了机密性。

symmetric encryption

TLS 里有非常多的对称加密算法可供选择,比如:

AES “高级加密标准”(Advanced Encryption Standard),密钥长度可以是 128、192 或 256。它是 DES 算法的替代者,安全强度很高,性能也很好,而且有的硬件还会做特殊优化,所以非常流行,是应用最广泛的对称加密算法。 ChaCha20 是 Google 设计的加密算法,密钥长度固定为 256 位,纯软件运行性能要超过 AES,曾经在移动客户端上比较流行,但 ARMv8 之后也加入了 AES 硬件优化,所以现在不再具有明显的优势,但仍然算得上是一个不错的算法。

加密分组模式

对称算法还有一个“分组模式”的概念,它可以让算法用固定长度的密钥加密任意长度的明文,把小秘密(即密钥)转化为大秘密(即密文)。

  • ECB、CBC、CFB、OFB (有安全漏洞,基本不用)

  • AEAD(Authenticated Encryption with Associated Data),最新的分组模式,在加密的同时增加了认证的功能,常用的是 GCM、CCM 和 Poly1305

将对称加密算法和分组模式组合起来,如 ChaCha20-Poly305

非对称加密

对称加密看上去好像完美地实现了机密性,但其中有一个很大的问题:如何把密钥安全地传递给对方,术语叫“密钥交换”。 所以,就出现了非对称加密(也叫公钥加密算法)。它有两个密钥,一个叫“公钥”(public key),一个叫“私钥”(private key),两个密钥是不同的,“不对称”。在非对称加密体系中,任何参与通信的一方都有两把密钥,一把是需要自己保存好的私钥(必须严格保密),一把则是对外公开的(任何人都能使用)、用于加密的公钥,也就是说和谁通信就要获取到谁的公钥。

asymmetric entryption

公钥和私钥有个特别的“单向”性,虽然都可以用来加密解密,但公钥加密后只能用私钥解密,反过来,私钥加密后也只能用公钥解密。 非对称加密可以解决“密钥交换”的问题。网站秘密保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密。而黑客因为没有私钥,所以就无法破解密文。 非对称加密算法的设计要比对称算法难得多,在 TLS 里只有很少的几种,比如 DH、DSARSA、ECC 等。 RSA 是最著名的,它的安全性基于“整数分解”的数学难题,使用两个超大素数的乘积作为生成密钥的材料,想要从公钥推算出私钥是非常困难的。随着计算机运算能力的提高,普遍认为密钥的推荐长度至少要 2048 位。 ECC(Elliptic Curve Cryptography)是非对称加密里的“后起之秀”,它基于“椭圆曲线离散对数”的数学难题,使用特定的曲线方程和基点生成公钥和私钥,子算法 ECDHE 用于密钥交换,ECDSA 用于数字签名。比起 RSA,ECC 在安全强度和性能上都有明显的优势。160 位的 ECC 相当于 1024 位的 RSA,而 224 位的 ECC 则相当于 2048 位的 RSA。因为密钥短,所以相应的计算量、消耗的内存和带宽也就少,加密解密的性能就上去了,对于现在的移动互联网非常有吸引力。

混合加密

虽然非对称加密没有“密钥交换”的问题,但因为是基于复杂的数学难题,运算速度很慢,即使是 ECC 也要比 AES 差上好几个数量级。如果仅用非对称加密,虽然保证了安全,但通信速度有如乌龟,实用性就变成了零。 把对称加密和非对称加密结合起来,两者互相取长补短,即能高效地加密解密,又能安全地密钥交换。 TLS 使用的混合加密方式:

  1. 在通信刚开始的时候使用非对称算法,比如 RSA、ECDHE,首先解决密钥交换的问题。

  2. 然后用随机数产生对称算法使用的“会话密钥”(session key),再用公钥加密。因为会话密钥很短,通常只有 16 字节或 32 字节,所以慢一点也无所谓。

  3. 对方拿到密文后用私钥解密,取出会话密钥。这样,双方就实现了对称密钥的安全交换,后续就不再使用非对称加密,全都使用对称加密。

摘要算法

实现完整性的手段主要是摘要算法(Digest Algorithm),也就是常说的散列函数、哈希函数。

把摘要算法近似地理解成一种特殊的压缩算法,它能够把任意长度的数据“压缩”成固定长度、而且独一无二的“摘要”字符串,就好像是给这段数据生成了一个数字“指纹”。 也可以把摘要算法理解成特殊的“单向”加密算法,它只有算法,没有密钥,加密后的数据无法解密,不能从摘要逆推出原文。

摘要算法实际上是把数据从一个“大空间”映射到了“小空间”,所以就存在“冲突”(collision,也叫碰撞)的可能性,可能会有两份不同的原文对应相同的摘要。好的摘要算法必须能够“抵抗冲突”,让这种可能性尽量地小。因为摘要算法对输入具有“单向性”和“雪崩效应”,输入的微小不同会导致输出的剧烈变化,所以也被 TLS 用来生成伪随机数(PRF,pseudo random function)。

  • MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1),是最常用的两个摘要算法,能够生成 16 字节和 20 字节长度的数字摘要。但安全强度低,在 TLS 里禁止使用。

  • 目前 TLS 推荐使用 SHA-2(系列摘要算法的统称),总共有 6 种,常用的有 SHA256SHA512,分别能够生成 32 字节、64 字节的摘要。

**摘要算法保证了“数字摘要”和原文是完全等价的。所以,只要在原文后附上它的摘要,就能够保证数据的完整性。**真正的完整性必须要建立在机密性之上,在混合加密系统里用会话密钥加密消息和摘要,这有个术语,叫哈希消息认证码(HMAC)。

数字签名

使用非对称加密中的私钥再加上摘要算法,就能够实现“数字签名”,同时实现“身份认证”和“不可否认”。 数字签名的原理,把公钥私钥的用法反过来,私钥加密、公钥解密。但因为非对称加密效率太低,所以私钥只加密原文的摘要,这样运算量就小的多,而且得到的数字签名也很小,方便保管和传输。

数字签名和公钥一样完全公开,但数字签名只有用私钥对应的公钥才能解开,拿到摘要后,再比对原文验证完整性,就可以像签署文件一样证明消息确实是你发的。

数字证书和 CA

非对称加密体系的公钥是对外公开的,这大大降低了密钥分发的复杂性。但直接分发公钥信息仍然可能存在安全隐患。比如 HTTPS 协议安全传输层连接建立的过程中,如何保证 HTTPS 服务端发送给客户端的公钥信息没有被篡改呢?也就是“公钥的信任”问题。其实 HTTPS 建立连接的过程并非直接传输公钥信息,而是使用携带公钥信息的数字证书来保证公钥信息的正确性和完整性。 数字证书,被称为互联网上的“身份证”,用于唯一标识网络上的一个域名地址或一台服务器主机。服务端将包含公钥信息的数字证书传输给客户端,客户端如何校验这个证书的真伪呢?可以用类似密钥交换的方法来解决公钥认证问题,用别的私钥来给公钥签名,找一个公认的可信第三方,让它作为“信任的起点,递归的终点”,构建起公钥的信任链。这个“第三方”就是 CA(Certificate Authority,证书认证机构),它具有极高的可信度,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。 CA 对公钥的签名认证也是有格式的,还要包含序列号用途颁发者有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成“数字证书”(Certificate)。在申请数字证书的时候需要向 CA 提交数字证书申请请求,这个请求以证书签名请求(Certificate Signing Request,CSR)文件的形式提供,可以通过 OpenSSL 基于申请者的私钥生成证书签名请求文件,这个 CSR 中包含证书申请人的信息,如国家邮箱域名公钥等信息。

ca

知名的 CA 全世界就那么几家,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,它们签发的证书分 DV、OV、EV 三种,区别在于可信程度。

  • DV 是最低的,只是域名级别的可信,背后是谁不知道。

  • EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份(在浏览器地址栏会显示出公司的名字,例如 Apple、GitHub 的网站)。

小一点的 CA 可以让大 CA 签名认证,但链条的最后,也就是 Root CA,就只能自己证明自己了,这个就叫“自签名证书”(Self-Signed Certificate)或者“根证书”(Root Certificate)。你必须相信,否则整个证书信任链就走不下去了。

有了证书体系,操作系统和浏览器都内置了各大 CA 的根证书,上网的时候只要服务器发过来它的证书,就可以验证证书里的签名,顺着证书链(Certificate Chain)一层层地验证,直到找到根证书,就能够确定证书是可信的,从而里面的公钥也是可信的。 证书体系(PKI,Public Key Infrastructure)虽然是目前整个网络世界的安全基础设施,但绝对的安全是不存在的,它也有弱点,还是关键的“信任”二字。

  1. CA 失误或者被欺骗,签发了错误的证书,虽然证书是真的,可它代表的网站却是假的。

  2. CA 被黑客攻陷,或者 CA 有恶意,因为它(即根证书)是信任的源头,整个信任链里的所有证书也就都不可信了。

所以,需要再给证书体系打上一些补丁。

  1. 针对第一种,开发出了 CRL(证书吊销列表,Certificate revocation list)和 OCSP(在线证书状态协议,Online Certificate Status Protocol),及时废止有问题的证书。

  2. 针对第二种,因为涉及的证书太多,就只能操作系统或者浏览器从根上“下狠手”了,撤销对 CA 的信任,列入“黑名单”,这样它颁发的所有证书就都会被认为是不安全的。

X509 证书规范

所有的公钥证书都需要符合 X509 数字证书基本规范。

证书编码格式

  1. DER:二进制格式

  2. PEM:ASCII 文本格式,在 DER 或其他二进制格式的基础上使用 Base64 编码为 ASCII 文本,以便在仅支持 ASCII 格式的环境中使用二进制的 DER 编码的数据。

-----BEGIN label 1-----
base64 string...
-----END label 1-----

-----BEGIN label 2-----
base64 string...
-----END label 2-----

其中 label 的数量没有限制,常见的 label 有:

  1. CERTIFICATE : 公钥证书文件 。

  2. CERTIFICATE REQUEST : CSR请求证书文件。

  3. PRIVATE KEY : 私钥文件。

  4. PUBLIC KEY : 公钥文件。

  5. X509 CRL : X509证书吊销列表文件。

证书结构

X509 证书由公钥用户标识符组成,此外还包括版本号证书序列号CA 标识符签名算法标识符签发者名称证书有效期等信息。

Certificate
 Version Number
 Serial Number
 Signature Algorithm ID
 Issuer Name
 Validity period
  Not Before
  Not After
 Subject name
 Subject Public Key Info
  Public Key Algorithm
  Subject Public Key
 Issuer Unique Identifier (optional)
 Subject Unique Identifier (optional)
 Extensions (optional)
 ...
 Certificate Signature Algorithm
 Certificate Signature

Last updated