TLS握手通信


RSA

阮一峰 RSA算法原理(一)

阮一峰 RSA算法原理(二)

一些数学知识

  • 质数

质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数

百度百科 质数

  • 互质关系

如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)

互质关系的结论:

1. 任意两个质数构成互质关系,比如13和61。

2. 一个数是质数,另一个数只要不是前者的倍数,两者就构成互质关系,比如3和10。

3. 如果两个数之中,较大的那个数是质数,则两者构成互质关系,比如97和57。

4. 1和任意一个自然数是都是互质关系,比如1和99。

5. p是大于1的整数,则p和p-1构成互质关系,比如57和56。

6. p是大于1的奇数,则p和p-2构成互质关系,比如17和15。
  • 欧拉函数

任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?

计算这个值的方法就叫做欧拉函数,以φ(n)表示。

分以下情况讨论

1. 如果n=1,则 φ(1) = 1 。因为1与任何数(包括自身)都构成互质关系。

2. 如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。

3. 如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则 φ(p^k) = p^k - p^(k-1) = p^k(1-1/p)。
例如:φ(8) = φ(2^3) = 2^3 - 2^2 = 8 - 4 = 4。

4. 如果n可以分解成两个互质的整数之积,n = p1 * p2,则 φ(n) = φ(p1p2) = φ(p1)φ(p2)

5. 任意一个大于1的正整数,都可以写成一系列质数的积。φ(n) = n(1-1/p1)(1-1/p2)...(1-1/pr)
  • 欧拉定理

如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立:a^φ(n) ≡ 1(mod n)

a的φ(n)次方被n除的余数为1

费马小定理:
假设正整数a与质数p互质,因为质数p的φ(p)等于p-1,则欧拉定理可以写成:a^(p-1) ≡ 1(mod p)

  • 模反元素

如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1

ab ≡ 1(mod n) b叫做a的模反元素

RSA算法

假设A与B通信

  1. A随机选择两个不相等的质数p和q

这里 p=61 q=53,在实际应用中,这两个质数越大就越难破解

  1. 计算p和q的乘积n

n = pq = 6153 = 3233

n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。
实际应用中,RSA密钥一般是1024位,重要场合则为2048位

  1. 计算n的欧拉函数φ(n)

φ(n) = (p-1)(q-1) = 60*52 = 3120

  1. 随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质

这里选择 17,实际应用中,常常选择65537

  1. 计算e对于φ(n)的模反元素d

ed ≡ 1 (mod φ(n)) 等价于 ed - 1 = kφ(n)

17d - 3120k = 1 (d,k)=(2753,15) d=2753

  1. 将n和e封装成公钥,n和d封装成私钥

n=3233,e=17,d=2753,所以公钥就是 (3233,17),私钥就是(3233, 2753)

这六个数字之中,公钥用到了两个(n和e),其余四个数字都是不公开的。其中最关键的是d,因为n和d组成了私钥,一旦d泄漏,就等于私钥泄漏

有无可能在已知n和e的情况下,推导出d?

ed≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。

φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。

n=pq。只有将n因数分解,才能算出p和q。

如果n可以被因数分解,d就可以算出,也就意味着私钥被破解

对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。

假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。

只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的

  • 加密和解密

假设A向B发送信息m,m必须是整数(字符串可以取ascii值或unicode值),且m必须小于n

m = 65

m^e ≡ c (mod n)

B的公钥是(n,e) (3233, 17)

65^17 ≡ 2790 (mod 3233)

c等于2790,于是A把2790发送给B

解密要用私钥(n,d) (3233, 2753)

B收到2790

cd ≡ m (mod n)

2790^2753 ≡ 65 (mod 3233)

因此加密前的原文就是65

TLS1.2

TLS 定义了四个核心子协议:

  • 握手协议 (handshake protocol)
  • 密钥规格变更协议 (change cipher spec protocol)
  • 应用数据协议 (application data protocol)
  • 警报协议 (alert protocol)

这里最主要、最复杂是握手协议,协商对称密码就是在该协议中完成的

握手协议

下图展示了 HTTPS 链接建立、TLS 握手协议里参数传递、证书验证、协商对称密钥的过程

握手协议TLS 协议中最复杂的一部分,在这个过程中双方会协商链接参数(TLS 版本号、随机数等)并完成身份验证。里面可能会存在几种情况:完整握手,对服务器进行身份验证、恢复之前的会话采用的简短握手、对客户端和服务器都进行身份验证握手,下文以完整握手为例

Client Hello

在一次新的握手协议中,客户端(浏览器)首先发出的一条消息是 Client Hello,告诉服务器我将给你传递这些数据:

  • Version:客户端支持的最佳协议版本号。
  • Random:客户端提供给服务器的随机数,在每次握手中都会重新生成,这个随机数用于后续生成密钥。
  • Session ID:会话 ID 在第一次链接时该字段是空的,表示客户端并不希望恢复某个已存在的会话。
  • Cipher Suites:客户端所支持的所有秘密套件,按优先级顺序排列。
Handshake Protocol: Client Hello 
  Handshake Type: Client Hello (1) 
  Length: 223 
  Version: TLS 1.2 (0x0303) 
  Random: b0fcb3aca27c6de8b0e4f146b92d33f24e6a671e62f8f6f669aabbfc19bb4326 
  Session ID Length: 0 
  Cipher Suites Length: 92 
  Cipher Suites (46 suites) 
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) 
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) 
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028) 
    ...

Server Hello

Server Hello 是服务器在收到客户端 Client Hello 之后的一个回应,告诉客户端服务器的协议版本、服务器也会给出一个随机数 Random 用于后续生成密钥,Cipher Suite 是从客户端 Client Hello 消息的 Cipher Suites 里选择的一个密码套件

Handshake Protocol: Server Hello 
    Handshake Type: Server Hello (2) 
    Length: 89 
    Version: TLS 1.2 (0x0303) 
    Random: 616d836f609800aaa1713462f61d50cc6472c45b54c0ac58dd52b9db4d555f6f 
    Session ID Length: 32 
    Session ID: 279fb99351526e29a4ce41af4cbff5575933e5c45dff7a2016a16cdf414f22c2 
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) 

解密码套件构成

Certificate(发送服务器证书信息到客户端)

证书信息,典型的 Certificate 消息用于携带服务器 X.509 证书链,一个接一个组合而成,主证书第一个,之后中间证书和根证书,服务器的公钥也包含在证书信息中

Handshake Protocol: Certificate 
    Handshake Type: Certificate (11) 
    Length: 2781 
    Certificates Length: 2778 
    Certificates (2778 bytes) 
        Certificate Length: 1407 
        Certificate: 3082057b30820463a0030201020210040f1f824b17ca53814dc5c6f4c6a0a8300d06092a… (id-at-commonName=*.imooc.com) 
        Certificate Length: 1365 
        Certificate: 3082055130820439a003020102021007983603ade39908219ca00c27bc8a6c300d06092a… (id-at-commonName=RapidSSL TLS DV RSA Mixed SHA256 2020 CA-1,id-at-organizationName=DigiCert Inc,id-at-countryName=US)

Server Key Exchange(密钥交换)

Server Key Exchange 消息是携带密钥交换算法需要的额外数据,目的是计算主密钥需要的另一个值:预主密钥(pre_master_secret)。

不同的算法套件对应的消息内容也是不同的,下面 EC Diffie-Hellman(简称 ECDHE)就是密钥交换算法,这个对应 Server Hello 消息中选择的密码套件 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 中的 ECDHE

下面 Server Params 中的 Curve Type 表示曲线类型,本次选中的椭圆曲线名称为 named_curve:secp256r1,再确定基点 G,此时还会选择生成一个随机数做为服务端椭圆曲线的私钥,存放到本地,再根据基点 G 和椭圆曲线的私钥计算出椭圆曲线公钥(这里的椭圆曲线公/私钥都是临时的,只对本次链接生效),名字为 Pubkey 传递给客户端。

为了确保椭圆曲线公钥信息不被篡改,将 Server Params 与客户端和服务器随机值连在一起使用私钥签名,客户端从证书中获得服务器的公钥,就可验证是否来自服务器。客户端和服务器的随机值对于一次握手是唯一的,这也意味着攻击者无法重复利用该签名。

Handshake Protocol: Server Key Exchange 
    Handshake Type: Server Key Exchange (12) 
    Length: 329 
    EC Diffie-Hellman Server Params 
        Curve Type: named_curve (0x03) 
        Named Curve: secp256r1 (0x0017) 
        Pubkey Length: 65 
        Pubkey: 049c1c4eaa2ab8ae7b54482efc5d07e2b191174d804d660be07ded253c86f9bc5cd24f34… 
        Signature Algorithm: rsa_pkcs1_sha512 (0x0601) 
            Signature Hash Algorithm Hash: SHA512 (6) 
            Signature Hash Algorithm Signature: RSA (1) 
        Signature Length: 256 
        Signature: 5b9b1a750f0168f0a57852b4a77c14c351c5b97d7eb4a470fa8e3cf9e385cf7ac16f056f...

不同的密钥交换算法,生成预主密钥的方式也不同,我们这里的示例以 ECDHE 为主,还有一种密钥交换算法是 RSA,它的密钥交换过程很简单,由客户端生成预主密钥,为 46 字节的随机数,使用服务器的公钥加密,经过Client Key Exchange 消息发送到服务端,服务端再用私钥就可解密出这个预主密钥。

基于 RSA 的密钥交换算法被认为存在严重的漏洞威胁,任何能够接触到私钥的人(例如,由于政治、贿赂、强行进入等)都可恢复预主密钥,进而构建相同的主密钥,最终密钥泄漏就可解密之前记录的所有流量了。这种密钥交换算法正在被支持前向保密保密的其它算法替代,例如,我们示例中的 ECDHE 算法在密钥交换时,每个链接使用的主密钥相互独立,如果出现问题也只是影响到当前会话,不能用于追溯解密任何其它的流量。

Server Hello Done

Server Hello Done 表示服务器已将握手消息需要的数据都发送完毕。之后就是等待客户端的回应。

Handshake Protocol: Server Hello Done 
    Handshake Type: Server Hello Done (14) 
    Length: 0 

Client Key Exchange(客户端发送给服务器的密钥交换信息)

Client Key Exchange 的消息也是携带密钥交换需要的额外数据,不过这一次是客户端发送给服务端的,Client Params 里面提供了客户端生成的临时椭圆曲线公钥信息。

Handshake Protocol: Client Key Exchange 
    Handshake Type: Client Key Exchange (16) 
    Length: 66 
    EC Diffie-Hellman Client Params 
        Pubkey Length: 65 
        Pubkey: 04c64110c2838d112d8fbc8a85a2c2b3b596e70d6ff9198330801df93ce9737432eeabe6...
  • 客户端验证证书和计算密钥
    现在一次 TCP 往返结束了,客户端拿到了服务器的证书、Server RandomServer Params,现在客户端需要验证证书合法性和计算一些加密信息。
  • 验证服务器发来的证书合法性
    客户端收到服务器的响应信息,验证证书的合法性,如果证书校验通过继续往下走。
  • 计算预主密钥(pre_master_secret)
    上面也提了,在 Server Key Exchange 消息中,服务器对 Server Params 用私钥做了签名,客户端要从证书中获得服务器公钥,验证参数是否来自期望的服务器,这也是身份验证。

身份验证成功之后,得到 Server Params 参数,而 Server Params 参数里包含了 “服务器密钥交换消息” 中生成的临时公钥、secp256r1 椭圆曲线算法,现在客户端使用 secp256r1 算法用这个临时公钥和客户端自己生成的临时私钥相乘计算出预主密钥(pre_master_secret)。

  • 计算主密钥(master_secret)
    现在客户端手里已经有了 Client RandomServer RandomPremaster Secret 三个随机参数,调用 PRF 伪随机函数函数生成 48 字节(384 位)主密钥。
    master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)

  • 构建会话密钥
    上面的主密钥并不是最终的会话密钥,最终的会话密钥使用 PRF 伪随机函数传入主密钥、客户端随机数、服务端随机数生成。

key_block = PRF(master_secret, "key expansion", server_random + client_random)

这个最终的会话密钥包括:对称加密密钥(symmetric key)、消息认证码密钥(mac key)、初始化项量(iv key,只在必要时生成)。

客户端Change Cipher Spec

Change Cipher Spec 消息表示客户端已生成加密密钥,并切换到加密模式。

TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec 
    Content Type: Change Cipher Spec (20) 
    Version: TLS 1.2 (0x0303) 
    Length: 1 
    Change Cipher Spec Message 

注意:Change Cipher Spec 不属于握手协议,它是另一种密钥规格变更协议。

客户端Encrypted Handshake Message

这个是将之前所有的握手数据做一个摘要,再用最后协商好的对称加密算法对数据做加密,通过 Encrypted Handshake Message 消息发送到服务器进行校验,这个对称加密密钥是否成功。

TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message 
    Content Type: Handshake (22) 
    Version: TLS 1.2 (0x0303) 
    Length: 60 
    Handshake Protocol: Encrypted Handshake Message 
  • 服务器计算密钥

服务器在收到客户端 Client Key Exchange 消息后,这时可以拿到 Client RandomServer RandomClient Params,先计算出预主密钥后,再分别计算出主密钥和最终的会话密钥,这块可参考客户端计算密钥一样的。

服务端Change Cipher Spec

服务器发出 Change Cipher Spec 消息告诉客户端,服务端已生成密钥,请求客户端切换加密模式。

TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec 
    Content Type: Change Cipher Spec (20) 
    Version: TLS 1.2 (0x0303) 
    Length: 1 

服务端Encrypted Handshake Message

Encrypted Handshake Message 这条消息也是服务器对握手的所有数据用协商好的对称加密算法加密,供客户端校验。

如果对抓取后的报文做解密,这里看到的是 Finished 消息。

TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message 
    Content Type: Handshake (22) 
    Version: TLS 1.2 (0x0303) 
    Length: 40 
    Handshake Protocol: Encrypted Handshake Message 

应用数据协议

整个握手过程完毕之后,我们会看到应用数据协议 Application Data Protocol: http2,之后我们的客户端/服务端建立一个安全通信隧道,就可以发送应用程序数据了。

TLSv1.2 Record Layer: Application Data Protocol: http2 
    Content Type: Application Data (23) 
    Version: TLS 1.2 (0x0303) 
    Length: 101 
    Encrypted Application Data: 1303136ee3f0e6daf0cb0e82d07fcca423c9cb2a26b29e332cdc604397f43c377df9805e… 
    [Application Data Protocol: http2] 

文章作者: 江湖义气
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 江湖义气 !
  目录