ECC Cipher Suites 加密套件在TLS中的应用 RFC 4492

简介

 本文档介绍了ECC算法在TLS协议中的使用方法,是对RFC 4492文档进行的翻译。由于翻译本文档时,对协议的认识有限,请大家指出错误和建议。

 

摘要

       本文档介绍了基于ECC的密钥交换算法在TLS协议中的应用,在协议的握手过程中使用ECDH作为密钥协商,并且使用ECDSA进行身份认证。

 

名词解释

       TLS: Transport Layer SecurityProtocol     安全传输层协议

       ECC: Elliptic Curve Cryptography         椭圆曲线算法

       ECDSA:Elliptic  Curve Digital  Signature  Algorithm 椭圆曲线签名算法

       ECDH:EllipticCurve Diffie-Hellman     椭圆曲线赫尔曼算法

 

1.概述:

       ECC相比RSA /DH算法来说,采取更短的密钥长度就可以达到相同的加密强度,而且运算速度要更快。加上类似RSA的密钥出口限制等原因,在国内实现非对称加密算法均采用SM2来替换RSA。

       本文主要描述了:

1.     通过使用ECDH密钥交换方案来进行长期的或者暂时的密钥来建立TLC的预主密钥。

2.     使用ECDH证书和ECDSA来互相认证。

2.密钥交换算法:

       以下基于ECC的ECDH算法均是用来进行TLS的预主密钥的协商,差别在于ECDH密钥的存活周期是长期的或者暂时的,还有认证算法的差别。后期的会话密钥的计算和ECC没有关系。

 

算法                             描述

ECDH_ECDSA                       固定的ECDH采用ECDSA签名证书。

 

ECDHE_ECDSA                    暂时的ECDH 采用ECDSA签名

 

ECDH_RSA                   固定的ECDH 采用RSA签名证书

 

ECDHE_RSA                      暂时的ECDH 采用RSA签名

 

ECDH_anon                   匿名的ECDH 不签名

 

ECDHE_ECDSA和ECDHE_RSA提供的向前加密保证。

 

采用ECDH后的加密流程如下所示:

 

 

 

 

 

 Client                                               Server

                                                    ————

 

ClientHello               ---------à          

                                                                                                  ServerHello

                                                                                    Ceritificate*

                                                               ServerKeyExchange*

                                                                             CertificateRequest*+

                          ß------------                ServerHelloDone

Certificate*+

ClientKeyExchange

CertificateVerify*+

[ChangeCipherSpec]

Finished                -------------à

                                                                             [ChangeCipherSpec]

                                    ß-------------                            Finished

Application Data       ß------------>                Application Data

 

              *消息  表示在一定的条件下才发送

              +消息  表示在需要验证客户端的有效性时才发送

添加ECC算法会直接影响到ClientHello、 ServerHello、Server’s  Certification 、ServerKeyExchange 、ClientKeyExchange 、 CertificateRequest、Client’sCertification和CertificationVerify这些数据包。

下面详细地描述每一个ECC交换算法

2.1 ECDH_ECDSA

使用ECDH_ECDSA时,服务端证书必须包含一个可以进行ECDH的公钥并且可以用ECDSA进行签名。使用该算法时,不必发送ServerKeyExchange消息,因为证书中已经包含了计算预主密钥所需要的所有信息。

客户端生成一对和服务端的长期公钥采用相同曲线的ECDH密钥对。并将其公钥在ClientKeyExchange消息中发送。

客户端和服务端执行相同的ECDH操作和使用计算出来的共享密钥。

2.2ECDHE_ECDSA

       在ECDHE_ECDSA中,服务端证书必须包含一个可以进行ECDH的公钥并且可以用ECDSA进行签名。服务端在ServerKeyExchange消息中发送自己临时性的ECDH公钥和详细的符合规定的曲线。这些参数必须使用和Server’sCertification证书公钥对应的私钥进行ECDSA运算。

       客户端生成和服务端相同曲线的ECDH密钥对,并将公钥在ClientKeyExchange消息发送给服务端。

2.3ECDH_RSA

       和ECDH_ECDSA的要求一样,不用的是使用RSA进行运算而不是ECDSA。

2.4ECDHE_RSA

       和ECDHE_ECDSA类似,除了证书公钥是RSA和采用RSA进行签名。

2.5ECDH_anon

       使用ECDH_anon算法时,不用发送Server’sCertificate 、CertificateRequest 、client’s Certificate 和CertificateVerify。

服务端必须在ServerKeyExchange消息中发送一个临时的ECDH公钥和一个指定的曲线,这个参数没有被签名。

       客户端使用和服务端相同的曲线参数生成ECDH密钥对,将公钥通过ClientKeyExchange消息发送给服务端。

3.客户端验证

本文档定义了三种新的客户端验证机制:ECDSA_sign、ECDSA_fixed_ECDH、RSA_fixed_ECDH。其中ECDSA-Sign机制不能用于ECDH_anon算法中。ECDSA_fixed_ECDH和RSA_fixed_ECDH可以用于ECDHE_ECDHA和ECDHE_RSA。但是,在ECDH的长期密钥模式下就不能使用,否则会损害向前保密的特性。

服务端通过CertificateRequest消息要求客户端发送一个或多个基于ECC的证书,服务端不能存在禁止使用密钥交换算法的证书,客户端在必要时可以查询服务端提供的认证模式。

如果客户端有符合规则的证书,那么发送证书之后还需要发送CertificateVerify消息,客户端还必须持有和证书中公钥相对应的私钥。

 

注意:允许服务器请求客户端发送一个和服务端不同类型的证书。

3.1ECDSA_sign

       使用这个认证算法时,客户端必须持有一个包含ECDSA公钥并且使用ECDSA签名过。客户端拥有和证书公钥对应的私钥。

3.2ECDSA_fixed_ECDH

       客户端必须拥有ECDSA公钥的证书和相对应的私钥,客户端还必须拥有通过服务器长期ECDH密钥的曲线计算出来的ECDH密钥。使用本机制时,需要发送一个空的ClientKeyExchange并且不用发送CertificateVerify消息。

3.3RSA_fixed_ECDH

       和3.2类似,使用RSA而不是ECDSA算法。

4.数据结构和说明

4.1client hello 扩展

放在client hello中,用来指定所支持的ECC  椭圆曲线和点压缩格式。

 

  enum { elliptic_curves(10), ec_point_formats(11)} ExtensionType;

elliptic_curves:支持的椭圆曲线扩展,指出客户端支持的椭圆曲线,在4.1.1中将详细描述。

ec_point_formats:支持的点压缩格式扩展。指出了客户端能解析的点压缩格式的集合。将在4.1.2中详细描述。

 

该结构的数据放在压缩算法之后。

 

       发送者的动作:

          客户端在ClientHello中提议使用ECC加密套件,枚举自己可以支持的椭圆曲线和可以解析的点压缩格式。客户端可以同时发送椭圆曲线和点压缩格式。如果支持的点压缩格式扩展已经发送,那么点压缩格式的内容必须为0。

       接收者的动作:

              服务端收到ClientHello后,如果发现其中包含了这个扩展项,必须从中挑选一个合适的cipher suite支持ECC,并且能使用曲线参数和点压缩格式来完成后面的协商。

 

注意:服务端参与到ECDHE_ECDSA的密钥交换时,可以使用和自己的证书不一致的曲线(i),但是(ii)临时的ECDH密钥放在ServerKeyExchange消息中。服务端必须考虑到扩展的两个内容

       如果服务端不能解析这个扩展项,或者不支持ECC算法,或者用这样的参数不能完成下面的协商过程,那么就发送失败告警给客户端。

4.1.1支持的椭圆曲线扩展

       enum {

            sect163k1 (1), sect163r1 (2),sect163r2 (3),

            sect193r1 (4), sect193r2 (5),sect233k1 (6),

            sect233r1 (7), sect239k1 (8),sect283k1 (9),

            sect283r1 (10), sect409k1 (11),sect409r1 (12),

            sect571k1 (13), sect571r1 (14),secp160k1 (15),

            secp160r1 (16), secp160r2 (17),secp192k1 (18),

            secp192r1 (19), secp224k1 (20),secp224r1 (21),

            secp256k1 (22), secp256r1 (23),secp384r1 (24),

            secp521r1 (25),

            reserved (0xFE00..0xFEFF),

           arbitrary_explicit_prime_curves(0xFF01),

           arbitrary_explicit_char2_curves(0xFF02),

            (0xFFFF)

        } NamedCurve;

 

       以sect163k1为例:

              指定名称和已经定义过的曲线集合的对应关系,曲线集合是SEC组织定义的。这些曲线也推荐ANSI X9.62和FIPS 186-2。

0xFE00到0xFEFF被预留为私有的。

       0xFF01 特定的素数鱼曲线参数。

0xFF02 特定的二元扩域曲线参数。

   NamedCurve是IANA组织来维护的。

       struct {

            NamedCurveelliptic_curve_list<1..2^16-1>

        } EllipticCurveList;

 

 如下的示例:

       一个客户端支持secp192r1 (aka NIST P-192; value 19 = 0x0013)和spec224r1(aka NIST P-224; value 21 = 0x0015)两种算法,但是跟倾向于使用secp192r1.那么这个椭圆曲线参数的扩展如下:

               00 0A 00 06 00 04 00 13 00 15

         00 0A --椭圆曲线参数的扩展类型

      00 06 扩展的总长度

      00 04 参数列表的长度

      00 13 secp192r1(倾向使用的放前面)

      00 15 spec224r1

    一个客户端支持一个明确使用的二元扩域曲线参数(value 0xFF02)在椭圆曲线参数的扩展如下:

                        00 0A 00 04 00 02 FF 02

  Note:不解释了,和上面一样。

4.1.2支持的点压缩格式扩展

enum { uncompressed(0), ansiX962_compressed_prime (1),

               ansiX962_compressed_char2 (2),reserved (248..255)

        } ECPointFormat;

 

        struct {

            ECPointFormatec_point_format_list<1..2^8-1>

        } ECPointFormatList;

       上面定义了三个ECC的点压缩格式,uncompressed点压缩格式在本文档的规定客户端必须支持。压缩点压缩格式可以节省带宽,通过点的X轴和Y轴的相关参数进行计算。本文档还支持ansiX962_compressed_prime和ansiX962_compressed_char2两种格式,前一种支持素数域曲线,第二种支持二元扩域曲线。248-255之间的值留为私用。

       ECC点压缩格式的命名空间也是IANA维护的。

ECPointFormatList包含了客户端所支持点压缩格式的参数选择,(偏爱的选择靠前)。

下面还是举例说明:

一个客户端只能解析uncompressed点压缩格式(value 0),点压缩格式扩展项的内容如下所示:

               000B 00 02 01 00

      

              00 0B:点压缩格式的类型

        00 02:点压缩格式的总长度

        01:点压缩格式列表长度

        00:uncompressed格式

       例二:

       一个客户端采用在素数域(vaule 1)内基于uncompressed(vaule0)格式的点压缩格式,还有在二次扩域(vaule 2)基于压缩格式的点压缩格式,那么点压缩格式扩展项的内容如下所示:

       00 0B 0004 03 01 00 02

4.2Server Hello 扩展

       这一节描述了TLS扩展中的ServerHello消息的结构。

       ServerHello包含了服务端从ClientHello的客户端支持的ECC cipher suite的扩展列表中挑选出来的自身可以解析的扩展项。这个曲线参数的扩展项将用在ServerKeyExchange中,用来进行ECDHE_ECDSA,ECDHE_RSA或者ECDH_anon的密钥交换算法中,或者曲线用来进行ECDH_ECDSA或者ECDH_RSA交换算法的证书公钥的加密运算。

       ServerHello扩展项的结构和ClientHello的扩展项结构一致。从客户端的曲线参数套件中挑选可以支持的参数,同时将优先级高的套件放在列表的前面。

 

       发送者的动作:

              服务端从ECC加密套件中选择一个可以支持的套件,并且支持扩展的点压缩格式放入到ServerHello消息中,选择点压缩格式的时候必须在列表中加入uncompressed消息。

       接收者的动作:

             客户端接收到ServerHello消息之后,在后续的握手协商过程中应当遵循服务端的选择,如果没有从ServerHello中获取到所支持的点压缩格式,那么就等于默认采用uncompressed格式。

4.3Server Certificate

       这个消息在所有非匿名的ECC密钥交换算法中都需要发送。这个消息是将服务端的可认证的静态公钥发送给客户端,服务端证书必须采用X509的格式。下面这个表是对不同ECC密钥交换算法使用中的证书的约束条件。

          密钥交换算法                          服务端证书类型

----------------------------------------            ---------------------------

ECDH_ECDSA                         证书必须包含一个ECDH支持的公钥,并且用ECDSA签名过

ECDHE_ECDSA                        同上

 

ECDH_RSA                            证书必须包含一个ECDH支持的公钥,并且用RSA签名过

ECDHE_RSA                          证书必须包含一个可以用来验证数字签名的RSA公钥,并且被RSA签名过

 

发送者动作:

    服务端构建一个可认证的证书链(与标准TLS相同),如果客户端使用了椭圆曲线的扩展项,那么服务器证书中的公钥必须符合客户端选择的曲线参数。详细地说就是公钥必须使用客户端支持的曲线参数和点压缩格式。

接收者动作:

       客户端首先验证证书链的有效性,然后将证书中的公钥提取出来并判断公钥能不能支持后续的证书交换算法。

4.4 Server key Exchange

     在使用ECDHE_ECDSA,ECDHE_RSA和ECDH_anon密钥交换算法时需要发送本消息。本消息的作用是客户端用来验证服务端的临时ECDH公钥。

       消息结构如下:

ECCurveType结构:

ECCurveType结构表示椭圆曲线的域规模q=p,p是大于3的素数(素数域),q=2m( 二元扩域,采用三项式基TPB或者五项式基PPB)

 

       enum { explicit_prime (1), explicit_char2(2),

               named_curve (3),reserved(248..255) } ECCurveType;

       explicit_prime :指定椭圆曲线的域规模,其基础有限域是素数域。

       explicit_char2:指定椭圆曲线的域规模,其基础有限域是二元扩域。

       named_curve:指定使用的曲线名称,这个选项在需要时使用。

248-255这期间的值留作私用。

 

 

ECCurve结构:

ECCurve结构是曲线方程中的参数

       素域:y2=x3+ax+b;

       二元扩域:y2+xy=x3+ax+b;

struct {

            opaque a <1..2^8-1>;

            opaque b <1..2^8-1>;

        } ECCurve;

 

a,b:这两个参指定了椭圆曲线的系数,每个参数的值内容都是字节串来表示域参数,并且通过ANSI X9.26进行了格式转换;

 

ECPoint结构:

       ECPoint结构是椭圆曲线的基点:

       素域:G=(xG,yG)∈E(FP),G≠0;

       二元扩域:G=(xG,yG)∈E(F2m),G≠0

struct {

            opaque point <1..2^8-1>;

        } ECPoint;

 Point:这是一个经过ANSI X9.62编码的字节串,用来表示椭圆曲线的基点。这个串可以采用压缩和非压缩格式,这个格式在客户端的点压缩格式扩展中支持。

 

ECBasisType结构:

    ECBasisType结构用来表示二元扩域的三项式或者五项式的结构。

enum { ec_basis_trinomial,ec_basis_pentanomial } ECBasisType;

 

       ec_basis_trinomial:二元扩域表示域规模的三项式;

       ec_basis_pentanomial:二元扩域表示域规模的五项式;

 

ECParameters结构:

       struct {

            ECCurveType    curve_type;

            select (curve_type) {

                case explicit_prime:

                    opaque      prime_p <1..2^8-1>;

                    ECCurve     curve;

                    ECPoint     base;

                    opaque      order <1..2^8-1>;

                    opaque      cofactor <1..2^8-1>;

                case explicit_char2:

                    uint16      m;

                    ECBasisType basis;

                    select (basis) {

                        case ec_trinomial:

                            opaque  k <1..2^8-1>;

                        case ec_pentanomial:

                            opaque  k1 <1..2^8-1>;

                            opaque  k2 <1..2^8-1>;

                            opaque  k3 <1..2^8-1>;

                    };

                    ECCurve     curve;

                    ECPoint     base;

                    opaque      order <1..2^8-1>;

                    opaque      cofactor <1..2^8-1>; casenamed_curve:

                    NamedCurve namedcurve;

            };

        } ECParameters;

 

curve_type;指定椭圆曲线基础域的类型

prime_p:素域的中的奇素数

curve:曲线参数a,b

base:基点G

order:基点G的阶n

cofactor:余因子h=#E(Fp)/n

m:二次扩域中F2m中的m

k:三项式的指数 Xm+Xk+1中的k

k1,k2,k3:五项式中的指数Xm+Xk3+Xk2+Xk1+1(k3>k2>k1)

namedcurve:指定一个推荐的曲线域参数集合,这些参数被用来指定特殊的曲线。在客户端推荐使用arbitrary_explicit_prime_curves(0xFF01)和arbitrary_explicit_char2_curves(0xFF02)时使用。SM2作为ECC算法使用时,国密局有推荐的曲线参数,因此,这部分应该采用国密局的推荐参数。

 

ServerECDHParams结构:

          struct {

            ECParameters    curve_params;

            ECPoint         public;

        } ServerECDHParams;

curve_params:指定ECDH公钥的椭圆曲线域参数

public:临时的ECDH公钥

 

ServerKeyExchange结构:

    ServerKeyExchange结构的格式如下:

       enum{ ec_diffie_hellman }KeyExchangeAlgorithm;

ec_diffie_hellman:指定包含ECDH公钥的ServerKeyExchange消息内容。

 

 

具体格式如下:

 

select(KeyExchangeAlgorithm) {

            case ec_diffie_hellman:

                ServerECDHParams    params;

                Signature           signed_params;

        } ServerKeyExchange;

 

Params:指定ECDH公钥和域参数

 Signed_params:参数的哈希结构,然后使用证书中公钥对应的私钥进行的签名。

                      enum {esdsa} SignatureAlgorithm;

              select(SignatureAlgorithm) {

              case ecdsa:

                  digitally-signed struct {

                      opaquesha_hash[sha_size];

                  };

          } Signature;

 签名结构是对一段sha1的hash值进行签名,这个hash算法也可以替换为其他的hash算法,我们在实现国密的规范的时候应当采用SM3实现(具体看测试平台的调试结果),具体用来散列的内容如下:

ServerKeyExchange.signed_params.sha_hash

            SHA(ClientHello.random +ServerHello.random +

                                             ServerKeyExchange.params);

     客户端随机数||服务端随机数||ServerKeyExchange曲线参数

*这个hash体现了向前保密的特性。

签名的结果是二进制的串结构如下(也是SM2算法签名的数据结构):

Ecdsa-Sig-Value ::=SEQUENCE {

               r       INTEGER,

               s       INTEGER

           }

发送者动作:

       服务器选择一个椭圆曲线的域参数和临时的ECDH公钥,这些参数符合IEEE1363的ECKAS-DH1方案。使用预先选定好的格式通过ServerKeyExchange消息发送给客户端。

接收者动作:

       客户端验证签名并将服务端的椭圆曲线的域参数和临时ECDH公钥从ServerKeyExchange消息中提取出来。

 

4.5Certificate Request

当需要对客户端进行验证时,发送本消息。服务端建议客户端发送符合要求的证书。

       消息结构如下:

       enum {

            ecdsa_sign(64), rsa_fixed_ecdh(65),

            ecdsa_fixed_ecdh(66), (255)

        } ClientCertificateType;

 

 内容参考第三章的定义。

发送者动作:

       服务端决定使用哪种客户端的认证模式,并且规定了客户端使用的模式。

接收者动作:

       客户端确认自己是否有满足要求的证书,从而决定时候进行后续的客户端验证。

4.6 Client Certificate

当服务端发送了CertificateRequest时,并且客户端拥有了一个适合要求的证书,那么客户端发送该证书。(如果服务端使用了点压缩格式扩展,这个证书只能认为适合使用ECDSA_sign,RSA_fixed_ECDH,和ECDSA_fixed_ECDH认证方法并且公钥支持服务端选择的点压缩格式。如果没有指定,那么就是用uncompreesed点压缩格式)

证书必须符合X509格式,也支持证书链。本消息用来对客户端公钥进行验证。对证书的具体要求如下表:

客户端验证模式                    客户端证书类型

———————————            ————————————

ECDSA_sign                          证书必须包含了一个可以用于ECDSA的公钥,并且证书被ECDSA算法签名过。

ECDSA_fixed_ECDH                   证书必须包含一个可以用于ECDH的公钥,该公钥和服务端的长期ECDH密钥采用相同的椭圆曲线。证书被ECDSA签名过。

RSA_fixed_ECDH                     证书必须包含一个可以用于ECDH的公钥,该公钥和服务端的长期ECDH密钥采用相同的椭圆曲线。证书被RSA签名过。

 

具体的组装格式可以参考TLS的标准。

 

发送者动作:

    客户端组装符合要求的证书链,在Certificate消息中发送。

接收者动作:

    服务端验证证书链的有效性,从证书中提取出客户端的公钥。

4.7Client Key Exchange

所有的密钥交换算法都需要发送本消息,如果客户端认证是采用了ECDSA_fixed_ECDH 或者RSA_fixed_ECDH模式认证,那么这个消息为空,否则其他的情况下包含了客户端的临时ECDH公钥。这个消息用来传输密钥交换的临时数据(例如临时的ECDH公钥)。

消息结构:

enum{ implicit, explicit } PublicValueEncoding;

implicit,explicit:ECC 套件指定了客户端的ECDH公钥是在客户端的证书中,还是需要客户端提供。如果需要提供,那么ECDH公钥在ClientKeyExchange消息中。

 

struct {

            select (PublicValueEncoding) {

                case implicit: struct { };

                case explicit: ECPoint ecdh_Yc;

            } ecdh_public;

        } ClientECDiffieHellmanPublic;

ecdh_Yc:客户端的临时ECDH公钥,采用了和ECPoint.point一样的编码格式,为一个比特串。如果服务端指定了点压缩格式的是压缩的,那么这个值为压缩的结果,否则就采用非压缩的模式。

 

  struct {

            select (KeyExchangeAlgorithm) {

                case ec_diffie_hellman:ClientECDiffieHellmanPublic;

            } exchange_keys;

        } ClientKeyExchange;

发送者动作:

       客户端选择一个符合服务端指定的曲线参数的临时ECDH公钥,并采用IEEE 1363的ECKAS-DH1进行编码。在ClientKeyExchange中采用上面的格式组装这个数据。

接收者动作:

       服务端接收到客户端的临时ECDH公钥,检查和服务端的ECDH公钥是否采用了相同的曲线参数。

4.8 Certificate Verify

当客户端发送了包含了一个可用于数字签名的公钥客户证书时,需要发送本消息。这个消息用来保证证书公钥的有效性。

消息结构:

        CertificateVerify.signature.sha_hash

            SHA(handshake_messages);

这个SHA也可以用其它的散列算法进行代替,采用ECC算法进行签名之后的结构如下:

Ecdsa-Sig-Value ::=SEQUENCE {

            r       INTEGER,

            s       INTEGER

        }

也是我们SM2签名采用的结构。

发送者动作:

       客户端将从clienthello开始到上一个消息进行散列,然后再用和证书对应的是要进行签名,发送给服务端。

接收者动作:

     服务端用Certificate消息中的证书中的公钥进行验证。


你可能感兴趣的:(信息安全)