资源描述
SSL协议 Version 3.0 3/4/96
翻译—隋立颖
一 本文件的地位
本文件是一个Internet草案。Internet草案是Internet工程特遣组(ITEF)及其领域和工作组的工作文件。请注意,其他团体也可以发布Internet草案。
Internet草案自公布之日起至多六个月内有效。它可以随时被修改、被替换,或被其他文件所覆盖。把Internet草案作为文献来引用,除说明是“正在进展中的工作”以外,是不合适的。
要了解任何一个Internet的当前地位,请查阅如下网址:(美国东海岸),(欧洲),ftp.isi.edu(美国东海岸)以及munnari.oz.au(环太平洋地区)。其中Internet Drafts Shadow Directories目录下的1id-abstract.txt列表可提供这方面的信息。
二 摘要
本文制定了安全套接层协议第3.0版(SSL3.0)规范。SSL是一个提供Internet上的通信隐私性的安全协议。该协议允许客户端/服务器应用之间进行防窃听、消息篡改及消息伪造的安全的通讯。
三 简介
制定SSL协议的初衷是为通讯双方提供安全可靠的通讯服务,协议包含两个层次:其较低的SSL记录层协议位于某一可靠的传输协议(例如TCP[TCP]协议)之上;SSL记录层协议用来对其上层的协议进行封装。握手协议就在这些被封装的上层协议之中,它允许客户端和服务器彼此认证对方;并且在应用协议发出或收到第一个数据之前协商加密算法和加密密钥。这样作的原因是保证了应用协议的独立性,使低级协议对高级协议是透明的。
SSL协议提供的连接安全性具有以下三条属性
l 连接是安全的。在初始化握手协议协商加密密钥之后传输的消息均为加密的消息。加密的算法为单钥加密算法(例如DES[DES], RC4[RC4]等)。
l 对方的身份是可以通过非对称加密算法-即公钥加密算法(例如RSA[RSA], DSS[DSS]等)来验证。
l 连接是可靠的。所传输的消息均包含一利用签名私钥加密的消息文摘(MAC),以保证消息的完整性。安全杂凑(hash)函数(例如SHA, MD5等)被用来产生消息文摘(MAC)。
四 目标
按它们的优先级,SSL协议3.0的目标是
l 在通讯双方之间利用加密的SSL消息建立安全的连接。
l 互操作性。通讯双方的程序是独立的,即一方可以在不知道对方程序编码的情况下利用SSL 3.0成功的交换加密参数。
注意:并不是所有的SSL的实例(甚至在同一应用程序内)都可以成功的连接。例如,如果服务器支持一特定的硬件令牌(token),而客户端不能访问此令牌,则连接不会成功。
l 可扩展性。SSL寻求提供一种框架结构,在此框架结构中,在不对协议进行大的修改的情况下,新的公钥算法和单钥算法可以在必要时被加入。这样做还可以实现两个子目标
1. 避免产生新协议的需要,因而进一步避免了产生新的不足的可能性。
2. 避免了实现一完整的安全协议的需要。
相对的有效性。加密操作,尤其是公钥加密,对CPU来说是一种很耗时的事,因此SSL协议引入一可选的对话缓存(CACHE)来减少从头开始的连接的数目。同时,它还注意减少网络的活动。
五 此文档的目的
SSL协议版本3.0详细说明书的主要读者是要实现此协议的人和进行加密分析的人。此详细说明书主要是为这两类人而写的,所以它时刻注意反映这两类人的需要。因此在本详细说明书中(而不是写在附录中)以文本方式包含了许多与算法相关的数据结构和规则,使它们易于被访问。虽然本详细说明书包含了维护物理安全性所必须的策略,本详细说明书并不想提供关于服务和界面的定义。
六 描述语言(Presentation language)
本文档主要是描述外部表示(external representation)的数据的格式,所以用到了下列简单、基础而有点随意的定义的表示语法,这些语法在结构上来自不同的出处。虽然这些语法在结构上有点象程序设计语言C、在语法和目标上象XDR[XDR],但过分的强调这种类似是有害的。本描述语言的目的仅仅是描述SSL。
6.1 基本块长(Basic block size)
所有的数据项的表示均是显式说明的,基本数据块的长度为一字节(也就是说8比特)多字节的数据项是由从上至下、从左至右的多个字节连接组成。从字节流的角度来看,一多字节的数据项(在本例中是一数字)是通过下述公式形成的:
value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) | ... | byte[n-1];
这种字节的顺序关系是网络中常用的顺序关系即大endian格式。
6.2 杂项
注释以“/*”开始,以“*/”结束。
可选的部分是由将其包含进斜体的括号“[ ]”中而指定的。
单字节的包含不可解释的数据的实体的类型为opaque
6.3 向量(Vectors)
向量(一维数组)是一同类型的数据元素的流,向量的规模可以在编写文档时说明,也可以留至运行时才指明;不管在哪一种情况下,向量的规模(即大小)是由向量中字节的个数而不是向量中元素的个数决定的。
说明一新类型T’是一固定长度的类型T的向量的语法为:
T T'[n];
在这里,T’在数据流中占n比特,其中n是T的所占字节数的倍数。向量中包含数据元素的个数没有包含在数据流之中。在下例中,Datum被定义为三个连续的协议无法解释的字节的向量;而Data被定义为三个连续的Datum,一共包含9个字节
opaque Datum[3]; /* 三个协议无法解释的字节 */
Datum Data[9]; /* 三个连续的包含三个字节的向量 */
可变长向量可以通过指明合法长度的范围,即形如<最小长度..最大长度>的形式来定义,在编码时,在字节流中实际长度应在向量的内容之前,此实际长度是以数字的形式存储的,此数字应能表示此向量的最大长度(ceiling length)。空向量指的是一实际长度为零的向量。
T T'<floor..ceiling>;
在下例中,mandatory是一必须包含300到400字节的opaque类型数据的向量,它不能是空向量,其实际长度域占有两个字节,即uint16,足以表示400(见6.4节),而longer最多能表示800个字节,即400个uint16的数据元素,且<请合法使用软件>可以是空向量。它的编码包含一两字节的实际长度域。
opaque mandatory<300..400>; /* 长度域为两个字节,不能为空向量 */
uint16 longer<0..800>; /* 零至400个16比特的无符号整数 */
6.4 数字(Numbers)
基本的数字的数据类型是无符号字节(uint8)。其他所有的大的数字均是由6.1节中描述的固定长度的字节流连接而成,且它们均是无符号的。下列数字类型是预定义的:
uint8 uint16[2];
uint8 uint24[3];
uint8 uint32[4];
uint8 uint64[8];
6.5 枚举(Enumerate)
另一类稀疏的数据类型是枚举(enum),枚举类型的数据的取值范围只能是在其定义是声明的值。每一次定义均定义了一不同的类型。只有相同类型的枚举数据才可以相互赋值和比较,枚举类型的每个枚举元素均必须象下例中所示的那样,被赋一个值。由于枚举类型这的元素是没有顺序的,所以它们可以取任意顺序的不同的值。
enum { e1(v1), e2(v2), ... , en(vn), [(n)] } Te;
枚举类型的值在字节流中占据的空间的大小是其定义的取值范围中最大的可能值所占的空间大小。下列定义会使类型Color占有一个字节。
enum { red(3), blue(5), white(7) } Color;
你还可以通过指定一个无标签的值来强制枚举类型所占的字节数,这样就不需定义一冗余元素了。在下例中,类型Taste在字节流中占两个字节但只能在1,2或4中取值。
enum { sweet(1), sour(2), bitter(4), (32000) } Taste;
枚举类型的元素的名字只在定义的类型中是有效的。在第一个例子中,对类型Color中的第二个元素的完全限定引用为Color.blue。这样的限定当赋值的目标是被说明的时候时是可以忽略的。
Color color = Color.blue; /* 重复说明,但是合法的 */
Color color = blue; /* 正确,类型是隐含的 */
对于元素的值不会转化为外部表示的枚举类型,元素的取值信息是可以省略的。
enum { low, medium, high } Amount;
6.6 结构(Constructed type)
结构类型可以由基本的数据类型方便的建成,每一次说明均声明了一新的、唯一的类型,定义的语法类似于C语言中结构的定义。
struct {
T1 f1;
T2 f2 ;
...
Tn fn;
} [T];
在一结构中的各域可以象枚举中引用元素时的语法一样用类型名加域名引用,例如T.f2引用的是上例中的第二个域,结构的定义可以嵌套。
6.6.1 变体结构(Variant)
定义结构时可能根据环境的不同而有不同的变体,选择器必须为枚举类型的数据,以定义结构中可能的变体,且必须用case语句将select中声明的每个枚举元素不会起来。变体结构的结构体可以有一供其引用的标签。在运行时如何决定变体的机制并没有在描述语言中规定。
struct {
T1 f1;
T2 f2 ;
...
Tn fn;
select (E) {
case e1 : Te1 ;
case e2 : Te2 ;
....
case en : Ten ;
} [fv];
} [Tv];
例如:
enum { apple, orange } VariantTag;
struct {
uint16 number;
opaque string<0..10>; /* 可变的长度 */
} V1;
struct {
uint32 number;
opaque string[10]; /* 固定的长度 */
} V2;
struct {
select (VariantTag) { /* 变体的选择器是隐含的 */
case apple: V1; /*VariantBody的定义,标签= apple */
case orange: V2; /*VariantBody的定义,标签= orange */
} variant_body; /* 可选的变体标签 */
} VariantRecord;
变体结构可以通过在类型前指定选择器的值来限定(narrowed),例如:
orange VariantRecord
是类型VariantRecord的一限定,它包含类型为V2的variant_body。
6.7 加密属性(Cryptographic attribute)
数字签名、流加密、块加密和公钥加密这四项加密操作的加密属性分别为digitally-signed,stream-ciphered,block-ciphered和public-key-encrypted。对一个域进行何种加密操作是由在此域的类型说明前的合适的加密属性(关键字)决定的,加密的密钥是由当前对话状态字隐含给出的(见7.1节)。
在数字签名中,输入为一单向哈希函数(one-way hash function)。当用RSA算法进行签名时,用签名私钥对一36字节的结构进行签名,此36字节的结构是由两个哈希函数生成的,一个为SHA,另一个是MD5。当用DSS算法进行签名时,可以直接对由SHA哈希函数生成的20字节的结构进行签名。
在流加密中,明文的长度与由密钥产生的密文的长度是相同的。此密钥是由伪随机数发生器生成的安全的密钥,是根据时间的变化而变化的。
在块加密中,密文的每一块均被加密成一块密文。由于明文的长度并不是固定的,所以有可能在对明文(发出的数据)分块时产生一不满的块(块的长度通常为64比特),此时就需要将此不满的块的剩余部分填充数据,一般来说是填零。
在公钥加密中,单向限门函数被用来加密要发出的数据,用一给定公钥加密的数据仅能由相应的私钥解出,同样用一给定私钥加密的数据仅能由相应的公钥解出。
在下例中:
stream-ciphered struct {
uint8 field1;
uint8 field2;
digitally-signed opaque hash[20];
} UserType;
哈希函数的结果做为签名算法的输入,整个结构UserType用流加密进行加密。
6.8 常量(Constant)
有类型的常量可以通过在常量名前加上所希望的类型,并在常量名后给其赋上所期待的值来定义。未限定的类型(opaque,可变长向量,变体结构及带有opaque的结构)不能被赋值。多元素的结构和向量的所有域均应被赋值。
例如:
struct {
uint8 f1;
uint8 f2;
} Example1;
Example1 ex1 = {1, 4}; /* 令 f1 = 1, f2 = 4 */
七、 SSL 协议
SSL是一层次化协议。在每一层,消息均可以包含描述长度、消息的描述及消息的内容的域。SSL在传输消息时,首先将消息分为其可处理的数据块,可以进行压缩,将其封装为一带消息验证(MAC)的包,随之进行加密并传输所得到的加密后的消息。在收到消息时,首先解密,然后验证、解压缩并重新组合得到原有的消息,将此消息发向较高的层次。
7.1 对话及连接状态
SSL的对话是有状态的,是由SSL的握手协议来同步客户端和服务器的状态的,因而允许它们一致的操作而不管它们的协议状态是否是并行的。从逻辑上讲,状态被提到了两次,一次是当前的操作状态,而另一次是在握手协议中的未决状态。而且,还维持单独的读状态和写状态。当客户端或服务器收到change cipher spec消息时,它将未决读状态复制到当前读状态。当客户端或服务器发出change cipher spec消息时,它将未决写状态复制到当前写状态。当握手协商完毕时,客户端或服务器将彼此交换change cipher spec消息(见7.3节),这样它们就可以用新同意的cipher spec来进行通信了。
SSL对话可以包含若干次安全连接,而且每一方均可以同时有多个对话。
对话状态包含下列元素:
对话标识 一由服务器为标识当前活跃的对话或重新开始的对话而随机
选取的字节流。
对等证书 对等方的X509.v3[X509]证书,状态的此元素可以为空。
压缩方法 在加密之前压缩数据所采用的算法。
加密说明 指出所采用的数据加密算法(如没有采用加密算法,采用DES
等)和作消息文摘的算法(如MD5,SHA等),它还定义象
hash_size一类的加密的属性(见附录A.7)
主共享的秘密 客户端和服务器所共享的48比特的共享的秘密。
是否可以重开始 一标识此对话是否可以用来初始化新的连接的标志。
连接状态包含下列元素:
客户端和服务器的随机数 由客户端和服务器为建立一次连接而随机选取的一字
节流。
服务器的MAC写共享秘密 服务器在对数据进行消息验证(MAC)操作时所使用的
共享的秘密。
客户端的MAC写共享秘密 客户端在对数据进行消息验证(MAC)操作时所使用的
共享的秘密。
服务器的写密钥 服务器在对数据进行加密时所使用的加密密钥,此密
钥也是客户端进行解密时的解密密钥。
客户端的写密钥 客户端在对数据进行加密时所使用的加密密钥,此密
钥也是服务器进行解密时的解密密钥。
初始化向量 当用CBC方式进行块加密时,对于每一密钥系统都将维
护一初始化向量(IV)。此域的值是由SSL握手协议进行
初始化的,为以后使用的方便此后的每一记录的最终的
密文块被保存在记录的后面。
序列号 参与连接的每一方都为其发出的和收到的消息维护一独
立的序列号。当一方发出或收到Change Cipher spec
消息时,其序列号置为零。序列号的类型为Unit64,所
以序列号不能超过264 -1。
7.2 记录层
SSL记录层由更高的层次那里接收未加解释的任意长度的非空块。
7.2.1 打包
记录层将信息块分裂为小于或等于214字节的SSLPlainText记录。客户端消息的界限并不反映至记录层中(也就是说,具有同样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 协议的版本号。此文档所描述的是SSL版本3.0 (见附录A.1.1).
length SSLPlaintext的字节长度,此长度不应超过214
fragment 应用数据。此数据对由Type域中所指出的更高层次的协议是透明的,并被
视为一独立的块 。
注意: 不同的SSL记录层的CententType数据可以交叉存取,应用数据一般要比其他的
ContentType数据要求更低级的传输过程。
7.2.2 记录的压缩和解压缩
所有的记录均应用在当前的对话状态中定义的压缩算法进行压缩。一般地,此算法为当前活跃的压缩算法,但在初始化时它被定义成CompressionMethod.null。压缩算法将 SSLPlaintext结构转换为SSLCompressed 结构,当CipherSpec变换后,压缩函数将删除其状态信息。
注意: CipherSpec是在7.1节中所描述的对话状态的一部分, 对CipherSpec 中各域的引
用在本文档中是用表示语法来表达的。关于CipherSpec的更加详细的描述见附录
A.7.
压缩必须是无损压缩且对原文的长度的增加不超过1024比特。如果解压缩函数遇到一待解的超过214比特的SSLCompressed.fragment,它将产生一终止的decompression_failure 报警(见7.4.2节)。
struct {
ContentType type; /* same as SSLPlaintext.type */
ProtocolVersion version; /* same as SSLPlaintext.version */
uint16 length;
opaque fragment[SSLCompressed.length];
} SSLCompressed;
length SSLCompressed.fragment的长度(单位:字节)。长度不应超过214+1024。
fragment SSLPlaintext.fragment的压缩格式。
注意: 操作CompressionMethod.null是一标识性操作,没有任何一个域的值被改变
(见附录 A.4.1) 。
实现时请注意:解压缩函数的责任是保证消息不会造成内部的缓冲区溢出。
7.2.3 记录的有效负荷保护和加密说明(CipherSpec)
所有的记录均用在当前的加密说明(CipherSpec)中定义的加密算法和消息验证(MAC)算法所保护, 一般地,在SSL内部有一活跃的CipherSpec,但在初始化时,它的值为SSL_NULL_WITH_NULL_NULL, 从值并不提供任何安全性。只有当握手结束后,参与双方共享一用于加密记录和计算消息验证码(MACs)的公共秘密。进行加密和消息验证(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的长度(单位:字节)。长度不应
超过214+2048。
fragment 包含消息验证码(MAC)的SSLCompressed.fragment加密后的形式。
7.2.3.1 Null 或标准的流加密
流加密(包含BulkCipherAlgorithm.null –见附录A.7)将SSLCompressed.fragment结构转换为SSLCiphertext.fragment 流结构,或者反之,将SSLCiphertext.fragment结构转换为SSLCompressed.fragment 流结构。
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 + length + content));
其中“+”表示将前后连接起来。
pad_1 字符0x36 在MD5算法中重复48次或在SHA算法中重复40次。
pad_2 字符0x5c,与pad_1一样的重复。
seq_num 从消息的序列号。
hash 由cipher组合所决定的杂凑算法。
请注意,消息验证码(MAC)在加密之前就计算出来了。流加密加密的是包含消息验证码(MAC)在内的整个块。对于不用同步向量的流加密方法(如RC4),在记录后边的流加密方法的状态被简单的用在随后的包中,若CipherSuite是SSL_NULL_WITH_NULL_NULL,且加密包含指定的操作(也就是说,数据还未被加密且消息验证码(MAC)的长度为零,标志着不使用消息验证码(MAC)), 则SSLCiphertext的长度是 SSLCompressed的长度与CipherSpec.hash_size的和。
7.2.3.2密码分组链接(CBC)块加密
对于块加密(象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)与7.2.3.1节中描述的一样。
padding 为了使明文的长度成为加密块长度的倍数而添加的随机字节。
padding_length 填料的长度必须比加密块的长度小且可以为零,填料的长度应使结构
GenericBlockCipher的总长度是加密块长度的倍数
被加密的数据长度(SSLCiphertext.length)应比SSLCompressed的长度, CipherSpec.hash_size和填料的长度的总和多一。
注意: 对于CBC块加密来说,其第一个记录的CBC块链的初始化向量(IV)是由握手协议提供的,随后记录的IV是前一记录的最后一密文块。
7.3 更改加密说明cipher spec的协议
更改加密说明(cipher spec)的协议在加密策略中被用来通知参与各方这一改变。协议只包含一个在当前(不是未决的)CipherSpec下加密并压缩过的消息。此消息包含一个字节,其值为1。
struct {
enum { change_cipher_spec(1), (255) } type;
} ChangeCipherSpec;
更改cipher spec的消息可以由客户端或服务器发出来通知对方随后的记录将由刚协商好的CipherSpec和密钥来保护。收方收到此消息后,将读未决状态复制到当前读状态中。客户端在密钥交换握手和证书验证消息(如果有的话)之后发出更改cipher spec的消息,服务器则在成功的处理了客户端发来的密钥交换消息之后发出一更改cipher spec的消息。一意外的更改cipher spec消息应产生一unexpected_message报警(见 7.4.2节)。当重新开始一原有的对话时,更改cipher spec消息应在问候消息(hello messages)之后发出。
7.4 报警协议
由SSL记录层所支持的一种媒体类型为报警类型,报警消息带有此消息的严重程度的编码和对此报警的描述。最严重一级的报警消息将立即终止连接,在这种情况下,本次对话的其他连接还可以继续进行,但对话标识符必须无效以防止此失败的对话重新建立新的连接。象其他的消息一样,报警消息是利用由当前连接状态所指出的算法加密和压缩的。
enum { warning(1), fatal(2), (255) } AlertLevel;
enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
decompression_failure(30),
handshake_failure(40), no_certificate(41), bad_certificate(42),
unsupported_certificate(43), certificate_revoked(44),
certificate_expired(45), certificate_unknown(46),
illegal_parameter (47)
(255)
} AlertDescription;
struct {
AlertLevel level;
AlertDescription description;
} Alert;
7.4.1 关闭报警
客户端和服务器为避免截断攻击必须共享连接已关闭这一信息,它们中的任一方均可以初始化关闭信息的交换。
close_notify 此消息通知收方发出者不会在此连接内再发任何消息,当一次对话中
的所有连接都没有恰当的close_notify 消息而终止时,此次对话是
不能重新开始的。close_notify 消息的严重程度是警告级的
7.4.2 错误报警
在SSL握手协议中的错误处理是很简单的,当发现一个错误后,发现方将向对方发一消息。当传输或收到最严重一级的的报警消息时,连接双方均立即终止此连接。服务器和客户端均应忘记前一次对话的标识符、密钥及有关失败的连接的共享信息。SSL中定义了下列错误报警:
unexpected_message 收到一意外的消息,此报警通常是致命性错误的报警且不应在正
常的连接中被观察到。
bad_record_mac 当收到一带有不正确的MAC的记录时,将返回此报警。此报警通
常是致命性错误的报警。
decompression_failure 解密函数收到不合法的输入(如数据太长等),此报警通是致命
性错误的报警。
handshake_failure 收到一handshake_failure报警消息表明发出者不能接受现有的
选项所提供的安全参数的集合,此报警通常是致命性错误的报
警。
no_certificate 当被要求给出证书而没有合法的证书时,将发出一
no_certificate报警消息。
bad_certificate 当一证书被讹用、或者证书中不会的签名不能被正确的认证等
时,发出此报警。
unsupported_certificate 一有不被支持的类型的证书(如包含了用户自定义的扩展)。certificate_revoked 一被其发出者取消的证书。
certificate_expired 一过期了的或不合法证书。
certificate_unknown 由一些不明的发出者发出的证书所引起的证书的不可接受性。
illegal_parameter 在握手中的一个域的值溢出或与其他域的值不一致,此报警是致
命性错误的报警。
7.5 握手协议总揽
对话状态的加密的参数是由SSL握手协议产生的,握手协议是在SSL记录层的顶部操作的。当一SSL客户和服务器首次开始通讯时,它们就协议版本、加密算法的选择、是否验证对方及公钥加密技术的应用进行协商以产生共享的秘密,这一处理是由握手协议完成的,可以总结如下:
其中*表示不是必须发出的可选的或依赖于环境的消息
客户端首先发出客户问候消息(client hello message),服务器收到之后或者发出服务器问候消息(server hellomessage),或者发生一终止性的错误然后此次连接将无法建立客户和服务器问候消息(client hello message)被用来在客户端和服务器之间建立安全的性能的协商,客户和服务器的问候消息(client hello message)将产生了下列属性:协议版本号、对话标识符、加密套接字及压缩方法,而且产生了两个随机数ClientHello.random和 ServerHello.random并且相互交换。
在问候消息之后,若要求验证身份,服务器将发出其证书,另外,如果需要的话(例如,如果他们的服务器没有证书,或者其证书仅用来进行签名),
展开阅读全文