SSL V3.0协议(一)

翻译自RFC6101


第五节 SSL协议

SSL是一个分层的协议,每层封包可能包括了长度、描述以及内容字段。SSL接受要传输的信息,并将这些信息(或者其压缩的结果,这是可选的)分片为可管理的块,然后添加MAC(message authenticate code,信息认证码)并加密,最后把封装好的信息传输出去。接收数据是通过解密、身份认证、解压缩、重组最后把结果丢给更高层客户端进一步处理。

5.1 会话和连接的状态

SSL是一个状态机,其客户端和服务器端的状态是通过SSL握手协议来协调的,从而使得它们俩的状态机可以协同工作,尽管事实上状态并非是相同的。(译者注:握手协议是SSL的管理协议,状态变化时,可以发出管理信息,从而协调C/S的状态,尽管他们俩的状态并非是同一个状态)逻辑上说一共有两种状态,一种是当前运行的状态,另一种是在握手协议期间pending的状态,此外,还分离了读和写的状态。

当客户端或者服务器端收到一个change cipher spec(密码规范改变)消息时,它拷贝pending读状态到当前读状态;当握手过程结束的时候,客户端和服务器端会交换它们的change cipher spec消息(5.3节),然后通过新的协商好的cipher spec来通讯。

一个SSL会话可能包括多个安全连接,通讯的每一方都可以有多个并发的会话。

会话的状态包括下列元素:

会话标识符:服务器指定的一个任意字节序列,用于识别一个活动的或者重用的会话状态。

peer认证: X509.v3认证一个peer,该栏位可以为NULL。

压缩方法: 在加密前用于压缩数据的算法。

密码规范: 指定批量数据压缩算法(例如NULL、DES等)以及MAC算法(例如MD5和SHA)。它也指明了压缩算法的属性,例如hash_size等。

主密钥: 客户端和服务器端共享的48bit的密钥。

可重用: 标志位,用来表征这个会话是否可以用来初始化新的连接。

连接的状态包括下列元素:

服务器端和客户端随机数:客户端和服务器端为每个连接选择的一个随机字节序列。

服务器端MAC写密钥:MAC操作由服务器端写入的数据的密钥

客户端MAC写密钥: MAC操作由客户端写入的数据的密钥

服务器写密钥: 用于服务器端数据的加密和客户端数据解密的密钥

客户端写密钥: 用于客户端数据的加密和服务器端数据的解密的密钥

初始化向量:

队列数目: 每一方都保留了各自的每个连接中用于传输和接受消息的队列数目,当一方发送或者收到一个change cipher spec消息,对应的队列数目被置为0。队列数目是uint64型,因此不可以超过2^64-1个。


5.2 记录层(Record Layer)

SSL的记录层从更高层接收未处理的原始数据,并将其保存到任意大小的非空的块中。

5.2.1 分片

记录层将信息块中的数据分片为SSLPlaintext记录,它最大不超过2^14字节。记录层并不保留客户端数据的边界(例如,相同ContentType的客户端数据可能被合并到同一个SSLPlaintext记录中)。

struct {
uint8 major, minor;
} ProtocolVersion;
enum {
change_cipher_spec(20), alert(21), handshake(22),
application_data(23), (255)
} ContentType;
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
opaque fragment[SSLPlaintext.length];
} SSLPlaintext;


type: 处理分片信息的高层协议。

version: 使用的协议版本,当前是v3.0

length: 后面的fragment的长度(字节),应该不超过2^14。

fragment: 应用层的数据,这个数据对SSL是透明的,并由type指定的高层协议当作一个独立的块来处理。

注意:不同SSL记录层ContentType的数据可能被交叉存储,应用数据通常比其他content type的传输优先级要低。


5.2.2 记录压缩和解压

所有的记录都会被压缩,压缩算法由当前会话状态的压缩算法栏位来指定。通常总有一个活动的压缩算法,但是,这个栏位初始化的时候会被置为NULL。

压缩算法将一个SSLPlaintext结构体翻译为一个SSLCompressed结构体,压缩算法会在CipherSpec被重置的时候清除它们的比特位。

注意:CipherSpec是5.1节描述的会话状态的一部分,其详细的说明见附录A.7。


压缩必须是无损的,并且不可以增加内容的长度超过1024字节,如果解压函数遇到了一个SSLCompressed.fragment可能被解压出超过2^14字节的内容,它将发起一个fatal的解压错误。(5.4.2节)


struct {
ContentType type; /* same as SSLPlaintext.type */
ProtocolVersion version;/* same as SSLPlaintext.version */
uint16 length;
opaque fragment[SSLCompressed.length];
} SSLCompressed;


length: fragment的长度(字节),应该不超过2^14+1024.

fragment: SSLPlaintext.fragment的压缩形式。

注意:一个为NULL值的压缩算法是合法的,没有任何警告会发生(附录A.4.1)

实现注意:解压函数应当检查内容不会导致buffer的溢出。


5.2.3 记录载荷保护和加密规范(CipherSpec)

所有的记录都通过当前加密规范中指定的压缩和MAC算法来保护,总会有一个活动的加密规范,然而,初始化时它将被置为SSL_NULL_WITH_NULL_NULL,它不提供任何安全性。

一旦握手过程结束,双方已经共享了用于记录压缩和计算加密MAC的密钥。用于进行压缩和计算加密MAC的算法由CipherSpec指定,包含在CipherSpec.cipher_type中。压缩和MAC函数将SSLCompressed结果体翻译为SSLCiphertext结构体,解压函数则是相反的过程。传输也包含了一系列的字段来表示丢失、警告或者额外的信息。


struct {
ContentType type;
ProtocolVersion version;
uint16 length;
select (CipherSpec.cipher_type) {
case stream: GenericStreamCipher;
case block: GenericBlockCipher;
} fragment;
} SSLCiphertext;


type: 和SSLCompressed.type相同

version: 和SSLCompressed.version相同

length: 后面的SSLCiphertext.fragment的长度(字节),不超过2^14+2048(SSLCompressed.length + hash_size)

fragment: SSLCompressed.fragment的加密形式,包括MAC

5.2.3.1 NULL或者标准流加密

流加密将SSLCompressed.fragment结果体转化为SSLCiphertext.fragment结构体,流解密则是相反的过程。(见附录A.7)

stream-ciphered struct {
opaque content[SSLCompressed.length];
opaque MAC[CipherSpec.hash_size];
} GenericStreamCipher;

MAC是这样生成的:

hash(MAC_write_secret + pad_2 +hash (MAC_write_secret + pad_1 + seq_num +SSLCompressed.type + SSLCompressed.length +SSLCompressed.fragment)) 

 其中“+”表示连接。

pad_1 对MD5,重复0x36字符48次;对SHA,重复0x36字符40次。

pad_2: 对MD5,重复0x5c字符48次;对SHA,重复0x5c字符40次。

seq_num: 这条信息的队列数目。

hash: 这个加密方式的hash算法。

注意:MAC在加密之前就计算好了,流压缩压缩整个块,包括MAX。对于不使用同步化向量的流压缩(例如RC4),一个记录末尾的流压缩状态直接为后续的封包所用。如果压缩算法是SSL_NULL_WITH_NULL_NULL,那么压缩包括了认证操作(例如,数据没有被压缩且MAC为0表示MAC没有被用)。SSLCiphertext.length是SSLCompressed.length + CipherSpec.hash_size。

5.2.3.2 CBC(Cipher Block Chaining)块压缩

对于块压缩(例如RC2或者DES),压缩和MAC函数将SSLCompressed.fragment结构体翻译为SSLCiphertext.fragment结构体。

block-ciphered struct {
opaque content[SSLCompressed.length];
opaque MAC[CipherSpec.hash_size];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
} GenericBlockCipher;

MAC的生成和5.2.3.1一样。

padding: 该字段用于保证plaintext的长度是块压缩的块长度对齐而添加的内容。

padding_length: 该字段是padding的长度,必须比块压缩的块长度小,可以是0。

压缩的数据的长度SSLCiphertext.length应当比SSLCompressed.lengthpadding_lengthCipherSpec.hash_size的和要大。

注意:在CBC时,第一个记录的初始化向量由握手协议来提供,后续的初始化向量是前一个记录的最后一个压缩块。


5.3 密码规范改变协议(Change Cipher Spec Protocol)

密码规范改变协议用于加密策略中的信号变化,该协议包括单个由当前CipherSpec指定的方法(而不是pending的那个)加密并压缩的报文。该报文包含了一个单个字节,其值为1。

struct {
enum { change_cipher_spec(1), (255) } type;
} ChangeCipherSpec;

密码规范改变报文既可由服务器端也可以由客户端发送,用于通知接收方后续的记录将被刚才协商好的密码规范和密钥保护。接受到该报文,将引发接收方拷贝pending读状态到当前读状态。

客户端会在握手交换密钥和认证信息(如果有)之后发送密码规范改变报文,而服务器端会在成功处理客户端发送来的密钥交换报文之后,发送密码规范改变报文。一个意外的密码规范改变报文会产生一个unexpected_message警报(5.4.2节)。当重用上一个会话时,密码规范改变报文会在hello报文之后发出。


5.4 警报协议(Alert Protocol)

(略)

5.5 握手协议综述

SSL握手协议运行在记录层之上,会话状态加密参数是通过SSL的握手协议产生的。当一个SSL的客户端和服务器端开始通讯时,它们就协议版本、压缩算法、相互认证的方法(可选地)达成一致,然后使用公钥加密技术来生成公钥,上述过程都是在握手协议里面实现的,总结如下:

客户端发送client hello报文

服务器端必须响应server hello报文,否则会引发致命错误然后连接中断

client hello和server hello被用于建立增强的安全能力的客户端和服务器端之间的连接,它们建立了如下属性:协议版本、会话ID、密码规范以及压缩方法。另外还产生并交换了两个随机值:ClientHello.random和ServerHello.random

在hello报文之后,服务器端会发送它的证书,如果它将要被认证。另外,服务器key交换报文也可能被发送,如果要求的话(如果服务器没有证书,或者它的证书只用于签名)。如果服务器被认证,它还可能请求客户端的证书,如果这是所选的密码规范要求的。

然后,服务器端会发送server hello done报文,表示握手阶段的hello报文结束了,并等待客户端的响应。

如果服务器端发送了证书请求报文,那么服务器端要么发送证书报文,要么发送no_certificate警报。然后,发送客户端key交换报文,其内容基于server hello和client hello协商选出来的公钥算法生成。如果客户端发送的证书带有签名功能,那么一个数字签名证书认证报文会被发送,用于严格地认证这个报文。

这时候,客户端会发送密码规范改变报文(见5.3节),并拷贝pending CipherSpec到当前CipherSpec。然后,客户端立即基于新的算法、key和密钥来发送完成报文,作为响应,服务器端会发送它自己的密码规范改变报文、拷贝pending CipherSpec到当前CipherSpec并且基于新的CipherSpec发送完成报文。

这时,握手协议完成,客户端和服务器端可以交换后续数据了。

注意:为了防止流水线中断,ChangeCipherSpec是一个独立的SSL协议的Content Type,而不是一个真正的SSL握手报文。

当客户端和服务器端决定重用一个之前的会话,或者复制已有的会话时(而不是初始化新的安全参数),其报文流程如下:

客户端发送client hello,使用被复用的会话的ID,服务器端会比对它的会话cache,如果找到匹配的ID,那么服务器端会愿意在特定的会话状态下重新建立这个连接,从而发送一个server hello,其会话ID和客户端的相同。

这时,客户端和服务器端都必须发送密码规范改变报文,并直接进入完成报文阶段。

一旦重新连接建立,客户端和服务器端可以交互数据了。

如果匹配的ID没有找到,服务器端会生成一个新的会话ID,SSL客户端和服务器端就要进行完整的握手了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值