天天看點

ECC Cipher Suites 加密套件在TLS中的應用 RFC 4492簡介摘要名詞解釋 1.概述:2.密鑰交換算法:3.用戶端驗證4.資料結構和說明

簡介

 本文檔介紹了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消息中的證書中的公鑰進行驗證。

繼續閱讀