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

原文地址:http://blog.csdn.net/dyrou/article/details/10329311

簡介

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章