法国梧桐树树皮的用途:rfc 2246(tls) - general - 密码王国

来源:百度文库 编辑:中财网 时间:2024/04/30 00:32:41

RFC 2246TLS

TLS的一个优点是他的应用层协议是独立的。高层协议可以透明的位于TLS协议的顶层。然而,TLS标准并没有具体指明协议是如何用TLS来增加安全性的。如何初始化TLS握手和如何解释证书交换认证(authentication certificates exchangeed)的决定都留给设计者和运行在TLS之上的协议实施者来决定。

2.目标:

1.密码安全:TLS应该用于建立两个实体件的安全连接

2.可互操作性:独立的程序员应该可以开发出使用TLS的应用程序,它可以在不理解另一方编码的情况下成功的交换密码参数

3.可扩展性:TLS寻求一种框架,在这种框架下,新的公钥和(bulk)加密算法在需要是可以包含进去.这一点也可以完成两个子目标:可以防止产生新协议的必要(有引入新的弱点的危险) ;避免执行一个全新的安全库(security library)

4.相对有效性:密码操作比较容易耗费CPU,尤其是公钥操作。因此,TLS协议加入了选会话缓冲方式来减少必须从scratch建立连接的数目。而且,应该注意减少网络活动。

3.本文档目标

       这篇文档和TLS协议本上都是基于网景出版的SSL3.0协议的。本协议与SSL3.0协议的区别并不大。但是非常重要的是TLS1.0SSL3.0是不可互操作的(interoperate)(虽然TLS1.0包含了一种机制,这种机制可以使TLS可以back down to SSL3.0)。这篇文档的首要意图是针对于实施此协议的作者或者那些做密码分析的人。因此目的撰写了标准,并且,它的意图是使之反映这两个团体的需要。(这句翻译的很烂!)

       这篇文档的意图不在于提供服务定义的细节,也不提供接口定义,(although it does cover areas of policy as they are required for the maintenance of solide security).

4.描述语言

       这篇文档主要处理外部描述(in an external representation)的数据格式。将会使用如下基本并且有些随意的描述语法。在结构中,此语法有几个来源(the syntax draws from several sources in its structure).尽管在语法上他类似于变成语言”C”,在语法和意图上类似于XDR但是如果要寻找太多的相似点就有些冒险(翻译的更烂了)这种描述语言的目的仅仅用于TLS文档,而不是用于超出特定目标的普遍应用。

4.1基本块大小

       所有数据项的描述都是明确说明的基本数据块大小是1个字节(例如:8比特)。多字节数据项是字节的组合,从左到右,从上到下。借助于字节流,一个多字节项(本例中是一个数字)通过以下方式构成(使用c的注解语法)

value=(byte[0]<<8*(n-1)) | (byte[1]<<8*(n-2)) | ……| byte[n-1]

这种多字节值使用的字节顺序是网络字节常用的顺序,或者称为big endian格式。

4.2其他

注释以”/”开始并以”\”结束

可选的部分用双括号“[[]]“括起来

包含未解释数据(什么叫未解释数据)的但字节实体的类型是opaque

4.3矢量

一个矢量(一维数组)是一系列同类型的元素。矢量的大小可以在记录时指定或者在运行时指定。在任何一种情况下,长度指的是矢量中的字节的数量,而不是元素的数目。指明一个信的类型 ,他是类型T的固定类型矢量(The syntax for specifying a new type  that is a fixed length vector of type T我认为相关资料此处翻译有误 ),语法如下:

T [n]

这里 在数据流中占n个字节,nT的大小的倍数。矢量的长度没有包含在编码流中。

       在如下的例子中,Datum定义为协议没有解释的3个连续的字节,而Data3个连续的Datum,共占九个字节。

       Opaque Datum[3];                /*三个未被解释的字节*/

       Datum Data[9];                    /*3个连续的3自己矢量*/

       可变长度矢量通过指定一个合法长度的子区间来定义,包括使用注解。在编码时,实际长度在字节流中位于矢量内容的前面。长度是能容纳矢量所指定的最大长度字节的开销。实际长度域为0的可变矢量被称为空矢量。

       T [floor…ceiling]

       在下面的例子中,mandatory是一个必须包含300400字节的类型为opaque的矢量。他不能为空。实际的长度域占两个字节,即一个unit16,就足够表示值400(4.4)。另一方面,longer可以表示800字节的数据,或者400unit16元素,它可能为空。编码时矢量前要加2字节的真实长度域。编码矢量的长度必须是单个元素长度的偶数倍(例如,一个17字节的uint16矢量是非法的)。

       Opaque   mandatory<300..400>;

              /*长度域为2字节,不可为空*/

       uint16     longer<0..800>;

              /*0400uint16*/

4.4数字

       基本的数字数据类型是无符号字节(uint8)。所有更大的数字数据类型都是由固定长度字节序列构成,这些序列中的字节相互连接,并且都是无符号的。预先定义的数字类型:

uint8       uint16[2];

uint8       uint24[3];

uint8       uint32[4];

uint8       uint64[8];

       所有在规范中出现的值,都是以”network”或者“big endian”顺序存储的。用16进制01 02 03 04表示的uint32等于十进制数16909060

4.5枚举类型

       另外一个稀疏数据类型称为枚举类型(enum),一个枚举类型的域只能取定义中生命的值。每一个定义是不同的类型。只有同一类型的枚举可以相互赋值或者比较。如下例所示,每一个枚举必须赋一个值。因为枚举类型是无序的,可以是任意顺序,被赋予任意的值。

Enum {e1(v1),e2(v2),….en(vn),[[(n)]]} Te;

       枚举值在字节流中占据它被定义为最大有序值所需要的空间。下面的定义使得类型Color的域占一个字节。

       Enum{red(3),blue(5),white(7)} Color;

       也可以指定一个不赋予任何标志的值,用来强迫定义需要的宽度,而不必定义一个无用的元素。在下面的例子中,Taste将会在数据流中占两个字节( ),但仅仅有124三个值。

       Enum {sweet(1),sour(2),bitter(4),(32000)} Taste;

       一个枚举类型的元素必须在定义的类型的中。在第一个例子中,一个完全合格对类型第二个元素应该Color.blue。如果被赋值的目标类型指定非常,则无须如此严格的限制。

       Color color = Color.blue;     /*指定的过分,但是合法*/

       Color color = blue;               /*正确,类型隐含*/

       对于不会转换成外部表示(?)的枚举型,数字信息可以省略。

       Enum{low,medium,high}     Amount

4.6构造类型

       为了方便,可以从原始类型构造出结构类型。每一个说明一个新的、唯一的类型。定义的语法非常类似于C语言。

       struct {

         T1 f1;

         T2 f2;

         ...

         Tn fn;

} [[T]];

       一个结构类型域可以使用类似于枚举语法来引用。例如:T.f2指说明的类型的第二个域。结构定义可以嵌套。

      4.6.1变元

       定义的类型可以有基于某些在环境中可知条件的变元。选择器必须是枚举类型,这个枚举类型定义了结构本身定义的可能的变元。对每一个在选择中定义的枚举类型的元素,都必须有一个条件分支。可以给予变元结构一个标签,以便引用。在运行选择变元的机制在描述语言中没有规定。

       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;   /* 变元体, tag = apple */

               case orange: V2;  /* 变元体, tag = orange */

           } variant_body;      

} VariantRecord;

       变元结构可以通过在类型前说明器的值来使之合法化。例如:一个orangeVariantRecord是一个VariantRecord的窄化变元,它一个类型为V2的变元体。÷

4.7密码属性

       有四个密码操作:数字签名、流加密、块加密和公共密钥加密,他们分别完成。一个域的加密过程通过在域的类型说明前加上适当的关键字指定而说明,加密的密钥通过当前会话状态来给出。

       在数字签名中,使用单向哈希函数作为签名算法。一个进行数字签名的元素被加密为一个opaque类型的矢量< 1>,其长度由签名算法和密钥指定。

       RSA签名中,签名(用私钥加密)两个哈希(MD5SHA1)32-字节的结构。它用PKCS#1的块类型0和块类型1编码。

       DSS中,20字节的SHA哈希直接运行于数字签名算法中,而没有附加的哈希。它产生2个值,rsDSS签名是一个opaque类型矢量,如上所述,它的内容为DER编码如下:

       Dss-Sig-Value  ::=  SEQUENCE  {

            r       INTEGER,

            s       INTEGER

}

       在流密码加密中,明文是唯一的,它带有一个表示的输出量,这些输出隐秘的从安全密钥的伪随机密码发生器中产生。

       在块加密中,每一块明文被加密为为一个暗块,所有的块加密都是在CBC模式下进行的。并且所有被块加密的项都是块加密长度的倍数。

       在公共密钥加密中,使用了一个公共密钥算法加密数据,此方法为可以用相匹配的私钥解密。公用密钥加密元素是类型为Opaque矢量<0… -1>。长度由签名算法和密钥来指定。

       RSA加密值是用PKCS1中描述得块类型2编码的。在下面的例子中:

       stream-ciphered struct {

           uint8 field1;

           uint8 field2;

           digitally-signed opaque hash[20];

} UserType;

       哈希的内容作为签名算法的输入,整个结构用流密码加密。这个结构的长度,字段1和字段2应该是两字节,将两个字节加起来是签名的长度,将签名算法的输出的长度相加。这是基于这样的事实的:签名算法和密钥是先于加解密结构已知的。

4.8常量

       为了规范的原因,可以通过生命一个需要类型的符号,并对其赋值来定义一个有类型的常量。用户定义的类型(Opaque,变长度矢量,包含Opaque的结构)不可以被赋值。多元素的结构矢量的域不能被省略。

例如:For example,

       struct {

           uint8 f1;

           uint8 f2;

       } Example1;

 

       Example1 ex1 = {1, 4};  /* 赋值 f1 = 1, f2 = 4 */

5HMAC和伪随机函数

       WTLS记录和握手层中的一系列操作要求一个加密的MAC。这是由密文保护的安全摘要。没有MAC密码知道就不可能实现MAC。我们用于这一操作的结构称为HMAC,在[HMAC]中描述。HMAC可以用不同的哈希规则:MD5或者SHA-1等。用如下方式表示:HMAC_MD5(secret ,data)HMAC_SHA(secret,data)。而外的哈希算法可以通过密码组件来定义,用来保护记录数据。但是MD5SHA-1很难编码为这个版本协议的握手描述。此外,为了密钥产生或者批准的目的,需要一个结构将密钥扩展为数据的块。伪随机函数(PRF)以密文、密根和标识符为输入,生成任意长的输出。

       为了使PRF足够安全,使用两个哈希算法,在某种意义上,其中一个算法安全的时候他都能保证PRF是安全的。受限,我们定义数据扩展函数,P_hash(secret,data),他使用单一的哈希函数将密文和密根扩展为任意数量的输出。

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +

                              HMAC_hash(secret, A(2) + seed) +

HMAC_hash(secret, A(3) + seed) + ...

此处:“+”表示连接。

A()定义为:

A(0)=密根;

A(i)HMAC_hash(secret,A(I-1))

       P_hash(secret, seed)可以迭代任意多次,用以获得所需数量的数据。例如,如果使用P_SHA-1产生64字节的数据,就需要迭代4(通过A(4)),产生80字节的输出数据。最后迭代产生的16字节将会被抛弃,只留下64字节的数据。

       TLSPRF的产生是将密文分为两份,用其中的一半产生P_MD5,另一半产生P_SHA-1,然后单独使用或者将两者合用(then exclusive-or‘ing the outputs of these two expansion functions  together.)

       S1S2是密文的等长的两个部分,S1取自密文的第一部分,S2为第二部分。他们的长度是通过将所有的密文进行舍入计算再分为两半而得到的。但是,如果原始密文是奇数字节长,则S1的最后一个字节与S2的第一个字节是相同的。

L_S = l密文的字节长度t;

L_S1 = L_S2 = ceil(L_S / 2);

密文按照上述方法被分为两部分(可能有一个共享的字节)S1采用第一个L_S1个字节而S2使用后面的L_S2个字节。

PRF定义为两个伪随机流通过(exclusive-or’ing them together)混合起来的结果。

PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR

                                  P_SHA-1(S2, label + seed);

       标签是一个ASCII的字符串,他应该包含在精确的形式中,它不附带长度字节,或者后面附加空字符。例如,字符“slithy toves”通过哈希下面的字节来处理:

73 6C 69 74 68 79 20 74 6F 76 65 73

       注意:因为MD5只处理16字节的输出,SHA-1处理20字节的输出。内部迭代的边界不用调整。要产生80字节的输出会包括P_MD5通过A(5)迭代,而P_SHA-1只需通过A(4)迭代。

6TLS记录层协议

       TLS记录层协议是一个分层协议。每一层,消息可能包括长度域、描述域和内容域。记录层协议传输消息,将消息分段为可控制的块,也可以压缩数据,使用MAC,加密,传输结果。收到的数据解密、验证、解压缩、重组,再传给上层用户。

       本文档中描述了四个记录协议:握手协议、告警协议、改变密码规范协议和应用数据协议。为了扩展TLS协议,任何一个新的记录类型都应该在内容类型值后面立即为这里所描述的四种记录协议分配类型值(附录A.2)。如果TLS它不能理解的记录类型,就应该忽略它。任何用于TLS的协议都要仔细构思来处理各种可能的攻击。注意:记录的类型和长度是不被加密保护的,应该注意减小这些值的通信量分析。

6.1连接状态

       TLS的连接状态是TLS记录协议的操作环境。它指明了压缩算法、加密算法和MAC算法。此外,这些算法的参数要知道:在读和写两个方向上的用于连接的MAC密文、(bulk)加密密钥和初始化向量Ivs。逻辑上讲,一般有四个连接状态:当前读状态和当前写状态,未决读状态和写状态。所有的记录都在当前读状态和当前写状态下处理。所有未决状态的参数都是有TLS的握手协议设置的。握手协议可以选择性的将未决状态转换为当前状态,在这种情况下,适当的当前状态被处理,取而代之的是未决状态。未决状态重新初始化为空状态。将一个未用安全参数初始化的状态置为当前状态是不合法的。初始当前状态常常是没有规定使用的加密、压缩或者MAC算法。用于TLS连接的读状态和写状态的安全参数通过提供如下的值来设置:

Ø         连接终端:

不管在连接中此实体被认为是“客户端”还是“服务器端”。

Ø         (bulk)加密算法

用于(bulk)加密的算法。本文档包括算法的密钥大小、密钥的多少是保密的,是块密码还是流密码,密码的块大小(如果合适)和它是否为“可导出”密码。

Ø         MAC算法

用于消息认证的算法。本文档包括通过MAC算法返回的哈希的大小。

Ø         压缩算法

用于数据压缩的算法。本文档必须包含算法用于加密的所有信息。

Ø         主密钥

连接中两个对等实体间共享的48字节的密文

Ø         客户端随机数

客户端提供的32字节的值

Ø         服务器随机数

服务器提供德32字节的值

这些参数由如下的描述语言定义:

enum { server, client } ConnectionEnd;

  enum { null, rc4, rc2, des, 3des, des40 } BulkCipherAlgorithm;

  enum { stream, block } CipherType;

  enum { true, false } IsExportable;

  enum { null, md5, sha } MACAlgorithm;

  enum { null(0), (255) } CompressionMethod;

       /* The algorithms specified in CompressionMethod,

          BulkCipherAlgorithm, and MACAlgorithm may be added to. */

 

       struct {

           ConnectionEnd          entity;

           BulkCipherAlgorithm    bulk_cipher_algorithm;

           CipherType             cipher_type;

           uint8                  key_size;

           uint8                  key_material_length;

           IsExportable           is_exportable;

           MACAlgorithm           mac_algorithm;

           uint8                  hash_size;

           CompressionMethod      compression_algorithm;

           opaque                 master_secret[48];

           opaque                 client_random[32];

           opaque                 server_random[32];

} SecurityParameters;

记录层使用安全参数产生如下六项:

client write MAC secret

  server write MAC secret

  client write key

  server write key

  client write IV (仅对块密码)

  server write IV (仅对块密码)

       服务器在接收和处理记录时使用了客户端的写参数(and vice-versa)。用于由安全参数产生这些对象的算法在6.3节中描述。

       一旦设置了安全参数,产生了密钥。连接状态就可以通过使之成为当前状态实例化。在处理每一个记录时,当前状态都要被更新。每一个连接状态都包括如下的几个元素:

Ø         压缩状态:

压缩算法的当前状态

Ø         密码状态

加密算法的当前状态。由用于连接的预算(scheduled key)密钥组成。此外,对于运行于CBC模式下的块密码(用于TLS的唯一模式),密码状态也包括用于连接状态的IV,之后被更新,包含上一个处理过的加密或者解密块的密文。对于流密码,它包括任何必须的状态信息,这些状态信息允许流继续加密或者解密数据。

Ø         MAC密文

此连接的MAC密文如上产生

Ø         序列号

每一个连接状态都包含一个序列号,他们分别为读状态和写状态保留。当连接状态为活跃状态时,序列号必须置为0,序列号是一个uint64类型,而且大小不超过 1。一个记录之后序列号自增:特殊的是,在特定连接状态下传输的第一个记录,应该用序列号0

6.2记录层

TLS记录层从任意长度的非空块的高层接收未解释的数据。

6.2.1分段

记录层将信息块分段为携带 或小于 字节字节块的明文记录。客户端的消息边界(boundary)不保留在记录层(例如:相同内容类型的多客户信息可能会合成为一个单独的TLS明文记录或者一个单独的信息要被分在几个记录中)

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[TLSPlaintext.length];

} TLSPlaintext;

Ø         类型

高层协议用来处理封闭的片断

Ø         版本

实施协议的版本。这篇文档描述的是TLS1.0,使用版本{31}。使用值3.1是有历史原因的,版本TLS1.0是对SSL3.0的微小的修改。他能够兼容版本3.0

Ø         长度

下面的TLSTextplain.fragement的长度(以字节表示)。大小不超过

Ø         片断

应用数据。这个数据是透明的,而且被视为独立的块,这个块被类型域中描述的高层协议处理。

注意:不同的TLS记录层内容类型的数据可能会交错(interleave)。移用层数据一般相对于别的内容类型传输的优先级比较低(Application data is generally of lower precedence for transmission than other content types)

6.2.2记录的压缩与解压缩

       所有的记录都要经过当前会话状态中定义的压缩算法压缩。有一个活跃的压缩算法(There is always an active compression algorithm)。然而,最初它被定义为CompressionMethod.null。压缩算法将TLSPlaintext结构翻译为TLSCompressed结构。当一个连接状态被激活时,压缩函数被初始化为缺省状态。压缩必须无损耗,不能将内容长度增加到1024字节。如果解压缩函数遇到一个TLSCompressed.fragment,它的解压缩长度超过了 字节,应该报告一个致命的解压缩失败错误。

       struct {

           ContentType type;       /* TLSPlaintext.type相同 */

           ProtocolVersion version;/* TLSPlaintext.version *相同/

           uint16 length;

           opaque fragment[TLSCompressed.length];

} TLSCompressed;

Ø         长度

下面的TLSCompressed.fragment的长度(用字节表示)。大小不应该超过 +1024

Ø         片断

TLSCompressed.fragment的压缩形式。

注意:CompressionMethod.null操作是同一操作,没有域会被警告(A CompressionMethod.null operation is an identity operation; no fields are altered.)

运行注意:

解压缩负责保证信息不会导致内部缓冲的溢出。

6.2.3记录的负载保护

              加密和MAC函数将TLSCompressed结构翻译为TLSCiphertext结构。解密函数则反之。记录的MAC通常包括序列号,因此可以检测到丢失、多余或者重复的消息。

struct {

           ContentType type;

           ProtocolVersion version;

           uint16 length;

           select (CipherSpec.cipher_type) {

               case stream: GenericStreamCipher;

               case block: GenericBlockCipher;

           } fragment;

} TLSCiphertext;

Ø         类型

类型域与TLSCompressed.type一致

Ø         版本

版本域与TLSCompressed.version一致

Ø         长度

下面的TLSCiphertext.fragment的长度(以字节表示)。长度不应该超过 +2048

Ø         片断

TLSCompressed.fragment的加密形式,附带MAC

6.2.3.1空或者标准流密码

       流密码将TLSCompressed.fragment结构(包括BulkCipherAlgorithm.null -参见附录 A.6)转换为TLSCiphertext.fragment结构。

stream-ciphered struct {

           opaque content[TLSCompressed.length];

           opaque MAC[CipherSpec.hash_size];

} GenericStreamCipher;

MAC按如下方式产生:

HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +

  TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment));

此处“+”表示连接。

Ø         seq_num

记录的序列号

Ø         hash

SecurityParameters.mac_algorithm.指定的哈希算法

注意:MAC是在加密之前计算的。流密码加密全部的块,包括MAC。对于不使用同步矢量的流密码(例如RC 4),来自一个记录的末尾的流密码状态连续的包(For stream ciphers that do not use a  synchronization vector (such as RC4), the stream cipher state from the end of

  one record is simply used on the subsequent packet)。如果密码组件是TLS_NULL_WITH_NULL_NULL,则加密由一样的操作组成(数据未被加密,MAC的大小为0意味着未使用MAC

TLSCiphertext.lengthTLSCompressed.length加上CipherSpec.hash_size

6.2.3.2CBC块密码

对于块密码(例如RC2DES),加密和MAC函数将TLSCompressed.fragment结构转换为TLSCiphertext.fragment structures结构。

block-ciphered struct {

           opaque content[TLSCompressed.length];

           opaque MAC[CipherSpec.hash_size];

           uint8 padding[GenericBlockCipher.padding_length];

           uint8 padding_length;

       } GenericBlockCipher;

Ø         padding

填充数据增加一些值,迫使明文的长度密码块长度的证书倍。填充可以是多大255字节的任意长度的数据。和在TLSCiphertext.length作用的结果一样长,是块长度的整数倍。可能需要比必须值大的长度来防御基于分析交换信息的长度对于协议的攻击。填充数据矢量中的每一个uint8都用填充数据值填补。

Ø         padding_length

填充长度是这样的,GenericBlockCipher结构的总大小是密码块长度的整数倍。合法值是从0255,这个长度说明了除去padding_length域本身的密码域的长度。加密数据长度(TLSCiphertext.length)TLSCompressed.lengthCipherSpec.hash_sizepadding_length的和大1

例如:如果块长度是8字节,内容长度TLSCompressed.length的长度为61字节,MAC长度是20字节,填充数据前的长度是82字节。因此,填充长度模8就必须为6这样才能使总长度为8字节的证书倍(块长度)。填充数据可以是61422等,到254。如果padding_length是最小值6,填充数据就可能是6字节,每一个都包含值6。因此,在块加密之前的GenericBlockCipher的最后8个八位组可能是xx 06 06 06 06 06 06 06,其中xxMAC的最后一个八位组。

注意:在CBC模块中的块密码,当设置安全参数的时候,第一个记录使用的IV用别的密钥和密文产生。随后记录的IV是前一个记录的密钥块。

6.3密钥计算

              从握手协议提供的安全参数产生密钥、IvsMAC密文,记录协议需要一个算法。主密钥被哈希为一系列的安全字节。指定到MAC密文,密钥和当前连接状态的所需的不可导出的Ivs(见附录A.6)。密码规范需要一个客户端写MAC密文、一个服务器写MAC密文、一个客户端写密钥、一个服务器写密钥、一个客户端写Ivs,和一个服务器写Ivs。这些都是由主密钥依次产生的。未使用的值为空。

当产生密钥和MAC密文时,主密文被用作为熵(entropy)源。随机值提供未加密的掺杂素材,IVs作为可导出密码。

为了产生密码素材,计算:

key_block = PRF(SecurityParameters.master_secret,

                          "key expansion",

                          SecurityParameters.server_random +

                          SecurityParameters.client_random);

知道产生足够的素材。Key_block按如下分割:

client_write_MAC_secret[SecurityParameters.hash_size]

server_write_MAC_secret[SecurityParameters.hash_size]  client_write_key[SecurityParameters.key_material_length]

server_write_key[SecurityParameters.key_material_length]

client_write_IV[SecurityParameters.IV_size]

server_write_IV[SecurityParameters.IV_size]

client_write_IV server_write_IV仅为非出口的块密码产生。对于可出口的块密码,初始化向量是稍后产生的,如下所述。任何多出的key_block都会被抛弃。

运行时注意:

本文档定义的cipher spec中需要的最大的素材是3DES_EDE_CBC_SHA:它需要2*24字节的密钥,2*20字节的MAC密文,2*8字节的IVs,一共104字节的密码素材。可出口的加密算法(CipherSpec.is_exportable)需要如下的额外处理,用以推导出最后的写密钥:

final_client_write_key =

  PRF(SecurityParameters.client_write_key,

  "client write key",

  SecurityParameters.client_random + SecurityParameters.server_random);

 

final_server_write_key =

  PRF(SecurityParameters.server_write_key,

  "server write key",

  SecurityParameters.client_random + SecurityParameters.server_random);

可出口的加密算法从hello信息的随机数信息中单独推导出来。

iv_block = PRF("", "IV block", SecurityParameters.client_random +

SecurityParameters.server_random);

iv_block被分为如上的两个初始化向量:

client_write_IV[SecurityParameters.IV_size]

server_write_IV[SecurityParameters.IV_size]

注意:在这种情况下使用没有密文的PRF。这仅仅意味着密文的长度为零字节,对于PRF的哈希没有任何贡献。

6.3.1出口密钥产生例子

       TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5对每两个加密密钥,需要5个随机字节,对MAC密文需要16字节,总共42个密码素材。PRF的输出存储在key_block中,key_block被分割,写密钥被掺杂,因为这是一个出口的加密算法。

key_block               = PRF(master_secret,

                                     "key expansion",

                                     server_random +

                                     client_random)[0..41]

       client_write_MAC_secret = key_block[0..15]

       server_write_MAC_secret = key_block[16..31]

       client_write_key        = key_block[32..36]

       server_write_key        = key_block[37..41]

 

       final_client_write_key  = PRF(client_write_key,

                                     "client write key",

                                     client_random +

                                     server_random)[0..15]

       final_server_write_key  = PRF(server_write_key,

                                     "server write key",

                                     client_random +

                                     server_random)[0..15]

 

       iv_block                = PRF("", "IV block", client_random +

                                     server_random)[0..15]

       client_write_IV = iv_block[0..7]

server_write_IV = iv_block[8..15]

7.TLS握手协议

       TLS握手协议由三个子协议组成,用来允许对等端为记录层协商安全参数、认证、初始化协商的安全参数、彼此汇报错误条件。

       握手协议的任务是协商会话,该会话由下面几项组成:

Ø         会话标识符

服务器选择的任意字节长度的序列,表示一个激活的或者重建的会话状态

Ø         对等实体证书

对等实体的X509v3 [X509]证书。这一状态元素可能为空,

Ø         压缩算法

压缩算法用于在加密前压缩数据

Ø         密码规范

指明了数据加密算法(例如:NULLDES)MAC算法(MD5SHA-1)。同时定义了密码属性,例如hash_size。(参见附录A.6的形式定义)

Ø         主密钥

在客户端和服务器端共享的48-字节的主秘密。

Ø         可重组性

一个标志,指明此会话能否用来初始化新的连接

       这些项目用来产生安全参数,供应用层保护应用数据使用。许多连接都可以使用同样的会话通过TLS握手协议的重组实例化。

7.1改变密码规范协议

       改变密码规范协议的存在是为了密码策略的过渡。协议由单独的一条信息组成,这条消息是由当前连接状态(而非未决状态)加密和压缩的。该消息由值为1的单字节组成。

struct {

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

       } ChangeCipherSpec;

       客户端和服务器端均发送改变密码规范协议,通知接受方随后的记录都将用新协商出来的密码规范和密钥保护。接收到这条消息后,接受者立即通知记录层立即将未决读状态拷贝为当前读状态。在发送完这条消息后,发送端立即通知记录层将未决写状态激活写状态。(参见6.1)。改变密码规范协议是在握手中协商好安全参数后,校验结束信息前发送的。

7.2告警信息

       TLS记录层支持的内容类型之一是告警类型。告警信息传送消息的严重性和告警描述。一个致命级别的告警信息将导致连接的立即结束。在这种情况下,跟这个会话有关的其他连接可能会继续,但是会话标识符是无效的,用以防止用失败的会话建立新的连接。与其他的消息一样,告警信息是加密和压缩过的,如当前连接状态中所述。

       enum { warning(1), fatal(2), (255) } AlertLevel;

       enum {

           close_notify(0),

           unexpected_message(10),

           bad_record_mac(20),

           decryption_failed(21),

           record_overflow(22),

                decompression_failure(30),

                te_unknown(46),

           illegal_parameter(47),

           unknown_ca(48),

           access_denied(49),

           decode_error(50),

           decrypt_error(51),

           export_restriction(60),

           protocol_version(70),

           insufficient_security(71),

           internal_error(80),

           user_canceled(90),

          no_renegotiation(100),

  (255)

          } AlertDescription;

        struct {

            AlertLevel level;

           AlertDescription description;

          } Alert;

7.2.1Closure Alert

       客户端和服务器必须共享连接关闭信息,这样可以防止截断攻击。每一方都可能发起关闭信息的交换。

       close_notify

       这条信息通知接受者:发送者不会再在此连接下发送任何信息。如果任意连接都没有恰当的警告等级的close_notify消息而结束,则此会话是不可重组的。

       每一方都可以通过发送close_notify发起关闭。在关闭之后收到的任何数据都将被忽略。

       在关闭写的一方(write side)的连接前,每一方都需要发送close_notify警告。也需要另一方响应一个close_notify警告,并立即关闭连接,抛弃所有的未决状态。并不要求关闭的发起者等候连接读方(read side)close_notify警告的响应。

       如果使用TLS的应用协议提供了在连接关闭后,任何数据可以在下面传输(If the application protocol using TLS provides that any data may be carried over the underlying transport after the TLS connection is closed)。在提示应用层TLS连接已经关闭之前,TLS的实现必须收到close_notify警告的响应。如果应用层不再传输任何附加数据,但是只关闭下层传输连接,则实现就可以不等候响应信息而关闭传输。No part of this standard should be taken to dictate the manner in which a usage profile for TLS manages its data transport, including when connections are opened or closed.

NB:假设在销毁传输之前连接能够可靠的传递未决数据

7.2.2Error Alert

       TLS握手中的错误处理非常的简单。当检测到一个错误时,检测方发送一个消息给另一方,当发送或者收到一个致命错误信息时,双方理解结束连接。要求客户端和服务器都忘记任何的与失败连接相关的会话标识符,密钥和密文。

定义了如下的错误告警:

unexpected_message

收到一个不合适的消息。这个告警一般为致命等级,并且在适当实现的通信中从不应该被观察到(never be observed in communication between proper implementations

bad_record_mac

如果记录收到一个不正确的MAC,将会出现这个告警。这个告警一般为致命

decryption_failed

TLSCiphertext以无效的方式解密:或者是块长度的整数倍,或者检测时,填充数据不正确。这个告警一般为致命

record_overflow

收到的TLSCiphertext记录超过了 2048字节。或者解密到TLSCompressed的记录长度超过 1024字节。这个消息一般为致命。

Ø         decompression_failure

解密函数收到不恰当的输入(例如:可能收到超过最大长度的数据)。这个消息一般为致命

Ø         handshake_failure

收到handshake_failure告警信息表明发送者在给定可选项下不能协商出一套可行的安全参数。这是消息一般为致命

Ø         bad_certificate

证书是不正确地,包含不能正确验证的签名等。

Ø         unsupported_certificate

不支持类型的签名

Ø         certificate_revoked

证书被签名者撤销

Ø         certificate_expired

证书已经过期或者当前是无效的

Ø         certificate_unknown

Some other (unspecified) issue arose in processing the certificate, rendering

Ø         illegal_parameter

握手中的域超出范围或者与其他的域不一致。这个告警消息为致命

Ø         unknown_ca

无效的证书链或者获得部分证书链,因为不能定位CA证书或者不能匹配已知的、可信CA,所以证书是不可得的,这个告警信息是致命的。

Ø         access_denied

收到一个有效的证书,但是当应用访问控制时,发送者决定不处理协商。这个告警消息一般为致命。

Ø         decode_error

因为某些域超出了指定的范围或者消息的长度不正确,因此消息不能译码。这个告警信息一般为致命

Ø         decrypt_error

握手密码操作失败,包括不能正确的验证签名、解密密钥交换或者验证一个结束信息

Ø         export_restriction

协商与检测到的出口限制不一致。例如:企图为RSA_EXPORT方法传送1024比特的ephemeral密钥。这个告警信息一般为致命。

Ø         protocol_version

客户端企图协商的协议版本是可知的,但是不支持(例如:老的协议版本因为安全员应要避免使用)。这个消息一般为致命。

Ø         insufficient_security

当协商的失败主要是因为服务器需要密码比客户端所支持的更安全时,返回的取代handshake_failure的信息。这个告警信息一般为致命

Ø         internal_error

与对等实体不相匹配或者协议的不正确而导致不能继续的内部错误(例如内存分配失败)。这个告警信息一般为致命

Ø         user_canceled

握手因为某些与协议无关的原因而被取消。如果用户在握手结束后取消操作,通过发送close_notify消息关闭连接可能更为合适。这个告警应该跟随一个close_notify。这个告警信息仅仅为一个警告。

Ø         no_renegotiation

客户端发送的响应问候请求的或者在初始化握手后服务器响应客户端问候信息的消息。其中之一都会导致重新协商。如果不合适,接受者应该响应此告警。在这一点上(at that point),源请求者可以决定是否继续进行连接。One case where this would be appropriate would be where a server has spawned a process to satisfy a request;可能在开始阶段就收到安全参数(密钥长度,认证等),以后可能改变比较困难。这个消息仅为警告。

       对于警告级别没有明确声明的所有错误,发送方可以自己决定是致命错误或者不是。如果收到一个警告级别的错误信息,接收方可以自己决定将他视为致命或者不是致命错误。但是,传送的为致命级别的错误就必须视为致命信息。

7.3握手信息概述

       会话状态的密码参数是TLS握手协议产生的,它在TLS记录层的顶端操作。当TLS的客户端和服务器端开始通信时,他们协商协议版本、选择密码算法、进行互相认证(可选)、用公钥加密技术产生共享密钥。

TLS的握手协议包括如下几个步骤:

Ø         交换Hello信息,协商算法、交换随机数、检查会话重组

Ø         交换允许客户端和服务器端协商预主秘密的必要的密码参数

Ø         交换证书和密码信息,使得客户端和服务器端进行认证

Ø         从预主秘密和给定随机数产生主秘密

Ø         为记录层提供安全参数

Ø         允许客户端和服务器端检测实体是否计算出相同的安全参数,握手是否在没有攻击的情况下发生的

注意:上层不能过渡依赖于TLS协商出的对等实体间最健壮的连接:有很多种中间人攻击的方法使得对等实体选择他们支持的安全性最差的方法。协议设计用来减小这种风险,但是仍然存在攻击:例如:攻击者可以堵塞安全服务运行的端口,或者得到一个实体,用以协商不需认证的连接。最基本的原则是高层必须知道他们的安全需求是什么,并且从不通过信道传输低于安全需求的信息。TLS协议是安全的,因为任一密码组件提供他们承诺级别的安全:如果同一个已认证了它的证书的主机协商一个RSA密钥交换的1024比特的3DES算法,你就可以认为他是安全的。

然而,不要在40比特的安全连接上发送数据,除非你认为数据不如试图解除它的加密有意义。

这个目标可以通过握手协议达到,可以总结如下:

客户端发送Hello信息,服务器端必须响应一个Hello信息,否则将会导致一个致命的错误,连接将失败。客户端Hello信息和服务器端Hello信息客户端和服务器端安全增强能力(security enhancement capabilities)。客户端Hell信息和服务器端的Hello信息建立如下的属性:协议版本、会话ID、密码组件和压缩算法。此外,产生并交换两个随机数:ClientHello.randomServerHello.random。实际上密钥交换使用了四个信息:服务器证书、服务器密钥交换、客户端证书和客户端密钥交换。可以通过为这些信息指定格式产生新的密钥交换方法,定义客户端和服务器端协商共享密钥使用的消息,密文应该足够长。目前定义的密钥交换方法交换长度为48128字节的范围内的密文。

Hello信息之后,如果要被验证的话,服务器发送自己的证书。此外,如果要求(例如:服务器没有证书,或者证书只为签名用)必须发送服务器密钥交换信息。如果服务器被认证,它也可以要求客户端发送客户端证书,如果它适合于所选的密码组件。现在服务器发送Hello done信息,暗示握手协议的Hello信息阶段结束。服务器等候客户端响应。如果服务器发送了证书请求消息,客户端就必须要发送证书。客户端的密钥交换信息此时发送,信息的内容依赖于客户端Hello信息和服务器Hello信息协商的密钥算法。如果客户端发送了有签名能力的证书,则发送一个数字签名证书验证信息明确验证证书。

此时,客户端发送一个改变密码规范信息,客户端将密码规范的未决状态复制为当前密码规范。客户端立即发送用协商的新的算法、密钥和密文加密的结束信息(finished)。作为响应,服务器发送自己的改变密码规范信息,将未决状态改为当前密码规范状态,发送使用新的密码规范的结束信息(finished)。至此,握手信息结束,客户端和服务器端开始交换应用层数据。

(流程图如下:)

Client                                               Server

      ClientHello                  -------->

                                                      ServerHello

                                                     Certificate*

                                               ServerKeyExchange*

                                               CertificateRequest*

                                 <--------        ServerHelloDone

      Certificate*

      ClientKeyExchange

      CertificateVerify*

      [ChangeCipherSpec]

      Finished                     -------->

                                               [ChangeCipherSpec]

                                  <--------             Finished

Application Data              <------->     Application Data

图一:完全握手的信息流程

*表示并不一定发送的可选的或者依情况而定的信息

注意:为了避免管道延迟,改变密码规范协议(ChangeCipherSpec)是一个独立的TLS协议内容类型,并不是真正意义上的TLS握手信息。当客户端和服务器端决定重组以前的会话或者复制一个已存在的会话(而不是重新协商新的安全参数),流程如下:

客户端发送具有要重组的会话的会话ID的客户端Hello信息,服务器端检查它的会话缓冲是否匹配。如果发现有匹配的,而且服务器端也同意在指定的状态下重新建立连接。此时,客户端和服务器端必须发送改变密码规范信息,并直接处理结束信息。一旦重新建立完成,客户端和服务器端就可以直接交换应用层数据了。(数据流图如下),如果没有匹配的会话ID,服务器产生一个新的会话IDTLS的客户端和服务器端进行一个完全握手。

      Client                                                Server

      ClientHello                   -------->

                                                       ServerHello

                                                [ChangeCipherSpec]

                                    <--------             Finished

      [ChangeCipherSpec]

      Finished                      -------->

Application Data              <------->     Application Data

图二:简单握手的数据流

每一个信息的内容和意义将在下面的章节中详细描述

7.4握手协议

TLS的握手协议是TLS记录协议定义的高级的客户之一(defined higher level clients)。这个协议用来协商会话的安全属性。握手信息提供给TLS记录层,在记录层被封装为一个或多个TLSPlaintext结构。他们按照当前激活会话状态的说明处理和传输。

enum {

           hello_request(0), client_hello(1), server_hello(2),

           certificate(11), server_key_exchange (12),

           certificate_request(13), server_hello_done(14),

           certificate_verify(15), client_key_exchange(16),

           finished(20), (255)

       } HandshakeType;

 

       struct {

           HandshakeType msg_type;    /* handshake type */

           uint24 length;             /* bytes in message */

           select (HandshakeType) {

               case hello_request:       HelloRequest;

               case client_hello:        ClientHello;

               case server_hello:        ServerHello;

               case certificate:         Certificate;

               case server_key_exchange: ServerKeyExchange;

               case certificate_request: CertificateRequest;

               case server_hello_done:   ServerHelloDone;

               case certificate_verify:  CertificateVerify;

               case client_key_exchange: ClientKeyExchange;

               case finished:            Finished;

           } body;

       } Handshake;

握手协议信息在下面按照他们必须发送的顺序描述。按照不希望的顺序传送握手信息会导致致命错误,但是,不需要的握手信息可以被省略。但是顺序中有一个例外:证书信息在握手中使用了两次(从客户端到服务器端,然后再从服务器端到客户端),但是只在第一个位置描述。不受顺序约束的一个信息是Hello request信息,可以在任何时间传送,但是如果是在它是在握手中间到达的,客户端应该忽略它。

7.4.1Hello messages

       Hello阶段的信息是用来在客户端和服务器端交换增强安全性能的参数的。当会话开始时,记录层连接状态的加密、哈希和压缩算法均初始化为Null。当前连接状态用于重协商消息。

7.4.1.1Hello Request

此消息发送时间:

服务器端可以在任何时间发送Hello Request消息。

消息含义:

Hello Request只是通知客户端它应该在方便的时候发送Hello信息再进行协商处理。如果客户端此时正在协商一个会话或者客户端可能,如果它希望的话,响应一个no_renegotiation警告,此消息则应该被忽略。因为握手消息在应用层数据之前传输,所以期望可以在收到几个记录后就开始协商过程。如果服务器发送了Hello消息,但没有收到客户端的响应Hello信息,将产生一个致命的告警,并关闭连接。

发送了hello request之后,在之后的握手协商结束之前,服务器都不应该再重复请求。

消息结构:

struct { } HelloRequest;

注意:Note: This message should never be included in the message hashes which are   maintained throughout the handshake and used in the finished messages and the certificate verify message

这个消息不应该包含在贯穿于整个我数的哈希消息中,他用在结束信息和证书验证消息中

7.4.1.2Client hello

l         消息发送时间:

当客户端第一次连接到服务器端时,需要发送Hello信息作为第一个消息。客户端也可以hello request的响应发送hello消息,或者在一个已经存在的连接中为了重新协商连接参数而主动发起。

l         消息结构:

客户端的hello消息包括一个随机结构,在协议中以后会使用。

struct {

              uint32 gmt_unix_time;

              opaque random_bytes[28];

           } Random;

Ø         gmt_unix_time

对应于发送者内部时钟的UNIX 32-bit格式的当前的时间与日期(秒数从格林尼治时间199711的午夜开始)。时钟不需要通过基本的TLS协议设置的非常准确。高层或者应用协议可能定义额外的需求。

Ø         random_bytes

由安全的随机数产生器产生的28个字节。

客户端的问候消息包含一个变长度的会话标识符。如果不为空,此值用来标识相同的客户端和服务器端之间的会话,客户端可能重用他们之间的安全参数。会话标识符可能来自于早期的连接,本次连接或者另外一个当前激活的连接。如果客户端仅仅想更新随机参数的结构,取得连接的值,第二种选择就比较有用。第三种选择使建立几个独立的连接成为可能,而这个过程不需要重复完全握手协议。这些独立的连接可以是连续产生,也可以是同时产生。a SessionID becomes valid when the handshake negotiating it completes with the exchange of Finished messages and persists until removed due to aging or because a fatal error was encountered on a connection associated with the session.当握手协商通过交换finised消息结束后,会话ID生效,一直到因为aging或者在与会话相关的连接中遇到致命错误时除去。

服务器定义的会话ID的实际内容为:

opaque SessionID<0..32>;

警告:

因为会话ID是没有经过加密的,或者直接用MAC保护(or immediate MAC protection),服务器不能在其中放置保密信息,或者使用假的会话ID的内容导致安全性被破坏。(注意,作为整体的握手内容(hat the content of the handshake as a whole),包括sessionID,都在握手的最后由finished信息交换保护)

密码组件列表,在客户端Hello信息中从客户端传给服务器端,包含客户端支持的的按优先顺序排列的密码算法的组合。每一个密码组件定义了一个密钥交换算法,一个对称加密算法(包括密钥长度)和MAC算法。服务器选择一个密码组件,如果没有合适的,返回一个握手失败告警并且关闭连接。

uint8 CipherSuite[2];    /*密码组件选择器*/

客户端的hello包括客户端支持的压缩算法列表,按照客户端的优先顺序排列。

enum { null(0), (255) } CompressionMethod;

       struct {

           ProtocolVersion client_version;

           Random random;

           SessionID session_id;

           CipherSuite cipher_suites<2..2^16-1>;

           CompressionMethod compression_methods<1..2^8-1>;

       } ClientHello;

Ø         client_version

客户端在会话中期望使用的TLS的协议版本号。这个应该是客户端支持的最高版本(最高值)。对于本文档中的版本,版本号应该为3.1(参见服务E的向后兼容的细节)

Ø         random

客户端产生的随机结构

Ø         session_id

客户端希望用于本次连接的会话的ID。如果没有session_id或者客户端希望产生新的安全参数时,此值为空。

Ø         cipher_suites

客户端支持的密码选择列表,按客户端的优先顺序。如果session_id不为空(意味着会话是会话重组请求),这个矢量必须至少包括来自于会话的cipher_suites。值在附录A.5中定义。

Ø         compression_methods

客户端支持的压缩算法列表。依客户端优先顺序排列。如果session_id不为空(意味着会话是会话重组请求),就必须包含来自于会话的compression_method。这个矢量必须包含,并且所有的实现都必须支持CompressionMethod.null。因此,客户端和服务器端将可以协商压缩算法。

在发送客户hello信息后,客户端开始等候服务器端的响应。从客户端返回的除了hello信息的所有其他握手信息都将被视为致命错误。

Forward compatibility note

In the interests of forward compatibility, it is permitted for a client hello message to include extra data after the compression methods. This data must be included in the handshake hashes, but must otherwise be ignored. This is the only handshake message for which this is legal; for all other messages, the amount of data in the message must match the description of the message

In the interests of forward compatibility,在压缩算法之后允许客户的hello信息包括额外数据。这些数据必须包含在握手的哈希中,否则将必须被忽略。这是唯一一个这样可以为合法的握手信息。对于其他所有消息,所有消息的数据的数量必须由消息描述的严格匹配。

7.4.1.3 Server hello

l         消息发送时间:

服务器端在能找到可接受的算法组件是,用此消息来响应客户端的hello消息。如果找不到这样的匹配,将响应一个握手失败告警。

l         消息结构

struct {

           ProtocolVersion server_version;

           Random random;

           SessionID session_id;

           CipherSuite cipher_suite;

           CompressionMethod compression_method;

} ServerHello;

Ø         server_version

这个域将包含客户端hello信息中的较低的版本和服务器支持的最高版本。本规范的版本为3.1(参见附录E中的向后兼容性的细节)

Ø         random

客户端产生的结构,与ClientHello.random独立且不相同

Ø         session_id

相应于本次连接的会话的标识符。如果ClientHello.session_id不为空,服务器将查找自己的会话缓冲区,寻找匹配的数据。如果找到相匹配的,并且服务器端愿意用指定的会话状态建立新的连接,服务器端就响应一个同客户端提供的相同的值。这就意味这会话的重组,而且指明双方直接处理finished信息。否则,这个域将包含一个新的值用来标识新的会话。服务器可能返回一个空的session_id表明会话不会被存储,因此就不能被重组。如果会话要被重组,就必须使用之前协商的相同的密码组件。

Ø         cipher_suite

服务器从客户端的ClientHello.cipher_suites列表中选择的单独的一个密码组件。对于重组的会话,这个域是重组的会话状态的值。

Ø         compression_method

从客户端的ClientHello.compression_methods列表中选择的单独的一个压缩算法。对于重组的会话,这个域是重组的会话状态的值。

7.4.2 Server certificate

l         消息发送时间

当协商好的密钥交换方法不为匿名是,服务器端必须发送证书。这个消息一般是紧跟在服务器端的hello信息之后的。

l         消息含义

证书类型必须适合于选择的密码组件的密钥交换算法,一般为X.509格式证书。必须包含一个与如下的密钥交换方法相匹配的密钥。除非特殊声明,否则证书的签名算法必须与证书密钥算法一致。除非特别声明,否则公钥可以为任意长度。

密钥交换算法证书密钥类型:

RSA                     RSA公钥;证书必须允许密钥用于加密

RSA_EXPORT            长度大于512比特的可以用于签名的RSA公钥,或者小于等于512比特用于加密或者签名的密钥

DHE_DSS                DSS 公钥

DHE_DSS_EXPORT          DSS 公钥.

DHE_RSA                 可以用于签名的RSA公钥

DHE_RSA_EXPORT        可以用于签名的RSA公钥

DH_DSS                  Diffie-Hellman密钥. 用于签名证书的算法是DSS

DH_RSA                  Diffie-Hellman密钥. 用于签名证书的算法是RSA

IETF PKIX工作组定义的证书profiles,密钥和密码格式。如果使用了密钥用法扩展,数字签名比特就必须为密钥的签名而设置(the digitalSignature bit must be set for the key to be eligible for signing,)如上所述。密钥加密比特也必须为加密设置,如上所述。密钥协商必须设置为Diffie-Hellman认证。

l         消息结构

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

       struct {

           ASN.1Cert certificate_list<0..2^24-1>;

} Certificate;

Ø         certificate_list

X.509V3证书序列()。发送者证书必须处于列表首位。接下来的证书必须直接认证它之前的证书。因为证书的验证需要根密钥单独的,自签名的证书,它声明了根证书的权利可能从证书链中被省略,在此,假设远程终端必须已经拥有了根证书,以便在任意情况下验证它。

相同的消息类型和结构用于用于对于证书请求消息的响应中。注意:在响应服务    器证书认证请求时,如果客户端没有合适的证书就不发送证书。

注意:PKCS #7 [PKCS7]不用作证书矢量的格式,因为PKCS #6 [PKCS6]扩展证书未使用。而且PKCS #7定义了SET而非SEQUENCE,使得解析列表的任务更加困难。

 

7.4.3 Server key exchange message

l         消息发送时间

在服务器证书信息发送之后立即发送此消息(或者在服务器hello消息之后,如果是匿名

协商)。如果证书消息(如果发送)没有足够的数据让客户端交换预主秘密,服务器发送此消息。对于如下的密钥交换方法,此项为真:

RSA_EXPORT (如果服务器证书中的公钥大于512比特)

  DHE_DSS

  DHE_DSS_EXPORT

  DHE_RSA

  DHE_RSA_EXPORT

  DH_anon

为如下的密钥交换方法发送服务器密钥交换信息是不合法的:

RSA

  RSA_EXPORT (如果服务器证书中的公钥长度小于或等于512比特)

  DH_DSS

  DH_RSA

l         消息含义

消息发送密码信息,使得客户可以交换预主秘密:用于加密预主秘密的RSA公钥,或者完成密钥交换的Diffie-Hellman公钥(结果是成为预主秘密)。因为为TLS额外定义了包含了新的密钥交换算法的密码组件,服务器的密钥交换消息只有在与密钥交换算法相关的证书类型不能为客户端交换预主秘密提供足够的信息时发送。

注意:相应于美国目前的出口法律,大于512比特的RSA系数不能用于从美国出口的软件的密钥交换中。使用这条消息,编码在证书中的较大的RSA密钥可能为RSA_EXPORT密钥交换方法的临时短的RSA密钥签名。(With this message, the larger RSA keys encoded in certificates may be used to sign temporary shorter RSA keys for the RSA_EXPORT key exchange method.)

l         消息格式

enum { rsa, diffie_hellman } KeyExchangeAlgorithm;

       struct {

           opaque rsa_modulus<1..2^16-1>;

           opaque rsa_exponent<1..2^16-1>;

} ServerRSAParams;

Ø         rsa_modulus

临时RSA密钥的模数

Ø         rsa_exponent

临时RSA密钥的公用指数

 

struct {

           opaque dh_p<1..2^16-1>;

           opaque dh_g <1..2^16-1>;

           opaque dh_Ys<1..2^16-1>;

} ServerDHParams;     /* 短的DH参数 */

Ø         dh_p

Diffie-Hellman运算中的素数模。

Ø         dh_g

Diffie-Hellman运算中的生成元

Ø         dh_Ys

服务器的Diffie-Hellman公值 (  mod p)

struct {

           select (KeyExchangeAlgorithm) {

               case diffie_hellman:

                   ServerDHParams params;

                   Signature signed_params;

               case rsa:

                   ServerRSAParams params;

                   Signature signed_params;

           };

} ServerKeyExchange;

Ø         params

服务器密钥交换参数

Ø         signed_params

对于非匿名密钥交换,对应于params值的哈希(参数值先散列,在签名)

md5_hash

  MD5(ClientHello.random + ServerHello.random + ServerParams);

  sha_hash

  SHA(ClientHello.random + ServerHello.random + ServerParams);

  enum { anonymous, rsa, dsa } SignatureAlgorithm;

  select (SignatureAlgorithm)

       {   case anonymous: struct { };

           case rsa:

               digitally-signed struct {

                   opaque md5_hash[16];

                   opaque sha_hash[20];

               };

           case dsa:

               digitally-signed struct {

                   opaque sha_hash[20];

               };

       } Signature;

7.4.4 Certificate request

l         使用时间

如果选择的密码组件合适(if appropriate for the selected cipher suite),非匿名的服务器可以随时请求客户端的证书。如果发送此消息,则应该在服务器密钥交换信息之后立即发送(如果发送;否则在服务器证书消息之后)

l         消息结构

enum {

           rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),

           (255)

       } ClientCertificateType;

opaque DistinguishedName<1..2^16-1>;

       struct {

           ClientCertificateType certificate_types<1..2^8-1>;

           DistinguishedName certificate_authorities<3..2^16-1>;

} CertificateRequest;

Ø         certificate_types

这个域是请求证书类型的列表,按服务器优先顺序排列

Ø         certificate_authorities

可接受的认证权威(CA)的DN列表。DN可能包括期望的根CA和从属CADN等。因此,这个消息即可以用于描述一致的根CA,也可以描述期望的认证空间(desired authorization space)。

注意:DNX.509中获得

注意:匿名服务器请求客户端认证,将会导致致命的handshake_failure告警。

7.4.5 Server hello done

l         使用时间

服务器发送此消息指明服务器hello和相关消息的完成。发送此消息之后,服务器等候客户端的响应。

l         消息含义

此消息意味着服务器已经结束了发送支持密钥交换的消息,客户端可以处理他的密钥交换过程。

收到服务器的Server hello done消息,如果需要,客户端验证服务器提供的有效证书,检查服务器的hello参数是否可得

l         消息结构

struct { } ServerHelloDone;

7.4.6 Client certificate

l         使用时间

这是在收到服务器Server hello done信息之后可以发送的第一条消息。这条消息只有在服务器发送证书请求时才发送。如果没有合适的信息,客户端应该发送一个没有证书的证书消息。如果服务器需要客户端认证才能继续握手,将响应一个致命的握手失败告警。用7.4.2节中定义的证书结构发送客户端证书。

注意:当使用基于密钥交换方法(DH_DSS 或者DH_RSA)Diffie-Hellman策略时,如果需要认证客户端,如果客户端参数要用于密钥交换,则编码在客户端的Diffie-Hellman组和产生器必须与服务器指明的Diffie-Hellman参数一致。

7.4.7 Client key exchange message

l         使用时间

一般由客户端发出。如果发送,应该紧跟客户端证书信息之后。否则,这是在接收到server hello done信息后客户端发送的第一个消息。

l         消息的意义

使用这条消息设置预主密文,方法时通过直接传送RSA加密的密文,或者通过允许每一端协商的相同的预主密文的Diffie-Hellman的传送。当密钥交换方法是DH_RSA或者 DH_DSS,则会请求客户端证书,客户端能够响应一张证书,它包含参数与服务器证书中指定的参数匹配的Diffie-Hellman公钥。此消息不包含任何数据。

l         消息结构

消息的选择基于所选的密钥交换方法。参看7.4.3KeyExchangeAlgorithm定义。

struct {

           select (KeyExchangeAlgorithm) {

               case rsa: EncryptedPreMasterSecret;

               case diffie_hellman: ClientDiffieHellmanPublic;

                     } exchange_keys;

                           } ClientKeyExchange;

7.4.7.1RSA加密的预主密文消息

l         消息含义

如果用RSA进行密钥协商和认证,服务器产生48字节的预主秘密,用服务器证书公钥或者服务器密钥交换信息提供临时RSA公钥加密,并在加密预主秘密信息中发送结果。这个结构是客户端密钥交换信息的变量,而不是消息本身。

l         消息格式

struct {

           ProtocolVersion client_version;

           opaque random[46];

} PreMasterSecret;

Ø         client_version

客户端支持的最近的版本(最高版本)。用来检测roll-back攻击。收到预主秘密后,服务器应该检测这个值是否与客户端在客户端问候消息中传送的值匹配。

Ø         random

46个安全产生的随机字节

struct {

           public-key-encrypted PreMasterSecret pre_master_secret;

       } EncryptedPreMasterSecret;

    注意:Daniel Bleichenbacher发现的攻击可以用来攻击用PKCS#1编码RSA TLS服务器。攻击利用了这样的事实:通过不同方式的失败,TLS服务器强制显示特定信息在解密时是不是PKCS#1格式。

  避免这种攻击的最好的方法是将不正确格式的消息以某种方法认为是与RSA块的正确格式难以区分的(The best way to avoid vulnerability to this attack is to treat incorrectly   formatted messages in a manner indistinguishable from correctly formatted RSA

  blocks)。因此,当收到格式不正确的RSA块时,服务器应该产生一个48字节长度的值,用它作为预主秘密。因此,服务器端将会一致的判断(act)收到的RSA块是否正确。

Ø         pre_master_secret

这个随机值由客户端产生,并用于产生主秘密。8.1节中会有描述。

7.4.7.2 客户端Diffie-Hellman公共值

l         消息含义

如果还没有包含在客户端证书中,这个结构传递客户的Diffie-Hellman公共值(Yc)。用于Yc的编码由枚举型的publicValueEncodingenumerated PublicValueEncoding)决定。这个结构是客户端密钥交换信息的一个变量,而不是消息本身。

l         消息结构

  enum { implicit, explicit } PublicValueEncoding;

Ø         implicit

如果证书已经包括了一个Diffie-Hellman密钥,则Yc是隐含的,不用再发送一次。在这种情况下,将发送客户端密钥交换信息,但是为空。

Ø         explicit

需要发送需要发送Yc

struct {

           select (PublicValueEncoding) {

               case implicit: struct { };

               case explicit: opaque dh_Yc<1..2^16-1>;

           } dh_public;

} ClientDiffieHellmanPublic;

u       dh_Yc

客户端的Diffie-HellmanYc

 

7.4.8 Certificate verify

l         消息发送时间

此消息给客户端证书提供明确的认证。此消息在有签名能力的客户端证书之后发送(例如:所有的除了具有固定的Diffie-Hellman参数的证书)。在发送时,紧跟在客户端密钥交换信息之后。

l         消息结构

struct {

            Signature signature;

} CertificateVerify;

签名类型在7.4.3中定义。

CertificateVerify.signature.md5_hash

  MD5(handshake_messages);

  Certificate.signature.sha_hash

  SHA(handshake_messages);

此处的handshake_messages指的是在客户端hello开始的时候发送和接收到的所有的握手信息,但不包括此信息,包括握手信息的类型和长度域。它是7.4节以来所有握手结构的串联。

7.4.9 Finished

l         消息发送时间

finished消息一般在改变密码规范协议之后立即发送,用来验证密钥交换和鉴别过程是否成功。在其他的握手消息和finished消息之间收到改变密码规范消息是必须的。

l         消息意义

finished消息是第一个用刚协商好的算法、密钥和密文加密保护的消息。Finished消息的接收必须验证内容是否正确。一旦一段发送了自己的finished消息,并且接收和验证了对端实体的finished信息,就可以开始在此连接上发送和接收应用数据了。

struct {

           opaque verify_data[12];

       } Finished;

Ø         verify_data

PRF(master_secret, finished_label, MD5(handshake_messages) +

  SHA-1(handshake_messages)) [0..11];

u       finished_label

用对于客户端发送的finished消息,为字符串 client finished”;对于服务器发送的finished消息,为字符串“server finished”。

u       handshake_messages

所有的握手消息的数据,但是不包括此消息。这个只是在握手层可见的数据,不包括记录头。这个是7.4节以来所有的握手消息的串连。

       在握手中,如果前面发送的不是改变密码规范消息,则会产生一个致命错误。

服务器发送的finished消息中的哈希包括Sender.server。客户端发送的finished消息中的哈希包括Client.serverhandshake_messages包括从开始到现在的所有的hello信息,不包括此fininshed消息。这与7.4.8节中的handshake_messages不同,因为他可能包括证书验证信息(如果发送)。而且,客户端发送的fininsed消息中的handshake_messages与服务器端发送的handshake_messages消息不同。因为后面发送的消息包含前一个消息。

注意:改变密码规范消息、告警消息和其他的记录类型不属于握手消息,因此不包含在哈希计算中。而且hello请求信息在握手哈希中被省略。

8 加密计算

       为了开始连接保护,TLS记录协议需要对算法组件、主秘密、客户端与服务器端的随机数的值进行说明。鉴别、加密和MAC算法服务器选择的cipher_suite决定,并在服务器hello信息中显示。压缩算法是在服务器hello消息中协商的,在hello信息中交换随机值。所有的这些都用来计算主密文。

8.1 计算主秘密

       对于所有的密钥交换方法,用同样的算法将预主秘密转换为主秘密。一旦计算出了主秘密,预主秘密就要从内存中删除。

master_secret = PRF(pre_master_secret, "master secret",

                           ClientHello.random + ServerHello.random)   [0..47];

主秘密长度一般都是48字节。预主秘密的长度依密钥交换方法不同。

8.1.1 RSA

       当用RSA进行服务器鉴别和密钥交换时,客户端产生48字节的预主秘密,用服务器公钥加密,发送给服务器。服务器用自己的私钥解密预主秘密(pre_master_secret)。双方在将pre_master_secret转换为master_secret,如上所述。

       RSA数字签名采用PKCS #1 [PKCS1]分组类型1RSA公钥加密采用PKCS #1 [PKCS1]分组类型2

8.1.2 Diffie-Hellman

       用传统的方法进行Diffie-Hellman计算。协商的密钥(Z)作为pre_master_secret,然后再将它转换为master_secret,如上所述。

       注意:Diffie-Hellman参数参数由服务器指定。既可以是短暂的(ephemeral),也可以包含在证书中。

9 强制的密码组件

没有特别指明应用标准的话,一个适应的应用必须实现的密码套件是TLS_DHE_DSS_

WITH_3DES_EDE_CBC_SHA

10 应用层数据协议

       应用层数据由记录层基于当前的连接状态传输、分段、压缩并加密。应用数据的处理对记录层来讲是透明的。

 

 

协议的常量值:

本节描述的协议的类型和常量。

Ø      A.1记录层

struct {

        uint8 major, minor;

    } ProtocolVersion;

 

    ProtocolVersion version = { 3, 1 };     /* TLS v1.0 */

 

    enum {

        change_cipher_spec(20), alert(21), handshake(22),

        application_data(23), (255)

    } ContentType;

 

    struct {

        ContentType type;

        ProtocolVersion version;

        uint16 length;

        opaque fragment[TLSPlaintext.length];

    } TLSPlaintext;

 

    struct {

        ContentType type;

        ProtocolVersion version;

        uint16 length;

        opaque fragment[TLSCompressed.length];

    } TLSCompressed;

 

    struct {

        ContentType type;

        ProtocolVersion version;

        uint16 length;

        select (CipherSpec.cipher_type) {

            case stream: GenericStreamCipher;

            case block:  GenericBlockCipher;

        } fragment;

} TLSCiphertext;

 

    stream-ciphered struct {

        opaque content[TLSCompressed.length];

        opaque MAC[CipherSpec.hash_size];

    } GenericStreamCipher;

 

    block-ciphered struct {

        opaque content[TLSCompressed.length];

opaque MAC[CipherSpec.hash_size];

  uint8 padding[GenericBlockCipher.padding_length];

  uint8 padding_length;

  } GenericBlockCipher;

Ø      2改变密码规范消息

struct {

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

} ChangeCipherSpec;

Ø      A.3告警消息

enum { warning(1), fatal(2), (255) } AlertLevel;

        enum {

            close_notify(0),

            unexpected_message(10),

            bad_record_mac(20),

            decryption_failed(21),

            record_overflow(22),

            decompression_failure(30),

            handshake_failure(40),

            bad_certificate(42),

            unsupported_certificate(43),

            certificate_revoked(44),

            certificate_expired(45),

            certificate_unknown(46),

            illegal_parameter(47),

            unknown_ca(48),

            access_denied(49),

            decode_error(50),

            decrypt_error(51),

            export_restriction(60),

            protocol_version(70),

            insufficient_security(71),

            internal_error(80),

            user_canceled(90),

            no_renegotiation(100),

            (255)

        } AlertDescription;

 

    struct {

        AlertLevel level;

        AlertDescription description;

} Alert;

Ø      A.4握手消息

enum {

        hello_request(0), client_hello(1), server_hello(2),

        certificate(11), server_key_exchange (12),

        certificate_request(13), server_hello_done(14),

        certificate_verify(15), client_key_exchange(16),

        finished(20), (255)

    } HandshakeType;

 

    struct {

        HandshakeType msg_type;

        uint24 length;

        select (HandshakeType) {

            case hello_request:       HelloRequest;

            case client_hello:        ClientHello;

            case server_hello:        ServerHello;

            case certificate:         Certificate;

            case server_key_exchange: ServerKeyExchange;

            case certificate_request: CertificateRequest;

            case server_hello_done:   ServerHelloDone;

            case certificate_verify:  CertificateVerify;

            case client_key_exchange: ClientKeyExchange;

            case finished:            Finished;

        } body;

} Handshake;

u    A4.1问候消息

struct { } HelloRequest;

    struct {

        uint32 gmt_unix_time;

        opaque random_bytes[28];

    } Random;

opaque SessionID<0..32>;

  uint8 CipherSuite[2];

  enum { null(0), (255) } CompressionMethod;

    struct {

        ProtocolVersion client_version;

        Random random;

        SessionID session_id;

        CipherSuite cipher_suites<2..2^16-1>;

        CompressionMethod compression_methods<1..2^8-1>;

  } ClientHello;

    struct {

        ProtocolVersion server_version;

        Random random;

        SessionID session_id;

        CipherSuite cipher_suite;

        CompressionMethod compression_method;

} ServerHello;

u    A4.2服务器鉴别和密钥交换消息

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

    struct {

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

    } Certificate;

enum { rsa, diffie_hellman } KeyExchangeAlgorithm;

    struct {

        opaque RSA_modulus<1..2^16-1>;

        opaque RSA_exponent<1..2^16-1>;

    } ServerRSAParams;

 

    struct {

        opaque DH_p<1..2^16-1>;

        opaque DH_g<1..2^16-1>;

        opaque DH_Ys<1..2^16-1>;

    } ServerDHParams;

 

    struct {

        select (KeyExchangeAlgorithm) {

            case diffie_hellman:

                ServerDHParams params;

                Signature signed_params;

            case rsa:

                ServerRSAParams params;

                Signature signed_params;

        };

    } ServerKeyExchange;

enum { anonymous, rsa, dsa } SignatureAlgorithm;

  select (SignatureAlgorithm)

    {   case anonymous: struct { };

        case rsa:

digitally-signed struct {

opaque md5_hash[16];

  opaque sha_hash[20];

  };

  case dsa:

            digitally-signed struct {

                opaque sha_hash[20];

            };

    } Signature;

 

    enum {

        rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),

        (255)

    } ClientCertificateType;

opaque DistinguishedName<1..2^16-1>;

    struct {

        ClientCertificateType certificate_types<1..2^8-1>;

        DistinguishedName certificate_authorities<3..2^16-1>;

    } CertificateRequest;

struct { } ServerHelloDone;

u    A4.3客户端鉴别和密钥交换消息

struct {

        select (KeyExchangeAlgorithm) {

            case rsa: EncryptedPreMasterSecret;

            case diffie_hellman: DiffieHellmanClientPublicValue;

        } exchange_keys;

    } ClientKeyExchange;

 

    struct {

        ProtocolVersion client_version;

        opaque random[46];

} PreMasterSecret;

    struct {

        public-key-encrypted PreMasterSecret pre_master_secret;

    } EncryptedPreMasterSecret;

enum { implicit, explicit } PublicValueEncoding;

    struct {

        select (PublicValueEncoding) {

            case implicit: struct {};

case explicit: opaque DH_Yc<1..2^16-1>;

} dh_public;

  } ClientDiffieHellmanPublic;

    struct {

        Signature signature;

    } CertificateVerify;

u    A4.4握手结束消息

struct {

        opaque verify_data[12];

} Finished;

Ø      5密码组件

下面的值定义了用于服务器hello和客户端hello消息的密码组件的代码。

CipherSuite定义了TLS1.0支持的密钥规范。在信道上第一次握手时初始化TLS连接状态为TLS_NULL_WITH_NULL_NULLbut must not be  negotiated, as it provides no more protection than an unsecured connection

CipherSuite TLS_NULL_WITH_NULL_NULL                = { 0x00,0x00 };

接下来的CipherSuite定义需要服务器提供用于密钥交换的RSA证书。服务器可能在证书请求消息中请求RSA或者DSS签名证书。

CipherSuite TLS_RSA_WITH_NULL_MD5                  = { 0x00,0x01 };

    CipherSuite TLS_RSA_WITH_NULL_SHA                  = { 0x00,0x02 };

    CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5         = { 0x00,0x03 };

    CipherSuite TLS_RSA_WITH_RC4_128_MD5               = { 0x00,0x04 };

    CipherSuite TLS_RSA_WITH_RC4_128_SHA               = { 0x00,0x05 };

    CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5     = { 0x00,0x06 };

    CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA              = { 0x00,0x07 };

    CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA      = { 0x00,0x08 };

    CipherSuite TLS_RSA_WITH_DES_CBC_SHA               = { 0x00,0x09 };

CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA          = { 0x00,0x0A };

       下面的CipherSuite定义用于服务器认证(也可以时客户端认证)Diffie-HellmanDH表示由CA签署的包含Diffie-Hellman参数的服务器证书中的密码组件。DHE表示短期的Diffie-Hellman,其中, Diffie-Hellman参数由DSS或者RSA证书签名,证书由CA签署。使用的签名算法在DH或者DHE参数之后指明。为了客户端认证,服务器向客户端发送RSA或者DSS有签名能力的证书请求或者发送Diffie-Hellman证书请求。客户端提供的Diffie-Hellman证书请求必须使用服务器描述的参数(组或者产生器)

CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   = { 0x00,0x0B };

    CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA            = { 0x00,0x0C };

    CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA       = { 0x00,0x0D };

    CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA   = { 0x00,0x0E };

    CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA            = { 0x00,0x0F };

    CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA       = { 0x00,0x10 };

    CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  = { 0x00,0x11 };

    CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA           = { 0x00,0x12 };

    CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA      = { 0x00,0x13 };

    CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA  = { 0x00,0x14 };

    CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA           = { 0x00,0x15 };

        CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA      = { 0x00,0x16 };

下面的密码组件用于完全匿名的Diffie-Hellman通信,其中不认证任何一方。注意,这种方法易于受到中间人攻击,因此不赞成使用。

CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5     = { 0x00,0x17 };

    CipherSuite TLS_DH_anon_WITH_RC4_128_MD5           = { 0x00,0x18 };

    CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA  = { 0x00,0x19 };

    CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA           = { 0x00,0x1A };

        CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA      = { 0x00,0x1B };

注意:所有开头的字节为0xFF的密码组件都被认为是私有的,可以用于定义本地/实验算法。Interoperability of  such types is a local matter.

注意:额外的密码组件可以通过发布说明了密码组件的RFC注册,其中包括相关算法必须的TLS协议信息,消息编码,获得预主秘密,对称加密,MAC计算和恰当的参考信息。RFC编辑办公室可能会按照自己的原则The RFC editor‘s office may, at its discretion, choose to publish  specifications for cipher suites which are not completely described (e.g., for classified algorithms) if it finds the specification to be of technical interest and completely specified.

注意:暴力了密码组件值{ 0x00, 0x1C }{ 0x00, 0x1D }避免与SSL3.0中基于Fortezza-based的秘密组件冲突。

Ø      A.6安全参数

这些安全参数都是有TLS握手协议决定,为TLS记录层提供参数用来初始化连接状态。安全参数包括:

enum { null(0), (255) } CompressionMethod;

  enum { server, client } ConnectionEnd;

  enum { null, rc4, rc2, des, 3des, des40, idea }

  BulkCipherAlgorithm;

  enum { stream, block } CipherType;

  enum { true, false } IsExportable;

  enum { null, md5, sha } MACAlgorithm;

  /*包括CommpressionMethod中说明的算法,BulkCipherAlgorithmMACAlgorithm */

       struct {

           ConnectionEnd entity;

           BulkCipherAlgorithm bulk_cipher_algorithm;

           CipherType cipher_type;

           uint8 key_size;

           uint8 key_material_length;

           IsExportable is_exportable;

           MACAlgorithm mac_algorithm;

           uint8 hash_size;

           CompressionMethod compression_algorithm;

           opaque master_secret[48];

           opaque client_random[32];

           opaque server_random[32];

} SecurityParameters;

Ø      B:词汇表

u       应用层协议

应用层协议直接位于传输层协议(如:TCP/IP)之上的协议。例如:HTTPTELNETFTPSNMP

u       非对称密码

参见公钥加密

u       鉴别

鉴别是一个实体确定另外一个实体身份的能力

u       分组密码

分组密码是用字节组(称为分组)来操作明文的算法。一般为64比特为一个分组

u       bulk密码

用于加密大量数据的数据加密算法

u       cipher block chaining (CBC)

CBC是用分组密码加密明文的一种模式,与前一个密文分组异或(is first exclusive-ORed with the previous ciphertext block),(如果是第一个分组,就使用初始化向量)。对于解密,每一个分组先被解密,然后再与前一个密文块(IV)异或。

u       证书

作为X.509协议的一部分(a.k.aISO鉴别框架),证书是由认证机构颁发的,将实体身份或者其他某些属性与公钥进行绑定。

u       客户

为服务器初始化TLS连接的应用实体。这可能,也可能不暗示着底层的传输连接(his may or may not imply that the client initiated the underlying transport  connection)。服务器和客户端操作的基本的区别是:服务器一般都是要被认证的,而客户端则可以选择。

u       客户端写密钥

用于加密客户端所写数据的密钥

u       客户端写MAC密文

用于验证客户端所写的数据的秘密数据(secret date)

u       连接

连接是提供恰当的服务类型的传输(ISO层模型的定义)。对于TLS,这种连接是端对端的。连接是暂时的。每个连接与一个会话对应。

u       数据加密标准

DES是广泛应用的对称加密算法。DES是使用56比特密钥和8字节大小的分组的分组密码。注意:在TLS中,为了密钥产生的目的,DES被视为有8字节(64比特)密钥长度,但实际上只提供56字节的保护(每个密钥字节的低位比特假定被设置为产生密钥比特中的奇偶校验(The low bit of each key byte is presumed to be set to produce odd parity in that key byte.))DES也可以用于这种模型的操作中:每一个数据分组使用3个密钥和3次加密。它使用168比特的密钥(密钥产生方法中的24字节)。提供相当与112比特的安全。[DES], [3DES]

u       数字签名标准(DSS)

数字签名的标准,包括数字签名算法。由National Institute of Standards and Technology验证的,由NIST FIPS PUB 186, "Digital Signature Standard," published May, 1994 by the U.S. Dept. of Commerce。定义的。[DSS]

u       数字签名

数字签名使用公钥算法和单向哈希函数产生可鉴别的数字签名,他是很难伪造或者复制的。

u       握手

客户端和服务器之间的用于建立交易参数的初始化协商

u       初始化向量(IV)

当分组密码使用CBC模式时,加密前要使用初始化向量IV与第一个明文分组异或计算

u       IDEA

Xuejia Lai and James Massey设计的64比特的分组密码

u       消息认证码(MAC)

消息认证码(MAC)是由消息和一些秘密数据计算的单向哈希。如果不知道秘密数据,它是很难伪造的。目的是检测消息是否被改动过

u       主密文

用于产生加密密钥、MAC密文和IVs的安全的秘密数据

u       MD5

MD5是安全的哈希函数,它将任意长度的数据流转换为固定大小的摘要(16字节)

u       公钥加密

一种使用两个密钥的密码技术。用公钥加密的消息只能用相应的私钥解密。相反,用私钥签名的消息可以用公钥验证

u       单向哈希函数

单向转化是将任意长度的数据转换为固定长度的哈希。反相转换或者寻找冲突在计算上是很困难的。MD5SHA单向哈希的例子。

u       RC2

by Ron Rivest at RSA Data Security, Inc开发的分组密码。[RSADSI] described in [RC2].

u       RC4

RSA数据安全注册的流密码。在[RC4]中描述了的一个兼容的密码

u       RSA

可以用于加密和签名的广泛使用的公钥算法

u       掺杂(salt)

抵制穷举攻击的用于出口加密密钥的非秘密的随机数据

u       服务器

用于响应来自于客户端连接请求的应用实体。

u       会话

一个TLS会话是客户端和服务器之间的一种关联。会话是由握手协议产生的。会话定义了一套密码安全参数,可以在多个连接中共享使用。会话可以用来避免用于每一个连接的新的安全参数的expensive协商。

u       会话标识符

会话标识符是由服务器产生的用来表示特定会话的值

u       服务器写密钥

用来加密服务器所写数据的密钥

u       服务器写MAC密文

用来鉴别服务器所写数据的秘密数据

u       SHA

FIPS PUB 180-1中定义的安全哈希算法。它产生20字节的输出。注意:所有对SHA的引用事实上使用的都是修改过的SHA-1算法

u       SSL

网景公司的安全套接层协议。TLS是基于SSL V3.0

u       流密码

一种将密钥转换为cryptographically-strong密码流的加密算法。它要与明文exclusive-ORed

u       对称密码

参见bulk密码

u       TLS

本协议。同时也指IETF的传输层安全工作组。参见本文档最后的注释。

Ø      C:密码组件定义

CipherSuite      Is       Key          Cipher      Hash                           Exportable Exchange
 
TLS_NULL_WITH_NULL_NULL               * NULL           NULL        NULL
TLS_RSA_WITH_NULL_MD5                 * RSA            NULL         MD5
TLS_RSA_WITH_NULL_SHA                 * RSA            NULL         SHA
TLS_RSA_EXPORT_WITH_RC4_40_MD5        * RSA_EXPORT     RC4_40       MD5
TLS_RSA_WITH_RC4_128_MD5                RSA            RC4_128      MD5
TLS_RSA_WITH_RC4_128_SHA                RSA            RC4_128      SHA
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5    * RSA_EXPORT     RC2_CBC_40   MD5
TLS_RSA_WITH_IDEA_CBC_SHA               RSA            IDEA_CBC     SHA
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA     * RSA_EXPORT     DES40_CBC    SHA
TLS_RSA_WITH_DES_CBC_SHA                RSA            DES_CBC      SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA           RSA            3DES_EDE_CBC SHA
TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA  * DH_DSS_EXPORT  DES40_CBC    SHA
TLS_DH_DSS_WITH_DES_CBC_SHA             DH_DSS         DES_CBC      SHA
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA        DH_DSS         3DES_EDE_CBC SHA
TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA  * DH_RSA_EXPORT  DES40_CBC    SHA
TLS_DH_RSA_WITH_DES_CBC_SHA             DH_RSA         DES_CBC      SHA
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA        DH_RSA         3DES_EDE_CBC SHA
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA * DHE_DSS_EXPORT DES40_CBC    SHA
TLS_DHE_DSS_WITH_DES_CBC_SHA            DHE_DSS        DES_CBC      SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA       DHE_DSS        3DES_EDE_CBC SHA
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA * DHE_RSA_EXPORT DES40_CBC    SHA
TLS_DHE_RSA_WITH_DES_CBC_SHA            DHE_RSA        DES_CBC      SHA
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA       DHE_RSA        3DES_EDE_CBC SHA
TLS_DH_anon_EXPORT_WITH_RC4_40_MD5    * DH_anon_EXPORT RC4_40       MD5
TLS_DH_anon_WITH_RC4_128_MD5            DH_anon        RC4_128      MD5
TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA   DH_anon        DES40_CBC    SHA
TLS_DH_anon_WITH_DES_CBC_SHA            DH_anon        DES_CBC      SHA
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA       DH_anon        3DES_EDE_CBC SHA
 
   * Indicates IsExportable is True
 

 

Key
      Exchange
      Algorithm       Description                        Key size limit
 
      DHE_DSS         Ephemeral DH with DSS signatures   None
      DHE_DSS_EXPORT  Ephemeral DH with DSS signatures   DH = 512 bits
      DHE_RSA         Ephemeral DH with RSA signatures   None
      DHE_RSA_EXPORT  Ephemeral DH with RSA signatures   DH = 512 bits,
                                                         RSA = none
      DH_anon         Anonymous DH, no signatures        None
      DH_anon_EXPORT  Anonymous DH, no signatures        DH = 512 bits
      DH_DSS          DH with DSS-based certificates     None
      DH_DSS_EXPORT   DH with DSS-based certificates     DH = 512 bits
      DH_RSA          DH with RSA-based certificates     None
      DH_RSA_EXPORT   DH with RSA-based certificates     DH = 512 bits,
                                                         RSA = none
      NULL            No key exchange                    N/A
      RSA             RSA key exchange                   None
      RSA_EXPORT      RSA key exchange                   RSA = 512 bits

       密钥大小限制:

       密钥大小给出了用于出口的密码组件的用于加密的合法的最大的公钥大小。

 
                         Key      Expanded   Effective   IV    Block
    Cipher       Type  Material Key Material  Key Bits  Size   Size
 
    NULL       * Stream   0          0           0        0     N/A
    IDEA_CBC     Block   16         16         128        8      8
    RC2_CBC_40 * Block    5         16          40        8      8
    RC4_40     * Stream   5         16          40        0     N/A
    RC4_128      Stream  16         16         128        0     N/A
    DES40_CBC  * Block    5          8          40        8      8
    DES_CBC      Block    8          8          56        8      8

    3DES_EDE_CBC  Block   24         24         168        8      8

 *表示IsExportable为真

类型:

说明运行在CBC模式中的是流密码还是分组密码