一.什么是TLS
TLS(Transport Layer Security,安全传输层),TLS是建立在传输层TCP协议之上的协议,服务于应用层,它的前身是SSL(Secure Socket Layer,安全套接字层),它实现了将应用层的报文进行加密后再交由TCP进行传输的功能。 TLS的作用 TLS协议主要解决如下三个网络安全问题。 1.保密(message privacy),保密通过加密encryption实现,所有信息都加密传输,第三方无法嗅探; 2.完整性(message integrity),通过MAC校验机制,一旦被篡改,通信双方会立刻发现; 3.认证(mutual authentication),双方认证,双方都可以配备证书,防止身份被冒充; TLS的发展过程 1995: SSL 2.0, 由Netscape提出,这个版本由于设计缺陷,并不安全,很快被发现有严重漏洞,已经废弃。 1996: SSL 3.0. 写成RFC,开始流行。目前(2015年)已经不安全,必须禁用。 1999: TLS 1.0. 互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版 2006: TLS 1.1. 作为 RFC 4346 发布。主要修复了CBC模式相关的如BEAST攻击等漏洞 2008: TLS 1.2. 作为 RFC 5246 发布 。增进安全性,目前应该主要部署的版本 2015之后: TLS 1.3,还在制订中,支持0-rtt,大幅增进安全性,砍掉了aead之外的加密方式。
二.TLS 1.3协议层级架构
在网络领域,为了实现解耦基本都遵循了层级软件架构,TLS协议位于下层TCP协议及上层(即应用层)协议之间。 Tips:由于TLS对交互信息的时序有规定,所以下层协议必须能够提供这种时序服务,因此TLS不能使用UDP来传输。针对UDP的安全应用场景,可参照DTLS规范。 同样在TLS协议内部也是基于分层架构,分为两层:下层为记录层协议,为TLS上层子协议为传送提供分片、消息加密及加密后报传输,同时对接收到的数据进行验证、解密、重新组装,然后提交给高层的应用层;上层包含4种子协议:握手协议(Handshake Protocal)、警报协议(Alert Protocol)、应用数据协议(Application Protocol)及Change_cipher_spec。其中change_cipher_spec只是为了兼容性存在,其余每个子协议都具有特定的作用,组合起来实现完整的协议功能。
三. HTTPS = HTTP over TLS.
只需配置浏览器和服务器相关设置开启 TLS,即可实现 HTTPS,TLS 高度解耦,可装可卸,与上层高级应用层协议相互协作又相互独立。
四. 加密
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 Hash、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。 TLS 的基本工作方式是,客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥,然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取。 例如,在 HTTPS 协议中,客户端发出请求,服务器端会将公钥发给客户端,客户端验证过后生成一个密钥再用公钥加密后发送给服务端(非对称加密),双方会在 TLS 握手过程中生成一个协商密钥(对称密钥),成功后建立加密连接。通信过程中客户端将请求数据用协商密钥加密后发送,服务端也用协商密钥解密,响应也用相同的协商密钥。后续的通信使用对称加密是因为对称加解密快,而握手过程中非对称加密可以保证加密的有效性,但是过程复杂,计算量相对来说也大。
五. TLS记录协议
下图描述了记录协议的整个操作过程。记录协议接收一个要传送的应用消息,将段分为块,压缩(可选)、加上MAC、加密、再加上一个TLS头,将的得到的最终数据单元放入一个TCP段中。接收的数据被解密、验证、解压、重组后,再传递给高层。 第1步 是分段每个上层消息被分成若干个小于或等于2^14字节(16384字节)的段; 第2步 进行可选择压缩,压缩必须采用无损压缩方法,并且增加长度不能超过1024个字节。 第3步 对压缩数据计算其消息认证码MAC。TLS使用RFC2104中定义的HMAC算法,HMAC计算方式如下: 其中,h为嵌入的散列函数(对于TLS为MD5或SHA-1); x为HMAC的消息输入(包括由嵌入散列函数定义的填充位); K+左边填充0的密钥,使其长度与散列码中的块长度一致(MD5或SHA-1中的块长为512位); ipad是将00110110这一比特序列(16进制的36)重复b/8次的结果; opad是将01011100这一比特序列(16进制的5C)重复b/8次的结果。 对于TLS,MAC计算包含以下表达式的各域: HMAC_hash(MAC_write_secret, seq_numⅡTLSCompressed.typeⅡ TLSCompressed.version Ⅱ TLSCompressed.length Ⅱ TLSCompressed.fragment)); seq_num(记录的序列号) MAC计算不仅覆盖了SSLV3中MAC计算的各域,还增加了一个体现协议版本号的域TLSCompressed。 第四步 将压缩消息和MAC用对称加密方法加密。加密对内容增加长度不能超过1024字节,以便整个长度不能超过2^14 + 2048 。以下加密算法是允许的。 对流加密而言,压缩消息和MAC一起被加密。注意,MAC在加密之前计算,然后将MAC和明文或者压缩后的明文一起加密。 对分组加密而言,填充应在MAC之后、加密之前进行。填充的格式是一定长度的填充字节后跟一个字节的填充长度。整个填充域的长度是使得总长度(明文+MAC+填充域的长度)为规定的加密分组长度的整数倍,最大255字节。例如,如果分组长度为16字节(如AES),明文(或如果使用了压缩则为压缩文本)加上MAC为79字节,则填充长度可以是1,17,33等,直到161 。当填充长度为161时,总长度为79+161=240 。使用可变的填充长度可以用来阻止哪些基于分析长度的攻击。 最后1步 加上一个如下域组成的SSL头部: 内容类型(8位) 封装段使用的高层协议 主版本号(8位) 表明TLS使用的主版本号,如TLSV2的值为3 。 从版本号(8位) 表明TLS使用的从版本号,如TLSV2的值为1 。 压缩长度(16位) 明文段(如果使用了压缩,则为压缩段)字节长度,最大值为2^14 + 2048。 已经定义的内容类型包括修改密码规范、警报、握手和应用数据。
六.修改密码规范协议
修改协议规范时TLS三个特定协议之一,也是最简单的一个。协议由一个仅包含一个字节值为1的消息组成,此消息使得挂起状态被复制到当前状态中,用于更新连接的密钥。
七.警报协议
警报协议用于向对等实体传递TLS相关的警报。和使用TLS的其他应用一样,警报消息按照当前状态压缩和加密。 1字节 1字节 层 警报
此协议的每个消息由两个字节组成。第一个字节,值1表示警告,值2表示致命错误,传递消息出错的严重程度,如果级别为致命,则TLS将立即终止连接,而会话中的其他连接将继续进行,但不会在此会话中建立新连接。第二字节包含描述特定警报信息的代码。通常导致致命错误的警报列举如下: 1.意外消息, 接收到不正确的消息 2.MAC记录出错,接收到不正确的MAC 3.解压失败,解压函数接收到不正确的输入(如不能解压或解压长度大于允许值的数据长度) 4.握手失败,发送者无法在给定选项中协商出一个可以接受的安全参数集。 5.非法参数,握手消息中的某个域超出范围或与其他域不一致。 6.解密失败,使用不正确的方法解密密文,或者长度不是块长度的整数倍或者填充值不对。 7.记录一处,接收的TLS记录中载荷(密文)长度超过2^14 + 2048字节或者密文解密长度超过2^14 + 2048字节。 8.未知的签证机构,接收到正确的证书链或部分链,但由于证书不能定位或者不能与可信任的签证机构匹配而不接收证书。 9.拒绝访问,接收到合法证书,但发送者拒绝协商访问。 10.解码出错,由于域超出了指定范围或消息长度不对使得消息不能解码。 11.输出限制,密钥长度的输出限制不能达成一致。 12.协议版本,客户端试图协商的协议版本可以识别但不能支持。 13.安全部组,服务器需要的安全级别客户端无法支持时协商失败的返回值,代替握手失败。 14.中间出错,与对方或协议正确性无关的中间环节出错,使得无法继续操作。
其余的警报如下: 1.结束通知,通知接收者,发送者将不再用此连接发送任何消息。各方再关闭连接的写端时均需发送结束通知。 2.证书出错,接收的证书被破坏(如签名无法通过验证) 3.不支持的证书,不支持的证书类型。 4.证书撤销,证书被其签名者撤销。 5.证书过期,证书超过使用期限。 6.未知证书,在处理证书时,出现其他错误,使得证书不被接受。 7.解密出错,握手密码访问失败,包括无法验证签名、解密密钥交换或校验完成消息。 8.用户取消,握手由于某些与协议错误的原因而被取消。 9.不再重新协商,由客户端响应hello请求或服务器再初始握手后响应客户端的hello。通常应答消息都会导致重新协商,但此警报表明发送者不能重新协商。此消息通常是警告消息。
八.握手协议
握手是 TLS 协议中最精密复杂的部分。在这个过程中,通信双方协商连接参数,并且完成身 份验证。根据使用的功能的不同,整个过程通常需要交换 6~10 条消息。根据配置和支持的协议扩展的不同,交换过程可能有许多变种。在使用中经常可以观察到以下三种流程:(1) 完整的握手, 对服务器进行身份验证;(2) 恢复之前的会话采用的简短握手;(3) 对客户端和服务器都进行身份验证的握手。 1.握手协议的职责是生成通信过程所需的共享密钥和进行身份认证。这部分使用无密码套件,为防止数据被窃听,通过公钥密码或 Diffie-Hellman 密钥交换技术通信。 2.密码规格变更协议,用于密码切换的同步,是在握手协议之后的协议。握手协议过程中使用的协议是“不加密”这一密码套件,握手协议完成后则使用协商好的密码套件。 3.警告协议,当发生错误时使用该协议通知通信对方,如握手过程中发生异常、消息认证码错误、数据无法解压缩等。 4.应用数据协议,通信双方真正进行应用数据传输的协议,传送过程通过 TLS 应用数据协议和 TLS 记录协议来进行传输。 握手协议消息的标头信息包含消息类型(1 字节)和长度(3 字节),余下的信息则取决于消息类型: struct { HandshakeType msg_type; //1byte uint24 length; //3bytes HandshakeMessage message; // ≥0 byte } Handshake;
8.1 完整握手
每一个 TLS 连接都会以握手开始。如果客户端此前并未与服务器建立会话,那么双方会执行一次完整的握手流程来协商 TLS 会话。握手过程中,客户端和服务器将进行以下四个主要步骤: 1.交换各自支持的功能,对需要的连接参数达成一致 2.验证出示的证书,或使用其他方式进行身份验证 3.对将用于保护会话的共享主密钥达成一致 4.验证握手消息并未被第三方团体修改 TLS的建立过程总共有13个包,第一次建立至少需要9个包。
8.1.1 TLS建立第一阶段:建立安全功能
客户端首先发送ClientHello消息到服务端,服务端收到ClientHello消息后,再发送ServerHello消息回应客户端。 ClientHello消息 Version 协议版本(protocol version)指示客户端支持的最佳协议版本。 Random 一个 32 字节数据,28 字节是随机生成的 (图中的 Random Bytes);剩余的 4 字节包含额外的信息,与客户端时钟有关。在握手时,客户端和服务器都会提供随机数,客户端的暂记作 random_C (用于后续的密钥的生成)。这种随机性对每次握手都是独一无二的,在身份验证中起着举足轻重的作用。它可以防止 重放攻击,并确认初始数据交换的完整性。 Session ID 在第一次连接时,会话 ID(session ID)字段是空的,这表示客户端并不希望恢复某个已存在的会话。典型的会话 ID 包含 32 字节随机生成的数据,一般由服务端生成通过 ServerHello 返回给客户端。 如果该字段不为空,说明以前是与服务器有连接的,在此期间,服务器将使用Session ID映射对称密钥,并将Session ID存储在客户端浏览器中,为映射设置一个时间限。如果浏览器将来连接到同一台服务器(在时间到期之前),它将发送Session ID,服务器将对映射的Session ID进行验证,并使用以前用过的对称密钥来恢复Session,这种情况下不需要完全握手。也叫作TLS会话恢复。后面会有介绍。 Cipher Suites 密码套件(cipher suite)块是由客户端支持的所有密码套件组成的列表,该列表是按优先级顺序排列的, 上面的报文中,客户端发送了74套加密套件。服务端会从中选出一种来作为双方共同的加密套件。 Compression 客户端可以提交一个或多个支持压缩的方法。默认的压缩方法是 null,代表没有压缩。从TLS 1.3开始,协议就禁用了TLS压缩。 Extensions 扩展(extension)块由任意数量的扩展组成。这些扩展会携带额外数据。
ServerHello消息 收到客户端问候之后服务器必须发送服务器问候信息,服务器会检查指定诸如TLS版本和算法的客户端问候的条件,如果服务器接受并支持所有条件,它将发送其证书以及其他详细信息,否则,服务器将发送握手失败消息。 如果接受,第二步是服务端向客户端发送 Server Hello 消息,这个消息会从 Client Hello 传过来的 Support Ciphers 里确定一份加密套件,这个套件决定了后续加密和生成摘要时具体使用哪些算法,另外还会生成一份随机数 Random_S。注意,至此客户端和服务端都拥有了两个随机数(Random_C+ Random_S),这两个随机数会在后续生成对称秘钥时用到。 Version 服务器无需支持客户端支持的最佳版本。如果服务器不支持与客户端相同的版本,可以提供某个其他版本以期待客户端能够接受。
Random 这个消息的结构与 ClientHello 类似,只是每个字段只包含一个选项,其中包含服务端的 random_S 参数 (用于后续的密钥协商)。 Session ID 服务器将约定的Session参数存储在TLS缓存中,并生成与其对应的Session id。它与Server Hello一起发送到客户端。客户端可以写入约定的参数到此Session id,并给定到期时间。客户端将在Client Hello中包含此id。如果客户端在此到期时间之前再次连接到服务器,则服务器可以检查与Session id对应的缓存参数,并重用它们而无需完全握手。这非常有用,因为服务器和客户端都可以节省大量的计算成本。 在涉及亚马逊和谷歌等流量巨大的应用程序时,这种方法存在缺点。每天都有数百万人连接到服务器,服务器必须使用Session密钥保留所有Session参数的TLS缓存。这是一个巨大的开销。 为了解决这个问题,在扩展包里加入了Session Tickets, 在这里,客户端可以在client hello中指定它是否支持Session Ticket。然后,服务器将创建一个新的会话票证(Session Ticket),并使用只有服务器知道的经过私钥加密的Session参数。它将存储在客户端上,因此所有Session数据仅存储在客户端计算机上,但Ticket仍然是安全的,因为该密钥只有服务器知道。 此数据可以作为名为Session Ticket的扩展包含在Client Hello中。
Cipher Suite Cipher Suite参数的第一个元素是密钥交换方法(如传统加密密钥和MAC交换方法)。支持下述密钥交换方法: 1.RSA, 用接收者的RSA公钥加密的密钥,必须拥有接收者公钥的公钥证书; 2.固定的Diffie-Hellman, Diffie-Hellman密钥交换,其中包含签证机构签发的Diffie-Hellman公钥参数的服务器证书,也就是说,公钥证书包含Diffie-Hellman公钥参数。客户端在证书中提供它的Diffie-Hellman公钥参数,或需要进行客户端认证时,在密钥交换消息中提供证书。 3.瞬时Diffie-Hellman,此技术用于创建瞬时(临时,一次性)的密钥。在这种情况下,Diffie-Hellman公钥在交换时使用发送者的RSA或者DSS私钥签名。接收者使用相应的公钥验证签名。由于它使用的是临时的认证密钥,因此在三种Diffie-Hellman选项中最安全。 4.匿名Diffie-Hellman,使用基本的Diffie-Hellman算法,没有认证。即,在向对方发送其Diffie-Hellman公钥参数时,不进行认证。这种方法容易受到中间人攻击,攻击者可以使用匿名Diffie-Hellman与双方进行通信。 密钥交换方法定义之后的是CipherSpec,其中包含以下域: 1.密码算法, 任何前面提及的算法,RC4、RC2、DES、3DES、DES40或IDEA。 2.MAC算法,MD5或SHA-1。 3.密码类型, 流或块 5.可否出口, 真或假 6.散列长度,0,16(MD5)或20(SHA-1)字节。 7.密钥材料,字节序列,包含生成写密钥所使用的数据。 8.IV大小,密码分组链CBC加密使用的初始向量的大小。 图中的 Cipher Suite 是后续密钥协商和身份验证要用的加密套件,此处选择的密钥交换与签名算法是 ECDHE_RSA,对称加密算法是 AES-GCM。
Compress method 还有一点默认情况下 TLS 压缩都是关闭的,因为 CRIME 攻击会利用 TLS 压缩恢复加密认证 cookie,实现会话劫持,而且一般配置 gzip 等内容压缩后再压缩 TLS 分片效益不大又额外占用资源,所以一般都关闭 TLS 压缩 。
Extension 这个阶段之后,客户端服务端知道了下列内容: 1.TLS版本 2.密钥交换、信息验证和加密算法 3.压缩方法 4.有关密钥生成的两个随机数。
8.1.2 TLS建立第二阶段:服务器认证和密钥交换
服务器向客户端发送消息。 服务器启动TLS握手第2阶段,是本阶段所有消息的唯一发送方,客户机是所有消息的唯一接收方。该阶段分为4步: 证书:服务器将数字证书和到根CA整个链发给客户端,使客户端能用服务器证书中的服务器公钥认证服务器。 服务器密钥交换(可选):这里视密钥交换算法而定 证书请求:服务端可能会要求客户自身进行验证。 服务器握手完成:第二阶段的结束,第三阶段开始的信号。
Certificate(可选)—第一次建立必须要有证书 一般情况下,除了会话恢复时不需要发送该消息,在TLS握手的全流程中,都需要包含该消息。消息包含一个X.509证书,证书中包含公钥,发给客户端用来验证签名或在密钥交换的时候给消息加密。 除匿名Diffie-Hellman方法外,其他密钥交换方法均需要证书消息Certificate message。注意,如果使用固定Diffie-Hellman,此证书消息将由包含了服务器Diffie-Hellman公钥参数作为服务器的密钥交换消息。 这一步是服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。 Server Key Exchange(可选) 根据之前在ClientHello消息中包含的CipherSuite信息,决定了密钥交换方式(例如RSA或者DH),因此在Server Key Exchange消息中便会包含完成密钥交换所需的一系列参数。 在以下两种情况下,不需要Server key exchange消息: 1.服务器发送了带有固定Diffie-Hellman参数的证书; 2.使用RSA密钥交换 以下情况需要Server key exchange消息: 1.匿名Diffie-Hellman 消息内容包含两个全局Diffie-Hellman值【一个素数和它的原根(primitive root)】和服务器Diffie-Hellman公钥。 2.瞬时Diffie-Hellman,消息包含三个Diffie-Hellman参数,包括匿名Diffie-Hellman中的两个参数和它们的参数签名。 3.RSA密钥交换,服务器在使用RSA时仅用了RSA签名密钥,因此,客户端不能简单地通过服务器公钥加密其密钥后传送,而服务器必须建立一个临时RSA公钥/私钥对,并使用服务器密钥交换消息发送公钥。消息内容包含两个临时的RSA公钥参数(指数,模)和参数签名。 因为这里是DH算法,所以需要发送服务器使用的DH参数。 在Diffie-Hellman中,客户端无法自行计算预主密钥; 双方都有助于计算它,因此客户端需要从服务器获取Diffie-Hellman公钥。 由上图可知,此时密钥交换也由签名保护。签名的其他细节均能得到保证。通常情况下,通过对消息使用散列函数并使用发送者私钥加密获得签名。在此,散列函数定义如下: hash(Random_CⅡ Random_SⅡ ServerParams); 散列不仅包含Diffie-Hellman或RSA参数,还包含初始hello消息中的两个随机数, 可以防止重放攻击和伪装。对DSS签名而言,散列函数使用SHA-1算法;对RSA签名而言,将要计算MD5和SHA-1,再将两个散列结果串接(36字节)后服务器私钥加密。
Certificate Request(可选)------可以是单向的身份认证,也可以双向认证 这一步是可选的,如果在对安全性要求高的常见可能用到。服务器用来验证客户端。服务器端发出Certificate Request消息,要求客户端发他自己的证书过来进行验证。该消息中包含服务器端支持的证书类型(RSA、DSA、ECDSA等)和服务器端所信任的所有证书发行机构的CA列表,客户端会用这些信息来筛选证书。Certificate Request message参数:证书类型和签证机构。 证书类型表明了公钥算法和它的用途: 1.RSA:仅用于签名 2.DSS:仅用于签名 3.固定Diffie-Hellman的RSA:此时发送RSA签名证书,其签名仅用于认证。 4.固定Diffie-Hellman的DSS:仅用于认证。 证书请求消息中的第二个参数是一个可接受的签证机构名字表。
Server Hello Done 该消息表示服务器已经将所有信息发送完毕,接下来等待客户端的消息。
8.1.3 TLS建立第三阶段
在接收到服务器完成消息之后,如果请求了证书,客户端需要验证服务器是否提供了合法证书,并且检查server hello参数是否可以接受。如果所有的条件,则客户端向服务器发回一个或多个消息。 客户端启动TLS握手第3阶段,是本阶段所有消息的唯一发送方,服务器是所有消息的唯一接收方。该阶段分为3步: 证书(可选):为了对服务器证明自身,客户要发送一个证书信息,这是可选的,在IIS中可以配置强制客户端证书认证。 客户机密钥交换(Pre-master-secret):这里客户端将预备主密钥发送给服务端,注意这里会使用服务端的公钥进行加密。 证书验证(可选),对预备秘密和随机数进行签名,证明拥有(a)证书的公钥。
Certificate(可选) 如果在第二阶段服务器端要求发送客户端证书,客户端便会在该阶段将自己的证书发送过去。服务器端在之前发送的Certificate Request消息中包含了服务器端所支持的证书类型和CA列表,因此客户端会在自己的证书中选择满足这两个条件的第一个证书发送过去。若客户端没有证书,则发送一个no_certificate警告。
接下来是此阶段必须要发的客户端密钥交换信息Client Key exchange message,消息的内容依赖于密钥交换的类型: 1.RSA 客户端生成48字节的次密钥,并使用服务器证书中的公钥或服务器密钥交换消息中的临时RSA密钥加密。它被用于后续的主密钥计算。 2.瞬时或匿名Diffie-Hellman,发送客户端Diffie-Hellman公钥参数。 3.固定Diffie-Hellman,由于证书中包含Diffie-Hellman公钥参数,因此,此消息内容为空。 根据之前从服务器端收到的随机数,按照不同的密钥交换算法,算出一个pre-master,发送给服务器,服务器端收到pre-master算出main master。而客户端当然也能自己通过pre-master算出main master。如此以来双方就算出了对称密钥。 如果是RSA算法,会生成一个48字节的随机数,然后用server的公钥加密后再放入报文中。如果是DH算法,这是发送的就是客户端的DH参数,之后服务器和客户端根据DH算法,各自计算出相同的pre-master secret. 本消息在给服务器发送的过程中,使用了服务器的公钥加密。服务器用自己的私钥解密后才能得到pre-master key.(向服务器证明自己的确持有客户端证书私钥。)
Certificate verify(可选) 在此阶段的最后,客户端发送一个证书验证消息Certificate verify message来提供对客户端证书的精确认证。此消息只有客户端具有签名能力时发送(如带有固定Diffie-Hellman参数外的所有证书)。此消息对一个基于前述消息的散列编码定义如下: Certificate Verify.signature.md5_hash MD5(handshake_messages); Certificate Verify.signature.md5_hash SHA(handshake_messages); 其中,握手消息handshake_messages指的是所有发送的握手协议消息或接收到的从client hello消息开始不包括此消息的所有消息。如果用户私钥是DSS,则被用于SHA-1散列;如果用户私钥是RSA的私钥,则被用于加密MD5和SHA-1散列连接。不管哪种情况下,其目的都是为了使用私钥验证客户证书的客户所有权。即使有人误用了客户证书,它也无法发送消息。
TLS建立第四阶段 完成握手协议,建立TLS连接。 Change Cipher Spec 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送(ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了)。 Client Finished: 客户端握手结束通知, 表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验(使用HMAC算法计算收到和发送的所有握手消息的摘要,然后通过RFC5246中定义的一个伪函数PRF计算出结果,加密后发送。此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。)
Server Finished: 服务端握手结束通知。 使用私钥解密加密的Pre-master数据,基于之前(Client Hello 和 Server Hello)交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, Pre-Master); 计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性; 发送一个 ChangeCipherSpec(告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了) 服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。 根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret对数据进行加密传输了。
九 密码计算
以下是通过密钥交换创建共享主密钥和使用密钥生成密钥参数。Secret Keys的生成过程以及作用流程图: PreMaster secret PreMaster Secret是在客户端使用RSA或者Diffie-Hellman等加密算法生成的。它将用来跟服务端和客户端在Hello阶段产生的随机数结合在一起生成 Master Secret。PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号。服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。 Master secret 由于最后通过交换,客户端和服务端都会有Pre-master和随机数,这个随机数将作为后面产生Master secret的种子,结合PreMaster secret,客户端和服务端将计算出同样的Master secret。 为了保证信息的完整性和机密性,TLS需要有六个加密密钥:四个密钥和两个IV。为了信息的可信性,客户端需要一个密钥(HMAC),为了加密要有一个密钥,为了分组加密要一个IV,服务器也是如此。TLS需要的密钥是单向的,不同于那些在其他方向的密钥。如果在一个方向上有攻击,这种攻击在其他方向是没影响的。生成过程如下: 主密钥是由一系列的Hash值组成。 master_secret = PRF(pre_master_secret,“master secret”,ClientHello.random + ServerHello.random)[0…47]; 根据要求,有4个密钥用于加密和验证每个消息的完整性,他们是: 1.客户端写入加密密钥:客户端用来加密数据,服务器用来解密数据。 2.服务器写入加密密钥:服务器用来加密数据,客户端用来解密数据。 3.客户端写入MAC密钥:客户端用来创建MAC,服务器用来验证MAC。 4.服务器写入MAC密钥:服务器用来创建MAC,客户端用来验证MAC。
十 TLS 会话恢复:
会话恢复是指只要客户端和服务器已经通信过一次,它们就可以通过会话恢复的方式来跳过整个握手阶段二直接进行数据传输。 TLS采用会话恢复的方式来减少SSL握手过程中造成的巨大开销。 为了加快建立握手的速度,减少协议带来的性能降低和资源消耗(具体分析在后文),TLS 协议有两类会话缓存机制: 1.会话标识 session ID: 由服务器端支持,协议中的标准字段,因此基本所有服务器都支持,服务器端保存会话ID以及协商的通信信息,Nginx 中1M 内存约可以保存4000个 session ID 机器相关信息,占用服务器资源较多; 2.会话记录 session ticket :t需要服务器和客户端都支持,属于一个扩展字段,支持范围约60%(无可靠统计与来源),将协商的通信信息加密之后发送给客户端保存,密钥只有服务器知道,占用服务器资源很少。 3.二者对比,主要是保存协商信息的位置与方式不同,类似与 http 中的 session 与 cookie。二者都存在的情况下,(nginx 实现)优先使用 session_ticket。
会话恢复具体过程(Session ID机制): 1.如果客户端和服务器之间曾经建立了连接,服务器会在握手成功后返回 session ID,并保存对应的通信参数在服务器中; 2.如果客户端再次需要和该服务器建立连接,则在 client_hello 中 session ID 中携带记录的信息,发送给服务器; 3.服务器根据收到的 session ID 检索缓存记录,如果没有检索到货缓存过期,则按照正常的握手过程进行; 4.如果检索到对应的缓存记录,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用类似,encrypted_handshake_message 是到当前的通信参数与 master_secret的hash 值; 5.如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec 与 encrypted_handshake_message 信息; 6.服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。
会话恢复具体过程( session ticket): 1.如果客户端和服务器之间曾经建立了连接,服务器会在 new_session_ticket 数据中携带加密的 session_ticket 信息,客户端保存; 2.如果客户端再次需要和该服务器建立连接,则在 client_hello 中扩展字段 session_ticket 中携带加密信息,一起发送给服务器; 3.服务器解密 sesssion_ticket 数据,如果能够解密失败,则按照正常的握手过程进行; 4.如果解密成功,则返回 change_cipher_spec 与 encrypted_handshake_message 信息,两个信息作用与 session ID 中类似; 5.如果客户端能够验证通过服务器加密数据,则客户端同样发送 change_cipher_spec与encrypted_handshake_message 信息; 6.服务器验证数据通过,则握手建立成功,开始进行正常的加密数据通信。
|