zoukankan      html  css  js  c++  java
  • SSL&TLS

    一.SSL和TLS
    1.SSL
    SSL:(Secure Socket Layer,安全套接字层),为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上传输过程中不会被截取。当前版本为3.0。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。
    1.1.SSL的特性
    数据传输的机密性:SSL加密通道上的数据使用对称密钥算法,目前主要支持的算法有DES、3DES、AES等,这些算法都可以有效地防止交互数据被窃听。
    身份验证机制:使用数字签名技术,SSL客户端必须验证SSL服务器的身份,SSL服务器是否验证SSL客户端的身份,则由SSL服务器决定。
    消息完整性验证:SSL利用基于MD5或SHA的MAC算法来保证消息的完整性。利用非对称密钥算法保证密钥本身的安全。SSL通常采用RSA算法加密传输密钥。
    公正性:SSL利用PKI提供的机制保证公钥的真实性:验证SSL服务器/SSL客户端的身份之前,SSL服务器/SSL客户端需要将从CA获取的证书发送给对端,对端通过PKI判断该证书的真实性。

    1.2.SSL协议组成

    SSL位于应用层和传输层之间,它可以为任何基于TCP等可靠连接的应用层协议提供安全性保证。SSL协议本身分为两层:
    • 上层:
      • SSL握手协议(SSL handshake protocol)
      • SSL密码变化协议(SSL change cipher spec protocol)
      • SSL警告协议(SSL alert protocol)
    • 底层:
      • SSL记录协议(SSL record protocol)。
    1)SSL握手协议
    握手协议是客户机和服务器用SSL连接通信时使用的第一个子协议,握手协议包括客户机与服务器之间的一系列消息。
    握手协议是在应用程序的数据传输之前使用的。它建立在SSL记录协议之上,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
    握手协议包含以下3个字段(1)Type:表示10种消息类型之一(2)Length:表示消息长度字节数(3)Content:与消息相关的参数
    2)SSL密码变化协议
    客户端和服务器端通过密码变化协议通知对端,随后的报文都将使用新协商的加密套件和密钥进行保护和传输。
    3)SSL警告协议
    客户机和服务器发现错误时,向对方发送一个警报消息,消息中包含告警的严重级别和描述。如果是致命错误,则算法立即关闭SSL连接,双方还会先删除相关的会话号,秘密和密钥。每个警报消息共2个字节,第1个字节表示错误类型,如果是警报,则值为1,如果是致命错误,则值为2;第2个字节制定实际错误类型。
    4)SSL记录协议
    记录协议在客户机和服务器握手成功后使用,即客户机和服务器鉴别对方和确定安全信息交换使用的算法后,进入SSL记录协议。主要负责对上层的数据(SSL握手协议、SSL密码变化协议、SSL警告协议和应用层协议报文)进行分块、计算并添加MAC值、加密,并把处理后的记录块传输给对端
    2.TLS协议
    TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本(已经证明不安全),可以理解为SSL 3.1,它是写入了 RFC 的。
    SSL3.0和TLS1.0几乎是一样的,后来沿着TLS的路径发展,不在更新SSL,目前广泛用的是TLS1.2,,最新的是TLS1.3。
    具体每个版本情况如下:
    1)TLS 1.1
    TLS 1.1在RFC 4346中定义,于2006年4月发表,它是TLS 1.0的更新。在此版本中的差异包括:
    • 添加对CBC攻击的保护:
    • 隐式IV被替换成一个显式的IV。
    • 更改分组密码模式中的填充错误。
    • 支持IANA登记的参数。
    2)TLS 1.2
    TLS 1.2在RFC 5246中定义,于2008年8月发表。它基于更早的TLS 1.1规范。主要区别包括:
    • 可使用密码组合选项指定伪随机函数使用SHA-256替换MD5-SHA-1组合。
    • 可使用密码组合选项指定在完成消息的哈希认证中使用SHA-256替换MD5-SHA-1算法,但完成消息中哈希值的长度仍然被截断为96位。
    • 在握手期间MD5-SHA-1组合的数字签名被替换为使用单一Hash方法,默认为SHA-1。
    • 增强服务器和客户端指定Hash和签名算法的能力。
    • 扩大经过身份验证的加密密码,主要用于GCM和CCM模式的AES加密的支持。
    • 添加TLS扩展定义和AES密码组合。所有TLS版本在2011年3月发布的RFC 6176中删除了对SSL的兼容,这样TLS会话将永远无法协商使用的SSL 2.0以避免安全问题。
    3)TLS 1.3
    TLS 1.3在RFC 8446中定义,于2018年8月发表。它基于更早的TLS 1.2规范,与TLS 1.2的主要区别包括:
    • 将密钥协商和认证算法从密码包中分离出来。
    • 移除脆弱和较少使用的命名椭圆曲线支持(参见椭圆曲线密码学)。
    • 移除MD5和SHA-224密码散列函数的支持。
    • 请求数字签名,即便使用之前的配置。
    • 集成HKDF和半短暂DH提议。
    • 替换使用PSK和票据的恢复。
    • 支持1-RTT握手并初步支持0-RTT。
    • 通过在(EC)DH密钥协议期间使用临时密钥来保证完善的前向安全性。
    • 放弃许多不安全或过时特性的支持,包括数据压缩、重新协商、非AEAD密码本、静态RSA和静态DH密钥交换、自定义DHE分组、点格式协商、更改密码本规范的协议、UNIX时间的Hello消息,以及长度字段AD输入到AEAD密码本。
    • 禁止用于向后兼容性的SSL和RC4协商。
    • 集成会话散列的使用。
    • 弃用记录层版本号和冻结数以改进向后兼容性。
    • 将一些安全相关的算法细节从附录移动到标准,并将ClientKeyShare降级到附录。
    • 添加带有Poly1305消息验证码的ChaCha20流加密。
    • 添加Ed25519和Ed448数字签名算法。
    • 添加x25519和x448密钥交换协议。
    • 将支持加密服务器名称指示(EncryptedServerNameIndication, ESNI)。
    协议组成
    • TLS 记录协议(TLS Record):通过使用客户端和服务端协商后的秘钥进行数据加密传输。
    • TLS 握手协议(TLS Handshake):客户端和服务端进行协商,确定一组用于数据传输加密的秘钥串。
    TLS的主要增强内容:
    TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。TLS 在SSL v3.0 的基础上,提供了以下增强内容:
    • 更安全的MAC算法
    • 更严密的警报
    • “灰色区域”规范的更明确的定义
    二.握手协商过程
    通过握手过程在客户端和服务器之间协商会话参数,并建立会话。会话包含的主要参数有会话ID、对方的证书、加密套件(密钥交换算法、数据加密算法和MAC算法等)以及主密钥(master secret)。通过会话传输的数据,都将采用该会话的主密钥和加密套件进行加密、计算MAC等处理。
    不同情况下,握手过程存在差异。下面将分别描述以下三种情况下的握手过程:
    • 只验证服务器的握手过程
    • 验证服务器和客户端的握手过程
    • 恢复原有会话的握手过程
    1)握手阶段分成五步

    第一步,客户端给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。

    第二步,服务端确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。

    第三步,客户端确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务端。

    第四步,服务端使用自己的私钥,获取客户端发来的随机数(即Premaster secret)。

    第五步,客户端和服务端根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。

    具体步骤如下:
    步骤 1. ClientHello – 客户端发送所支持的 SSL/TLS 最高协议版本号和所支持的加密算法集合及压缩方法集合等信息给服务器端。
    步骤 2. ServerHello – 服务器端收到客户端信息后,选定双方都能够支持的 SSL/TLS 协议版本和加密方法及压缩方法,返回给客户端。
    (可选)步骤 3. SendCertificate – 服务器端发送服务端证书给客户端。
    (可选)步骤 4. RequestCertificate – 如果选择双向验证,服务器端向客户端请求客户端证书。
    步骤 5. ServerHelloDone – 服务器端通知客户端初始协商结束。
    (可选)步骤 6. ResponseCertificate – 如果选择双向验证,客户端向服务器端发送客户端证书。
    步骤 7. ClientKeyExchange – 客户端使用服务器端的公钥,对客户端公钥和密钥种子进行加密,再发送给服务器端。
    (可选)步骤 8. CertificateVerify – 如果选择双向验证,客户端用本地私钥生成数字签名,并发送给服务器端,让其通过收到的客户端公钥进行身份验证。
    步骤 9. CreateSecretKey – 通讯双方基于密钥种子等信息生成通讯密钥。
    步骤 10. ChangeCipherSpec – 客户端通知服务器端已将通讯方式切换到加密模式。
    步骤 11. Finished – 客户端做好加密通讯的准备。
    步骤 12. ChangeCipherSpec – 服务器端通知客户端已将通讯方式切换到加密模式。
    步骤 13. Finished – 服务器做好加密通讯的准备。
    步骤 14. Encrypted/DecryptedData – 双方使用客户端密钥,通过对称加密算法对通讯内容进行加密。
    步骤 15. ClosedConnection – 通讯结束后,任何一方发出断开 SSL 连接的消息。
    2)握手阶段有三点需要注意

    (1)生成对话密钥一共需要三个随机数。

    (2)握手之后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

    (3)服务器公钥放在服务器的数字证书之中。

    为了保障随机性,采用会话密钥(session key),每次会话产生一对对称密钥,密钥的种子通过三次随机数(readom)形成,在握手协商(handshake)中的premaster secret(第三个密钥)。用三个随机数的主要目的是降低伪随机的概率,以提高安全性(被猜测的可能性)。

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

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

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

    3)握手过程中各种消息抓包情况

    下面介绍最常见的握手规则,一种不需要验证客户端身份但需要验证服务器身份的握手:

    a) ClientHello

    这条消息将客户端的功能和首选项传送给服务器。

    • Version: 协议版本(protocol version)指示客户端支持的最佳协议版本
    • Random: 一个 32 字节数据,28 字节是随机生成的 (图中的 Random Bytes);剩余的 4 字节包含额外的信息,与客户端时钟有关 (图中使用的是 GMT Unix Time)。在握手时,客户端和服务器都会提供随机数,客户端的暂记作 random_C (用于后续的密钥的生成)。这种随机性对每次握手都是独一无二的,在身份验证中起着举足轻重的作用。它可以防止 重放攻击,并确认初始数据交换的完整性。
    • Session ID: 在第一次连接时,会话 ID(session ID)字段是空的,这表示客户端并不希望恢复某个已存在的会话。典型的会话 ID 包含 32 字节随机生成的数据,一般由服务端生成通过 ServerHello 返回给客户端。
    • Cipher Suites: 密码套件(cipher suite)块是由客户端支持的所有密码套件组成的列表,该列表是按优先级顺序排列的
    • Compression: 客户端可以提交一个或多个支持压缩的方法。默认的压缩方法是 null,代表没有压缩
    • Extensions: 扩展(extension)块由任意数量的扩展组成。这些扩展会携带额外数据

    b)ServerHello

    是将服务器选择的连接参数传回客户端。

    这个消息的结构与 ClientHello 类似,只是每个字段只包含一个选项,其中包含服务端的 random_S 参数 (用于后续的密钥协商)。服务器无需支持客户端支持的最佳版本。如果服务器不支持与客户端相同的版本,可以提供某个其他版本以期待客户端能够接受

    图中的 Cipher Suite 是后续密钥协商和身份验证要用的加密套件,此处选择的密钥交换与签名算法是 ECDHE_RSA,对称加密算法是 AES-GCM,后面会讲到这个

    还有一点默认情况下 TLS 压缩都是关闭的,因为 CRIME 攻击会利用 TLS 压缩恢复加密认证 cookie,实现会话劫持,而且一般配置 gzip 等内容压缩后再压缩 TLS 分片效益不大又额外占用资源,所以一般都关闭 TLS 压缩

    c)Certificate

    典型的 Certificate 消息用于携带服务器 X.509 证书链
    服务器必须保证它发送的证书与选择的算法套件一致。比方说,公钥算法与套件中使用的必须匹配。除此以外,一些密钥交换算法依赖嵌入证书的特定数据,而且要求证书必须以客户端支持的算法签名。所有这些都表明服务器需要配置多个证书(每个证书可能会配备不同的证书链)。

    Certificate 消息是可选的,因为并非所有套件都使用身份验证,也并非所有身份验证方法都需要证书。更进一步说,虽然消息默认使用 X.509 证书,但是也可以携带其他形式的标志;一些套件就依赖 PGP 密钥

    d) ServerKeyExchange

    携带密钥交换需要的额外数据。ServerKeyExchange 是可选的,消息内容对于不同的协商算法套件会存在差异。部分场景下,比如使用 RSA 算法时,服务器不需要发送此消息。

    ServerKeyExchange 仅在服务器证书消息(也就是上述 Certificate 消息)不包含足够的数据以允许客户端交换预主密钥(premaster secret)时才由服务器发送。

    比如基于 DH 算法的握手过程中,需要单独发送一条 ServerKeyExchange 消息带上 DH 参数:

    e)ServerHelloDone

    表明服务器已经将所有预计的握手消息发送完毕。在此之后,服务器会等待客户端发送消息。

    f) verify certificate

    客户端验证证书的合法性,如果验证通过才会进行后续通信,否则根据错误情况不同做出提示和操作,合法性验证内容包括如下:

    • 证书链的可信性 trusted certificate path;
    • 证书是否吊销 revocation,有两类方式 - 离线 CRL 与在线 OCSP,不同的客户端行为会不同;
    • 有效期 expiry date,证书是否在有效时间范围;
    • 域名 domain,核查证书域名是否与当前的访问域名匹配;

     PKI 体系 的内容可知,对端发来的证书签名是 CA 私钥加密的,接收到证书后,先读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性;然后去查询证书的吊销情况等

    g)ClientKeyExchange

    合法性验证通过之后,客户端计算产生随机数字的预主密钥(Pre-master),并用证书公钥加密,发送给服务器并携带客户端为密钥交换提供的所有信息。这个消息受协商的密码套件的影响,内容随着不同的协商密码套件而不同。

    此时客户端已经获取全部的计算协商密钥需要的信息: 两个明文随机数 random_C 和 random_S 与自己计算产生的 Pre-master,然后得到协商密钥(用于之后的消息加密)

    图中使用的是 ECDHE 算法,ClientKeyExchange 传递的是 DH 算法的客户端参数,如果使用的是 RSA 算法则此处应该传递加密的预主密钥

    h)ChangeCipherSpec

    通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信

    i)Finished (Encrypted Handshake Message)

    Finished 消息意味着握手已经完成。消息内容将加密,以便双方可以安全地交换验证整个握手完整性所需的数据。

    这个消息包含 verify_data 字段,它的值是握手过程中所有消息的散列值。这些消息在连接两端都按照各自所见的顺序排列,并以协商得到的主密钥 (enc_key) 计算散列。这个过程是通过一个伪随机函数(pseudorandom function,PRF)来完成的,这个函数可以生成任意数量的伪随机数据。
    两端的计算方法一致,但会使用不同的标签(finished_label):客户端使用 client finished,而服务器则使用 server finished。

    m)Server

    服务器用私钥解密加密的 Pre-master 数据,基于之前交换的两个明文随机数 random_C 和 random_S,同样计算得到协商密钥

    同样计算之前所有收发信息的 hash 值,然后用协商密钥解密客户端发送的 verify_data_C,验证消息正确性;

    n)change_cipher_spec

    服务端验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信(图中多了一步 New Session Ticket,此为会话票证,会在会话恢复中解释);

    0)Finished (Encrypted Handshake Message)

    服务器也结合所有当前的通信参数信息生成一段数据 (verify_data_S) 并采用协商密钥 session secret (enc_key) 与算法加密并发送到客户端;

    p)握手结束

    客户端计算所有接收信息的 hash 值,并采用协商密钥解密 verify_data_S,验证服务器发送的数据和密钥,验证通过则握手完成;

    q)加密通信

    开始使用协商密钥与算法进行加密通信。

    三、会话加密及会话恢复

    1.记录协议

    会话通过记录协议进行加密。记录协议负责在传输连接上交换的所有底层消息,并且可以配置加密。每一条 TLS 记录以一个短标头开始。标头包含记录内容的类型 (或子协议)、协议版本和长度。原始消息经过分段 (或者合并)、压缩、添加认证码、加密转为 TLS 记录的数据部分。
    分片 (Fragmentation):记录层将信息块分割成携带 2^14 字节 (16KB) 或更小块的数据的 TLSPlaintext 记录。
    记录压缩和解压缩 (Record compression and decompression):压缩算法将 TLSPlaintext 结构转换为 TLSCompressed 结构。如果定义 CompressionMethod 为 null 表示不压缩空或标准流加密 (Null or standard stream cipher):流加密(BulkCipherAlgorithm)将 TLSCompressed.fragment 结构转换为流 TLSCiphertext.fragment 结构
    CBC 块加密 (分组加密):块加密(如 RC2 或 DES),将 TLSCompressed.fragment 结构转换为块 TLSCiphertext.fragment 结构
    记录有效载荷保护 (Record payload protection):加密和 MAC 功能将 TLSCompressed 结构转换为 TLSCiphertext。记录的 MAC 还包括序列号,以便可以检测到丢失,额外或重复的消息。
    密钥计算 (Key calculation):记录协议需要一种算法,从握手协议提供的安全性参数生成密钥、IV 和 MAC secret.
    主密钥 (Master secret): 在连接中双方共享的一个 48 字节的密钥
    客户随机数 (client random): 由客户端提供的 32 字节值
    服务器随机数 (server random): 由服务器提供的 32 字节值

    四、session的恢复

    握手阶段用来建立连接。如果出于某种原因,对话中断,就需要重新握手。

    有两种方法可以恢复原来的session:一种叫做session ID,另一种叫做session ticket。

    1)采用session ID 方式

    session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的"对话密钥",而不必重新生成一把。

    客户端给出session ID,服务器确认该编号存在,双方就不再进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通信。

    session ID是目前所有浏览器都支持的方法,但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。

    2)采用session ticket方式

    客户端不再发送session ID,而是发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。

    使用这种方式,除了所有的状态都保存在客户端(与 HTTP Cookie 的原理类似)之外,其消息流与服务器会话缓存是一样的。

    这种方法有可能使扩展服务器集群更为简单,因为如果不使用这种方式,就需要在服务集群的各个节点之间同步会话。
    Session ticket 需要服务器和客户端都支持,属于一个扩展字段,占用服务器资源很少。

     

     

     
    参考文章:

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





  • 相关阅读:
    VC获取系统时间、程序运行时间
    数学题
    最小费用流
    最大流模板
    计划
    算法竞赛入门经典 训练指南 之 图论(完全版持续更新)
    uva 11324 The Largest Clique 强连通分量求缩点构造DAG
    hdu 4288 Coder 一个很水的版本 >_<
    hoj 2939 Coin Question
    成都网络赛 1002 Control 1005 Food
  • 原文地址:https://www.cnblogs.com/worter991/p/13492076.html
Copyright © 2011-2022 走看看