SM2密碼算法應用分析

1 曲線

參考《SM2橢圓曲線公鑰密碼算法第1部分:總則》(GM/T0003.1-2012),2012-03-21發佈版本。

1.1  Fp上的橢圓曲線

定義在Fp(p是大於3的素數)上的橢圓曲線方程爲:

y2 = x3+ax+b a;b Fp,且(4a3+27b2) modp ̸= 0--------------------(1)

橢圓曲線E(Fp)定義爲:

E(Fq) = {(x;y)|x;y Fp,且滿足方程(1)}{O},其中O是無窮遠點。

橢圓曲線E(Fp)上的點的數目用#E(Fq)表示,稱爲橢圓曲線E(Fp)的階。

1.2  F2m上的橢圓曲線

定義在F2m上的橢圓曲線方程爲:

y2+xy = x3+ax2+ba;b F2m,且b ̸= 0-------------------- (2)

橢圓曲線E(F2m )定義爲:

E(F2m) = {(x;y)|x;y F2m,且滿足方程(2)}{O},其中O是無窮遠點。

橢圓曲線E(F2m )上的點的數目用#E(F2m)表示,稱爲橢圓曲線E(F2m )的階。

2 曲線參數

參考《SM2橢圓曲線公鑰密碼算法第5部分:參數定義》(GM/T0003.5-2012),2012-03-21發佈版本。

SM2只有Fp上的橢圓曲線的推薦參數

推薦使用素數域256位橢圓曲線。

橢圓曲線方程:y2 = x3 + ax + b

曲線參數:

p=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF 00000000 FFFFFFFF FFFFFFFF

a=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF 00000000 FFFFFFFF FFFFFFFC

b=28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7F39789F5 15AB8F92 DDBCBD41 4D940E93

n=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF7203DF6B 21C6052B 53BBF409 39D54123

Gx=32C4AE2C 1F198119 5F990446 6A39C9948FE30BBF F2660BE1 715A4589 334C74C7

Gy=BC3736A2 F4F6779C 59BDCEE3 6B692153D0A9877C C62A4740 02DF32E5 2139F0A0

 

國際通用的X9.62命名曲線有很多,下面略舉2Fp曲線:

256bits:

p=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF

a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC

b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B

n=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551

Gx=6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296

Gy=4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5

h=1

192bits:

p=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF

a=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC

b=64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1

n=FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831

Gx=188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012

Gy=7192B95FFC8DA78631011ED6B24CDD573F977A11E794811

h=1

3 密鑰語法

參考《SM2密碼算法使用規範》(GM/T0009-2012),2012-11-22發佈版本。

3.1  SM2私鑰

SM2私鑰是一個大於等於1並且小於n-1的整數,記爲k,長度爲32字節。

SM2PrivateKey ::= INTEGER

GMT0010SM2密碼算法加密簽名消息語法規範》中定義了和X9.62相同的私鑰語法:

ECPrivateKey{CURVES:IOSet}::= SEQUENCE {
  version INTEGER {ecPrivkeyVer1(1)}(ecPrivkeyVer1),
  privateKey SM2PrivateKey,(其實X9.62中,這裏是OCTETSTRING,而不是上面的INTEGER)
  parameters[0] Parameters{{IOSet}}OPTIONAL,
  publicKey [1] SM2PublicKey
}

其實上面的定義還不夠完善,真正要實現私鑰交換的話,還要封裝成PKCS#8格式:
PrivateKeyInfo ::=SEQUENCE {
 version Version,
 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
 privateKey PrivateKey,
 attributes [0] IMPLICIT Attributes OPTIONAL
}
Version ::=INTEGER (目前取0)
PrivateKeyAlgorithmIdentifier ::=AlgorithmIdentifier(和公鑰定義相同)
PrivateKey ::=OCTET STRING(即是ECPrivateKey)

3.2  SM2公鑰

SM2公鑰是SM2曲線上的一個點,由橫座標和縱座標兩個分量來表示,記爲(xy,簡記爲Q,長度爲64字節。Q=kG,是私鑰與曲線基點的乘積

SM2PublicKey::=BIT STRING

SM2PublicKey爲類型,內容爲04||X||Y,其中XY分別標識公鑰的X分量和Y分量。其長度各爲256位。

GMT0010SM2密碼算法加密簽名消息語法規範》中定義了和X9.62相同的主題公鑰語法:

SubjectPublicKeyInfo ::= SEQUENCE {

 algorithm AlgorithmIdentifier{{ECPKAlgorithms}},

 subjectPublicKey SM2PublicKey

}

AlgorithmIdentifier::= SEQUENCE {

 algorithm OBJECTIDENTIFIER,

 parameters ANY DEFINED BY algorithm OPTIONAL

}

algorithm OIDX9.62相同:iso(1) member-body(2) us(840)ansi-x962(10045) keyType(2) ecPublicKey(1)

Parameters::= CHOICE {

  ecParametersECParameters,

  namedCurveObjectIdentifier,

  implicitlyCA NULL

}

參數是命名曲線OIDiso(1) member-body(2) cn(156) ccstc(10197) 1.301,即SM2。公鑰數據是SM2PublicKey::= BIT STRING,即04||X||Y

3.3  加密後的SM2密鑰對

SM2EnvelopedKey::=SEQUENCE{

symAlgID  AlgorithmIdentifier,--對稱密碼算法標識

symEncryptedKey  SM2Cipher,--對稱密鑰密文,參見

Sm2PublicKey SM2PublicKey,--SM2公鑰

Sm2EncryptedPrivateKey BITSTRING  --SM2私鑰密文(對稱加密)

}

3.4  用戶標識ID的默認值

無特殊約定的情況下,用戶標識ID的長度爲16字節,其默認值從左至右依次爲:

0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38

4 運算過程

4.1  簽名

設待簽名的消息爲M,爲了獲取消息M的數字簽名(r,s),作爲簽名者的用戶A應實現以下運算步驟:

A1:置M=ZAM;ZA= Hv(ENTLA||IDA||a||b||Gx||Gy||Ax||Ay);ENTLA爲IDA的比特長度,2字節;IDA用戶標識默認值見上節;a,b,Gx,Gy見曲線參數;Ax,Ay爲公鑰座標

A2:計算e = Hv(M),按規則將e的數據類型轉換爲整數;

A3:用隨機數發生器產生隨機數k[1,n-1]

A4:計算橢圓曲線點(x1,y1)=[k]G,按規則將x1的數據類型轉換爲整數;

A5:計算r=(e+x1) modn,若r=0r+k=n則返回A3

A6:計算s = ((1 +dA)^−1 • (k − r • dA)) mod n,若s=0則返回A3

A7:按規則將rs的數據類型轉換爲字節串,消息M的簽名爲(r,s)

注:按上面的曲線參數,則rs分別爲32字節,即簽名值爲64字節。但按照《SM2密碼算法使用規範(GM/T 0009-2012)》,簽名結果爲ASN.1編碼:

SM2Signature::= SEQUENCE {

R  INTEGER,  --簽名值的第一部分

S  INTEGER      --簽名值的第二部分

}

4.2  驗證

爲了檢驗收到的消息M′及其數字簽名(r, s),作爲驗證者的用戶B應實現以下運算步驟:

B1:檢驗r′ ∈[1,n-1]是否成立,若不成立則驗證不通過;

B2:檢驗s′ ∈[1,n-1]是否成立,若不成立則驗證不通過;

B3:置M=ZA M′;

B4:計算e = Hv(M),按規則將e′的數據類型轉換爲整數;

B5:按規則將r′、s′的數據類型轉換爲整數,計算t = (r + s) modn,若t = 0,則驗證不通過;

B6:計算橢圓曲線點(x1; y1)=[s]G +[t]PA

B7:按規則將x1的數據類型轉換爲整數,計算R = (e + x1) modn,檢驗R=r′是否成立,若成立則驗證通過;否則驗證不通過。

 

X9.62 ECDSA的簽名與驗證過程:

簽名:

1. Select a random or pseudorandom integerk, 1<=k<=n-1.

2. Compute [k]G = (x1,y1) and convert x1 toan integer x1`.

3. Compute r= x1 mod n. If r=0 then go tostep 1.

4. Compute k^-1 mod n.

5. Compute SHA-1(m) and convert this bitstring to an integer e.

6. Compute s = k^-1(e+dA*r) mod n. If s=0then go to step 1.

7. A's signature for the message m is(r,s).

驗證:

1. Verify that r and s are integers in theinterval [1,n-1].

2. Compute SHA-1(m) and convert this bit stringto an integer e.

3. Compute w = s^-1 mod n€.

4. Compute u1= e*w mod n and u2= r*w modn€.

5. Compute X= [u1]G+[u2]PA.

6. If X=O, then reject the signature.

  Otherwise, convert the x-coordinate x1

4.3  加密

設需要發送的消息爲比特串MklenM的比特長度。

爲了對明文M進行加密,作爲加密者的用戶A應實現以下運算步驟:

A1:用隨機數發生器產生隨機數k[1,n-1]

A2:計算橢圓曲線點C1=[k]G=(x1,y1),按本文本第1部分4.2.84.2.4給出的細節,將C1的數據類型轉換爲比特串;

A3:計算橢圓曲線點S=[h]PB,若S是無窮遠點,則報錯並退出;

A4:計算橢圓曲線點[k]PB=(x2,y2),按本文本第1部分4.2.54.2.4給出的細節,將座標x2y2的數據類型轉換爲比特串;

A5:計算t=KDF(x2 y2, klen),若t爲全0比特串,則返回A1

A6:計算C2 = M t

A7:計算C3 = Hash(x2 M y2)

A8:輸出密文C = C1 C3 C2

注:C1爲‘04’開頭,再加64字節的XYC332字節的Hash值,C2和明文長度相同。即加密結果是原文長度+97字節。但按照《SM2密碼算法使用規範(GM/T 0009-2012)》,簽名結果爲ASN.1編碼:

SM2Cipher::= SEQUENCE{

XCoordinate  INTEGER,  --x分量

YCoordinate  INTEGER,  --y分量

HASH      OCTECTSTRING SIZE(32), --雜湊值

CipherTextOCTECTSTRING--密文

}

4.4  解密

klen爲密文中C2的比特長度。

爲了對密文C=C1 C3 C2進行解密,作爲解密者的用戶B應實現以下運算步驟:

B1:從C中取出比特串C1,按本文本第1部分4.2.34.2.9給出的細節,將C1的數據類型轉換爲橢圓曲線上的點,驗證C1是否滿足橢圓曲線方程,若不滿足則報錯並退出;

B2:計算橢圓曲線點S=[h]C1,若S是無窮遠點,則報錯並退出;

B3:計算[dB]C1=(x2,y2),按本文本第1部分4.2.54.2.4給出的細節,將座標x2y2的數據類型轉換爲比特串;

B4:計算t=KDF(x2 y2, klen),若t爲全0比特串,則報錯並退出;

B5:從C中取出比特串C2,計算M = C2 t

B6:計算u = Hash(x2 M′ ∥ y2),從C中取出比特串C3,若u ̸= C3,則報錯並退出;

B7:輸出明文M′。

5 加密消息語法

SM2密碼算法加密簽名消息語法規範》(GM/T0010-2012)基本參照了PKCS#7的語法,然後再定義了一些國密算法的OID。令人奇怪的是,國密對datasignedDataenvelopedData等還自定義了一套自己的OID,而不是沿用CMS已有的OID,實在看不出這樣做有什麼好處。

SM2密碼算法加密簽名消息語法規範:iso(1) member-body(2) cn(156) ccstc(10197) 6.1.4.2

PKCS#7 OIDiso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7)

6 數字證書

《基於SM2密碼算法的數字證書格式規範》(GM/T0015-2012)定義的證書語法基本和RFC2459X.509證書格式相同。

國密還定義了一些證書擴展如:個人身份標識碼、個人社會保險號、企業工商註冊號、企業組織機構代碼、企業稅號等。

6.1  簽名算法

算法OID爲:1.2.156.10197.1.501。即SM3withSM2

參數爲:NULL

6.2  主題公鑰語法

參見本文“3.2 SM2公鑰”對主題公鑰的說明。


6.3  CA簽名值

ASN.1編碼的SM2Signature結構,見本文“4.1簽名”

7 開發接口

7.1  國密接口

國密接口有3個標準:《GMT0016智能密碼鑰匙密碼應用接口規範》、《GMT0018密碼設備應用接口規範》、《GMT0019通用密碼服務接口規範》。搞不清楚爲什麼要分這麼多標準。

7.2  PKCS#11

7.2.1 算法類型


pkcs11t.h已定義的ECC宏有:
#define CKM_EC_KEY_PAIR_GEN            0x00001040
#define CKM_ECDSA                      0x00001041
……

自己擴展:
#define SM2_MYCA_DEFINED 0x92ca04
SM2密鑰對產生
#define CKM_SM2_KEY_PAIR_GEN CKM_VENDOR_DEFINED+SM2_NETCA_DEFINED
SM2簽名(傳SM3 HASH值)
#define CKM_SM2DSA  CKM_SM2_KEY_PAIR_GEN+1
SM2加密
#define CKM_SM2IES  CKM_SM2_KEY_PAIR_GEN+2


7.2.2 密鑰類型


#define CKK_EC              0x00000003
自己擴展:
#define CKK_SM2  CKK_VENDOR_DEFINED+SM2_MYCA_DEFINED


7.2.3 密鑰模板


#define CKA_EC_PARAMS 0x00000180 (DER-encoding of an ANSI X9.62 Parameters value)
#define CKA_EC_POINT  0x00000181 (DER-encoding of ANSI X9.62 ECPoint value Q)
dA-->CKA_VALUE: (Biginteger)ANSI X9.62 private value d
PA(x,y)-->CKA_EC_POINT

7.3  CSP

Cryptographic Service Provider

CSP類型

在wincrypt.h有定義宏:
#define PROV_EC_ECDSA_FULL      16
#define PROV_EC_ECNRA_FULL      17


算法標識

在wincrypt.h有定義宏:
#define CALG_ECDH               (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | ALG_SID_ECDH)
#define CALG_ECMQV              (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_ANY | ALG_SID_ECMQV)
#define CALG_ECDSA              (ALG_CLASS_SIGNATURE | ALG_TYPE_DSS | ALG_SID_ECDSA)


密鑰結構

按《GMT0018密碼設備應用接口規範》

#define ECCref_MAX_BITS 512
#define ECCref_MAX_LEN ((ECCref_MAX_BITS+7)/8)
typedefstruct ECCrefPublicKey_st
{
  unsigned int bits;
  unsigned char x[ECCref_MAX_LEN];
  unsigned char y[ECCref_MAX_LEN];
}ECCrefPublicKey;
typedefstruct ECCrefPrivateKey_st
{
  unsigned int bits;
  unsigned char K[ECCref_MAX_LEN];
}ECCrefPrivateKey;

7.4  CNG

Cryptographic Next Generation

7.5  JCE

SunEC提供者只能支持X6.92的命名曲線,如果ECParameterSpec傳遞SM2的曲線參數,最終將報異常:“java.security.InvalidAlgorithmParameterException:Unsupported curve”。如果用bouncycastle(“BC”), ECParameterSpec可以正常傳遞SM2的曲線參數,但由於SM2的簽名與加密步驟都和X9.62/X9.63不同,所以出來的結果也不相同。需要自己在EC數學庫的基礎上實現SM2算法。


 

參考資料

  • SM2橢圓曲線公鑰密碼算法1部分:總則》(GM/T0003.1-2012),2012-03-21發佈版本

  • SM2橢圓曲線公鑰密碼算法2部分:數字簽名算法》(GM/T0003.2-2012),2012-03-21發佈版本

  • SM2橢圓曲線公鑰密碼算法4部分:公鑰加密算法》(GM/T0003.4-2012),2012-03-21發佈版本

  • SM2橢圓曲線公鑰密碼算法5部分:參數定義》(GM/T0003.5-2012),2012-03-21發佈版本

  • SM2密碼算法使用規範》(GM/T0009-2012),2012-11-22發佈版本

  • SM2密碼算法加密簽名消息語法規範》(GM/T0010-2012),2012-11-22發佈版本

  • 《基於SM2密碼算法的數字證書格式規範》(GM/T0015-2012),2012-11-22發佈版本











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