带你看不同的https

前言

https并非一个协议,一般来讲,若是咱们说使用了https,意思是说,咱们在http上使用了tls协议。 因而,咱们能够更进一步的理解到:c++

  1. tls实际上不是特意为http服务的一个协议。
  2. tls是应用层中比较下层的协议
  3. tls能够应用于其余应用层协议,好比邮件

为何我比较强调这种层次概念,由于知识的边界和概念须要划分清晰,在遇到问题,才能知道突破口是在哪。我看大部分关于https文章会一上来就讲一些握手过程,或者密码学原理相关的内容,或者有些文章甚至没有关于协议本书的说明,而是仅仅讲抽象握手过程。我想,这样的理解并无很结构化的去讲好这样一个东西,因此这也是我写这篇文章的初衷。git

为了容易理解,我会把比较结构性内容放在前面,把细节内容放在后面。github

宏观看tls

上面一直在讲tls,对于事先没有了解过https的人来讲,可能有点迷糊——tls是什么? 了解过tls的人,应该也知道ssl协议。web

  • TLS:全称是Transport Layer Security协议,意思就是传输层安全协议
  • SSL:全称是Secure Sockets Layer协议,意思是安全套接层协议

从字面意思上来看,这两个东西差很少,实际上,这两个东西也能够认为是同样的概念。tls就是ssl升级以后的版本,在早期时候(1994),为了解决http自己的安全问题,网景公司建立了ssl协议应用于http协议,后来将ssl统一,应用于更普遍的应用层协议,进一步标准化ssl协议,也就是tls协议。算法

能够把tls当成一层协议看待,那么其于http的关系相似于:数组

为什么须要tls

上面提到,为了解决http存在的安全问题,因此引入tls协议。咱们天然会有这样的疑问,是什么样的安全问题,须要在协议上去作文章。浏览器

先总结这样三个问题:安全

  1. 数据隐私问题
  2. 数据被篡改问题
  3. 身份认证问题

数据隐私:http协议是明文传输,也就是说若是中间人劫持请求,很容易理解到http协议传输内容的含义。有人可能会问:那咱们平时经过加密传输不就能够解决了吗,为何须要在协议中大动干戈。这里就须要点密码学的常识,若是仅仅是简单的加密数据,咱们有三种可选密码方案,对称加密,非对称加密,单向散列或者mac算法,无论是对称加密和非对称加密,这意味着双方都须要有解密用的钥,对称加密用的是同一个密钥,非对称须要各有一把相对的钥匙。对于web这样面向客户端的传输,在客户端植入密钥明显是不现实的行为,因此可选方案中,密钥怎么安全传输变成了另外一个问题,也是tls协议握手协议解决的问题。至于不可逆的加密,好比登陆密码自己,对于中间人攻击,其实他并不须要知道你自己数据是什么,这样看似把数据隐私化,实际上并无达到安全效果。bash

数据被篡改:若是http协议无法防止被篡改。虽然有消息验证码,数字签名能保证数据完整。可是单纯一个密码技术依然很难防止中间人攻击服务器

身份认证问题:http是无状态协议,因此验证服务端身份是一件重要事情,证书认证也是https安全传输的一环

http确实存在这样一些安全问题,虽然对使用者而言,确实有不少方法去预防安全问题,可是经过分析能够发现,无法用简单的方式,经过单一的一个种密码学算法就能解决这些问题,通常来讲,会组合各类密码学算法,这是一个繁琐的工做,因此tls也是将这些繁琐的问题,统一成一个解决方案。

tls协议结构

tls是介于应用层协议和tcp协议纸之间的协议,tls协议能够分红两层协议:

  1. 握手协议(TLS Handshaking Protocols)
  2. 记录层协议(TLS Record Protocol)

结构如图:

握手协议能够分红四个子协议: 结构如图:

注:在tls 1.2版本以前,没有heartbeat心跳协议,而是change cipher spec protocol密码切换协议。

记录层协议是接近tcp协议的底层协议,用来将握手协议定义消息封装和下层协议通信。

握手子协议

握手协议能够说是tls中最重要的子协议,由于它的职责就是协商出一种合适的 密码套件 。上面也提到,解决一个安全问题不止一种加密算法,密码套件正是一组各类不一样功能算法的集合。通常须要两个来回协商完成。

握手协议中以消息为单位,消息格式如图:

一个消息分红是三个部分:

  1. 消息长度:占用三个字节,用于定义消息最终长度大小
  2. 消息类型:占用一个字节,tls握手协议中有不一样的消息类型,每一个消息类型会带不一样的数据。
  3. 消息内容:大于一个字节,这是消息的主体内容

tls协议有十种不一样的消息类型,分别是:

  1. hello_request: 0x00
  2. client_hello: 0x01
  3. server_hello: 0x02
  4. certificate: 0x0b
  5. server_key_exchange: 0x0c
  6. certificate_request: 0x0d
  7. servert_done: 0x0e
  8. certificate_verify:0x0f
  9. client_key_exchange:0x10
  10. finished: 0x14

握手过程

握手过程通常是两个来回,主要用于交换不一样的信息。tls1.2版本的握手过程,大致能够如图这样抽象表示:

能够看到,在通过两个来回以后,客户端和服务端就正式进入数据传输。在握手端来回中,不难发现,一个请求可能会带好几个握手协议不一样的消息类型。这是由于,虽然握手协议会把不一样消息交给记录层协议,可是记录层协议通常会把几个类型封装成一个数据块发送。

图中的*标记表示该消息会根据不一样的密码套件作调整,[]标记表示该协议并非握手协议定义的内容,可是也会在握手过程当中进行。颜色较浅部分属于须要一个集合,绑定发送,这是双向认证须要的环节。

接下来,就细看每个消息的含义把

Client Hello消息

上面流程图中,客户端首先会发起一个消息,这个消息结构以下:

struct {
        ProtocolVersion client_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suites<2..2^16-2>;
        CompressionMethod compression_methods<1..2^8-1>;
        select (extensions_present) {
            case false:
                struct {};
            case true:
                Extension extensions<0..2^16-1>;
        };
} ClientHello; 
复制代码

该数据定义了6个key:

  1. client_version:表示支持的最高版本号
  2. random:客户端生出的随机数,这里你能够先记下,finished消息中用prf算法生产主密钥和密钥块会用到,生成预备主密钥也会用到,避免重放攻击。
  3. session_id:这个是会话重启相关的,创建过https链接的客户端能够保存服务器给的id,若是这个值存在,则会走会话重启的过程,而不是像项目那样完整的流程
  4. cipher_suites: 客户端支持的密码套件
  5. compresson_methods: 压缩算法,通常不会启用压缩算法
  6. extensions: 支持的扩展内容

因此说,消息并非很复杂。

server_hello

服务端的hello信息和客户端同样的结构

struct {
        ProtocolVersion server_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suite;
        CompressionMethod compression_method;
        select (extensions_present) {
            case false:
                struct {};
            case true:
                Extension extensions<0..2^16-1>;
        };
} ServerHello;
复制代码

具体就不重复描述了。

server certificate消息

这个消息是和上面的hello在一个请求的,能够看到,握手协议发送完server_hello状况之后就会发送certificate消息。可是因为,一些密码套件如DH_anon和DCDH_anon,不会发送该证书,因此该消息是可选的,可是大部分状况,都会用到证书信息。

该消息主要承载证书信息,证书是作身份验证的,该消息结构以下:

opaque ASN.1Cert<1..2^24-1>;

    struct {
        ASN.1Cert certificate_list<0..2^24-1>;
    } Certificate;
复制代码

能够看到只有一个certificate_list数组,该数组发送的是证书链,用于证书认证。 关于证书细节留到后面去讲述。

server_key_exchange消息

若是certificate消息里的证书信息不足以知足协商加密算法信息要求,会额外发送一个server_key_exchange信息做为补充。有6种密码套件是须要这个消息来发送的,以下:

DHE_DSS
DHE_RSA
ECDHE_ECDSA
ECDHE_RSA
------------------------
// 无证书
DH_anon
ECDH_anon
复制代码

分割线以前的套件因为使用的临时的 DH/ECDH 密钥协商算法,证书中是不包含这些动态的 DH 信息(DH 参数和 DH 公钥),因此发送完证书信息以后会追加这个消息对DH信息作补充

分割线下面的两种套件,属于匿名协商,没有证书信息,因此不会有certificate消息,可是因为须要发送额外的静态DH信息,因此会在这个消息里追加发送。

对于不一样公钥密码算法细节就不在这里讨论。

certificate_request消息

能够看到,服务器端可能会发送一个certificate_request消息。该消息是可选的,同时是灰色,我用灰色表示,为了说明该消息和其余灰色信息的关系,同时,通常也不会出现。可是在双向认证场景中,因为须要客户端也提供证书,因此服务端会发送这样信息,要求客户端也须要认证证书。

server_hello_done消息

上面流程图,在发送完sertificate和exchange信息以后,服务端会紧接一个server_hello_done类型消息做为结束。以后server会等待客户端后续的工做。该消息结构十分简单:

struct { } ServerHelloDone;
复制代码

client_certificate消息

对于客户端的certificate消息,该消息表示,若是在收到服务端发送的消息里,包含certificate_request消息,则客户端会根据自身条件发送证书信息。若是没有客户端没有合适的证书信息,会发送一个空数组。

client_key_exchange消息

该消息不管如何都会发送,这个消息最大的做用是传递pre_master_key,也就是预备主密钥,除了预备主密钥,若是客户端须要发送上面的certificate消息,还会对类型DH算法密钥作补充信息。可是无论怎么,生成pre_master_key是最重要对事,生成对pre_master_key是用于生成master_key的重要前提,生成master_key会在双方拿到pre_master_key以后,在生成master_key以后,便会发送[ChangeCipherSpec]消息,转换状态。这意味着握手过程进入能够加密阶段。

其含义能够参考上面服务端的server_key_exchange

[ChangeCipherSpec]协议

对于1.2版本的,在握手消息中,会涉及到协议状态转换,在1.3版本以后,该协议不在存在,可是为了向下兼容,握手中可能还会有。该协议是用于改变协议状态。

能够理解为,在上述的握手过程当中,收到该协议消息的端,状态都为:

pending read status 待读状态
    pending write status 待写状态
复制代码

在接收到该信息以后,端状态修改成:

current read status 可读状态
    current write status 可写状态
复制代码

该消息表示,在握手过程当中,当进入可读可写状态时,表示对端将进入加密阶段,这也意味着,握手环节已经基本完成,具有加密传输的条件。

finished消息

在双方发送完,会对握手中的重要信息进行验证,验证双方会发送本身的校验信息,消息结构以下:

struct {
        opaque verify_data[verify_data_length];
    } Finished;

    verify_data = 
        PRF(master_secret, finished_label, Hash(handshake_messages))
        [0..verify_data_length-1];
复制代码

该消息的意义在于:握手过程当中全部的子消息都没有加密和完整性保护,消息很容易篡改。为了不握手期间存在消息被篡改的状况,因此 Client 和 Server 都须要校验一下对方的 Finished 子消息。

完成finish消息以后,最后双方的通信会以master_key做为对称加密信息的主密钥。

以上,是tls1.2定义的握手内容,固然,还有不少细节没有研究,好比握手中涉及到的随机数,session_id的做用。不过大致的过程已经讲完了,后续慢慢补充一些细节。细节部分则须要一点密码学常识。

细看tls

若是想更深刻理解,则须要了解部分密码学相关内容,像上面提到的对称加密,非对称加密,随机数,均属于密码学的内容。

密码学常识

这里简单的介绍几个密码学概念,他们分别是:

  • 随机数
  • 单向散列函数(hash算法)
  • 消息验证码(mac算法)
  • 数字签名
  • 对称加密算法
  • 公钥加密算法

随机数算法

随机数做为重要的密码学单元,在密码学中普遍运用到,密码学单元是指:在其余算法中,随机数会产当一个因子的做用。好比生成对称密码和消息验证码。

随机数有三个重要的特性:

  • 随机性
  • 不可预测性
  • 不可从新性

三个特性关系能够表示为:

通常咱们把具备不可重现性的随机数叫真随机数,把具备不可预知的随机数叫强伪随机数,把具备随机性的随机数叫伪随机数

只有至少具备强伪随机数特性的随机数算法才能用于密码学。

单向散列函数

单向散列函数即one-way hash function。就是咱们常说的hash算法,对于用过md5算法的小伙伴应该不陌生。可是须要注意的是,单向散列函数的做用是保证消息的完整性。

单向散列函数具备这样的特色:

  • 不一样消息能达到固定长度的散列值
  • 抗碰撞,不一样消息获得的散列值不一样
  • 单向性,没法经过散列值得到原值
  • 高效

关于强抗碰撞和弱抗碰撞:

  • 强抗碰撞:对于任意散列值,找到相同消息的困难度
  • 弱抗碰撞:对于一个消息和其散列值,找到另一条不一样消息,和该散列值相同的困难度

经过特色咱们能够很容易的知道,单向散列能够用来比较消息的完整性。由于其足够小,足够快,用来校验不一样内容是否完整颇有用。

缺陷: 固然,这也暴露了,单向散列函数的局限性,就是没法防止被篡改,也没法验证信息的来源。没法防止篡改,是由于攻击者很容易的能够将不一样消息生成散列而且假装。好比中间人攻击。

常见散列算法:

  • MD5
  • SHA(secure hash algorithms),SHA-1,SHA-2(256,512,224,384),SHA-3(256,5`1,224,384)

对称加密算法

加密和解密都是用同一个密钥的加密算法,叫对称加密算法。对称加密算法是在传输数据双方持有一个相同的密钥,这种算法须要解决最大问题就是密钥的传输问题。 常见的对称加密有AES,DES。

公钥密码算法

公钥密码算法就是非对称加密算法,因为前面提到的对称加密算法的局限性,因此很天然而然的联想到,是否有一种传输数据双方使用不一样的密钥的算法。公钥密码算法的解密模型也很简单:

这里须要提下,公钥加密算法确实有更多可能性,可是我发现不少人有一些理解误区:

  1. 就是非对称就比对称更优秀,或者说,更机密。我想这是不正确的,由于就机密性来讲,取决于算法的密钥长度,同时非对称加密的性能不好,很难说一样机密性,非对称加密能作的比对称加密好。
  2. 认为非对称加密能够解决中间人攻击,非对称加密是解决不了中间人攻击的,由于中间人只要劫持了公钥,就能神不知鬼不觉的替换掉原来公钥,用本身伪造的伪公钥和伪密钥瞒天过海。
  3. 非对称算法在于它有使得传输过程当中有更多可选方案,好比数字签名和密钥协商中,都会用到非对称加密的非对称密钥,这才是公钥算法的重要意义。

目前最经常使用的公钥加密算法是RSA算法和ECC算法。

关于这两个算法细节,这里就不花时间描述了。ECC算法相对密钥比RSA算法短,同时效率和机密性比RSA高。

公钥加密算法的缺点就是执行效率太慢。

消息验证码(MAC)

消息验证码(message authentication code)是一种确认完整性,并认证的技术。简称MAC算法。

关于mac算法的理解须要结合以前的单向散列算法来看。咱们知道,单向散列算法能够保证消息的完整性。

先看看二者的对比。

MAC算法相对单向散列算法而言,多了一个共享密钥才能生成MAC值。这样很容易联想到,如何在网络中传输密钥是MAC算法的一个问题,这个问题和对称加密算法中的问题同样。

那MAC算法相对HASH算法解决了什么问题呢,咱们知道,若是中间人攻击了HASH算法生成的HASH值。因为HASH算法和MAC算法不关注消息的机密性,因此中间人能够对消息进行修改,同时用HASH算法从新生成HASH值从而达到篡改数据的效果。虽然MAC算法的密钥若是被中间人劫持,同样会遭受一样的问题,可是咱们若是有一种方案,可以保证Mac密钥不被劫持,就能防止中间人攻击,这就是Mac算法存在的意义。

因此,在MAC算法密钥安全的状况下。mac能保证消息完整,同时可以认证,认证的含义是只有持有密钥的人能够生成mac值。

那mac算法的有没有其局限性,除了说mac算法自己不是为了机密性而生以外,mac算法依然没法反正抵赖问题。如何理解抵赖?

咱们假设做为第三者角度而言,用mac算法认证的消息虽然是完整的,可是若是有一天有一方对这个消息不认可,因为发送方和接收方都有密钥生成mac值,因此咱们没法单从mac值中判断说,这个消息是谁生成的。这就须要用到后面介绍的数字签名技术。

数字签名

数字签名,是一种可以认证消息来源,保证数据准确性,防止篡改的技术。关于数字签名,依然须要和单向散列算法和MAC算法作一个对比。

单向散列算法能够保证消息完整准确性,含义在于只能保证在信息传输中不存在异常。可是没法防止如中间人攻击之类的,篡改数据,同时也没法对消息进行认证。

Mac算法能够保证消息准确同时,由于有一个共享密钥,因此只要保证密钥安全,就能反正数据被篡改,可是因为数据传输双方对密钥是相同的,没法经过第三方得知消息是谁发送的,即不能防止抵赖。

数字签名在借助公钥密码算法的密钥不一样的特色,实现了消息认证的机制。原理很简单,就是生成消息的一方经过密钥生成签名,接受消息的一方,能够经过公钥解开消息而后认证消息的正确性。为何数字签名能够反正抵赖,由于只有持有公钥的人才能验证消息,只有持有密钥的人才能生成签名。这样双方都没法抵赖,同时也能保证消息的完整性,一样能反正篡改。

关于数字签名的简单流程:

因为签名提到非对称加密算法的性能不好,因此上面流程的比对,性能天然也很差,缘由是消息的长度可能很长,同时,对于rsa算法而言,须要加密的消息越长,其密钥公钥长度也要越长。聪明同窗很容易联想到,使用单向散列算法可使消息生成简单的hash值,同时,单向散列算法性能也很好。这样就解决了这个问题,因此,通常的签名算法流程优化以下:

补充:这里作一点补充,在数字签名里,非对称加密算法,经过密钥加密生成签名,经过公钥解密验证签名。而在使用rsa作加密操做时,通常会用公钥加密数据传输,而不会经过密钥加密数据传输。缘由是由于,公钥是公开对,任何人均可能得到,若是经过密钥加密数据,任何人均可能拿到公钥而后解密。

密钥协商算法

回顾前面的技术,消息认证码(MAC),对称加密,以及用到这些技术的地方,都要强调密钥重要性。可是在网络传输过程当中,为了双方都能持有相同密钥。咱们会思考如何传输密钥。

这个就是密钥如何配送的问题,关于解决密钥配送问题,有如下几种方式:

  1. 事先共享密钥:好比直接在浏览器和服务器里面事先内置须要的密钥,这显然是不太现实的作法
  2. 密钥中心分配:创建一个专门管理密钥的中心,由它来分配,可是这样存储量和维护成本就很大。
  3. 基于非对称算法实现:由拿到公钥的一端负责生成主密钥,而且用公钥加密发送主密钥。这样就能防止泄密,由于只有密钥持有者能够解密主密钥。可是单纯的这种方式会由中间人攻击问题,要配合证书认证公钥合法。
  4. 基于DH算法实现:DH算法会在两端都保留各类私有信息,而且经过传输部分公共信息,两边经过公共信息生成主密钥。而即便公共信息被拿到,第三方也没法经过公共信息生成主密钥,从而达到传输密钥都效果。

这里只讲下DH的简单过程,关于用非对称算法传输密钥很好理解,就再也不这里描述:

在上面流程中,G,P,G^AmodP和G^BmodP是四个公开的数字。可是要经过这四个数字算出A,B数是很难的。

生成元G的意义: G的计算是比较复杂的,对于G^XmodP (1 < x < p 内的整数)的全部值都不一样时,G就是P的元。而A,B随机取0到P之间的全部整数。这样,A,B有足够多的选择,同时计算有足够多的可能性。

DH算法能防止中间人攻击吗?不能,中间人依然能够经过中间篡改伪造A和B达到中间人攻击的效果。

DH算法能够和RSA这类非对称算法作签名,从而抵御中间人攻击。 DH算法和ECC算法进行结合升级新的密钥写书协商算法便是ECDH。

证书认证

证书认证的意义是给公钥加上签名,RSA算法在作密钥协商,或者数据加密时。均可能被中间人给劫持伪造。可是若是有一种技术可以识别,公钥有没有被伪造,那就可以防止中间人攻击。

这样咱们很容易联想到咱们以前谈论到数字签名技术,由于数字签名不只能保证数据不被篡改,还能防止抵赖。可是,聪明的你应该很容易联想到,数字签名也是要用公钥算法作签名。怎么保证签名都机构都公钥安全又是另外一个问题。

因而,咱们想象若是有这样一个机构,他用本身都私钥给客户都公钥进行签名。而后这样都机构公开本身都公钥,由于中间人没有机构都私钥,这样中间人没法伪造签名。就没法伪造客户都公钥了。

这样又有新都问题,咱们凭什么想象这个机构。事实到这里,咱们确实只能想象这个机构,别无他法。这个机构就是CA机构。

因此,证书其实就是给客户的公钥和信息加上一个数字签名,有了这个数字签名。就无法伪造公钥。

可是,新的问题是,在作数字签名认证时,咱们须要用到CA机构的公钥进行认证,若是经过网络的方式去获取公钥,这个公钥有没可能被攻击者劫持,是有可能的。因此比较好的作法是把CA机构的信息内置到操做系统中。不经过网络获取。可是若是CA机构的数量过于庞大,怎么办。因此实际上,CA机构分为 CA根机构CA中间机构。在操做系统中只要内置根证书就好了。经过根证书给下一级机构签名,而中间机构经过网络传输也没有关系,只要更证书是安全的,就能经过签名发现中间机构是否被伪造。这样就解决了传输问题。

再看握手过程

经过前面关于密码学的了解。这里能够更深刻的去思考握手过程。 此次咱们先明确握手的目的,看上图中的过程,握手过程最终是为了数据传输服务的。也就是后续数据传输中的application data过程。

记录层协议

数据传输是在记录层协议中的定义的,关于记录层协议,主要是完成一下的功能:

  1. 装载由上层协议分发下来的消息
  2. 有选择的压缩数据
  3. 对数据进行加密,解密和mac认证

因此,在握手结束后,通常会采用对称加密算法加密数据,而后作mac认证。握手过程为了给传输数据提供会话密钥。而tls 1.2版本在PRF函数中使用加密基元是 SHA256 算法。

在握手过程当中,最终会生成三个密钥分别是:

  1. 预备主密钥(pre_master_key)
  2. 主密钥(master_key)
  3. 会话密钥(session_master_key)

在前面的握手过程当中,咱们看到第一个来回,协商了主要的密码套件,而且客户端和服务端交换了以一对随机数,分别是client_random,和server_random。忘记的回去看hello消息的结构。

上面的主密钥是经过PRF函数和随机数计算得来:

PRF(pre_master_secret, "master secret",
    ClientHello.random + ServerHello.random)
    [0..47];
复制代码

计算时间前面提到过,是在校验完证书以后。

以rsa协商为例,预备主密钥,则由客户端随机生成,而后经过公钥发送,也就是client_key_exchange的那个消息中生成。

这里能够根据密码学原理提出几个解答:

  1. 为何是由客户端生成预备主密钥中,经过公钥加密发送。 答:在前面提到的rsa密钥协商中,经过公钥一方去发送密钥信息,第三方没法解密出密钥信息,由于第三方必须用非对称中的私钥去解密,可是私钥是不公开的。相反,若是是经过私钥加密,则因为公钥是公开的,第三方很容易解密获得密钥。

  2. 若是是dh算法相关的协商,如何获取到预备主密钥。 答:加入不是rsa做为密钥协商,那么双方会在exchange信息中交换公共信息,而后计算出预备主密钥,预备主密钥就不会进行网络传输。本质上是没有变化的。

  3. 在1问题中,经过rsa密钥协商不是会遭遇中间人攻击吗? 答:密码学章节已经讲过,证书技术是如何防止中间人攻击的,也就是通过证书签名的公钥是安全的,中间人没法伪造。因此不会有中间人攻击。

而会话密钥是记录层中经过主密钥生成的数据。该数据会被拆成几部分,分别用于加密解密,和mac认证。

会话重启

tls 1.2有两种会话重启的方式,分别:

  1. 基于Session Id
  2. 基于Session Ticket

基于Session Id流程:

基于session的方式,在客户端发送第一个hello的时候,会带上消息中的session_id,该id是在完整握手中由服务器生成,而且保存在服务器内存中。 会话重启中会保留以前的主密钥,会话密钥会从新生成。这样能够防止前向安全性。

这种重启方式有session的通病,就是比较占用服务器资源,由于session是服务器生成而且保存在服务器中。

相比session的重启方式,基于ticket的方式就是在客户端存储会话,服务端不作存储。不过每次重启会更新ticket。流程以下:

参考资料:

  1. <<图解密码学>>
  2. <<深刻浅出https>>
  3. https
相关文章
相关标签/搜索