◆苗新亮 雷 波 劉 棟
(中國電子科技集團(tuán)公司第三十研究所 四川 610041)
采用OpenSSL簽發(fā)的RSA證書,通過Windows的證書查看器發(fā)現(xiàn),公鑰部分經(jīng)過了ASN.1編碼,在實(shí)際公鑰的基礎(chǔ)上增加了ASN.1編碼的頭部和尾部。而采用OpenSSL簽發(fā)的ECC證書,通過Windows的證書查看器發(fā)現(xiàn),公鑰部分并沒有采用ASN.1編碼:證書中的公鑰起始部分僅比實(shí)際公鑰多了一個(gè)字節(jié),即“04”。那么這個(gè)“04”的具體含義是什么?為什么會(huì)在ECC的證書里出現(xiàn)?能否不要這個(gè)“04”?下面將對(duì)這一系列問題進(jìn)行分析回答。
根據(jù)美國國家標(biāo)準(zhǔn)ANSI X9.62中的描述:一個(gè)橢圓曲線點(diǎn)P(不是無窮遠(yuǎn)點(diǎn)O)由兩個(gè)域元素表示,x坐標(biāo)和y坐標(biāo),標(biāo)記為P=(xp,yp)。這個(gè)點(diǎn)可以使用x坐標(biāo)xp和一個(gè)確定比特zp壓縮表示為(xp,zp),這個(gè)確定比特zp衍生自x坐標(biāo)xp和y坐標(biāo)yp。
IEEE標(biāo)準(zhǔn) 1363TM-2000中也對(duì)橢圓曲線點(diǎn)的壓縮進(jìn)行了描述,并與美國國家標(biāo)準(zhǔn) ANSI X9.62基本一致。在IEEE標(biāo)準(zhǔn)1363aTM-2004中對(duì)橢圓曲線點(diǎn)的壓縮形式進(jìn)行了擴(kuò)展,將原有的壓縮形式定義為LSB壓縮形式,擴(kuò)展增加了SORT壓縮形式。LSB壓縮形式是指壓縮比特是yp或ypxp?1的整數(shù)表示的最低有效位。SORT壓縮形式是指壓縮比特是yp和y'p整數(shù)表示的比較結(jié)果。其中,點(diǎn)是點(diǎn)的逆,在素?cái)?shù)域Fp中y'p=?yp,在二元擴(kuò)域 F2中
在我國的SM2橢圓曲線公鑰密碼算法標(biāo)準(zhǔn)中,采用的壓縮形式與美國國家標(biāo)準(zhǔn)ANSI X9.62基本相同。在OpenSSL中,點(diǎn)的壓縮完全遵循了美國國家標(biāo)準(zhǔn)ANSI X9.62,即采用了LSB壓縮形式。ANSI X9.62中的壓縮過程如下:
1.1.1 素?cái)?shù)域上的點(diǎn)壓縮
(2)計(jì)算αmodp的平方根β。如果沒有平方根存在則報(bào)錯(cuò);
(3)如果β最右側(cè)一個(gè)比特與zp相等,那么設(shè)置yp=β,否則設(shè)置yp=p?β。
1.1.2 二元擴(kuò)域上的點(diǎn)壓縮
只要能夠獲得P的x坐標(biāo)xp和zp,yp就能重新計(jì)算出來,詳細(xì)計(jì)算方式如下:
②尋找一個(gè)域元素β,使得,如果沒有解則報(bào)錯(cuò);
在美國國家標(biāo)準(zhǔn)ANSI X9.62定義了點(diǎn)與八位字節(jié)串的相互轉(zhuǎn)換方式,以便于必要的時(shí)候以字符串的形式展示。無窮遠(yuǎn)點(diǎn)O使用一個(gè)八位字節(jié)串(octet string)表示為PC=00。一個(gè)非無窮遠(yuǎn)點(diǎn)的圓曲線點(diǎn)可以表示為一個(gè)以下三種形式的字符串:壓縮形式、非壓縮形式、混合形式。標(biāo)準(zhǔn)中直接使用了IEEE標(biāo)準(zhǔn)1363TM-2000的一些結(jié)論。
在IEEE標(biāo)準(zhǔn)1363TM-2000中,點(diǎn)與八位字節(jié)串的相互轉(zhuǎn)換方式不僅定義了這三種表示形式,還清楚的定義出了具體格式:
其中,PC是一個(gè)固定格式的字節(jié),使用二進(jìn)制表示為000UC。如果是非壓縮形式或混合形式,U比特等于1,否則于0。如果是壓縮形式或混合形式,C比特等于1,否則等于0。如果是壓縮形式或混合形式,特等于zp,否則等于0。
XP是xp的八位字節(jié)串表示。如果是壓縮形式或混合形式,YP是yp的八位字節(jié)串表示,否則YP為空。
IEEE標(biāo)準(zhǔn)1363aTM-2004對(duì)PC的格式進(jìn)行修訂,使用二進(jìn)制表示為。其中,如果采用了SORT壓縮形式,S比特為1,否則為0。其他定義的內(nèi)容沒有變化。
在我國的SM2橢圓曲線公鑰密碼算法標(biāo)準(zhǔn)中,采用的轉(zhuǎn)換方式與美國國家標(biāo)準(zhǔn)ANSI X9.62基本相同。
在OpenSSL中,點(diǎn)的轉(zhuǎn)換完全遵循了美國國家標(biāo)準(zhǔn)ANSI X9.62,與IEEE標(biāo)準(zhǔn)1363TM-2000保持一致。ANSI X9.62中的轉(zhuǎn)換過程如下:
1.2.1 點(diǎn)到八位字節(jié)串的轉(zhuǎn)換
輸出:一個(gè)八位字節(jié)串PO。如果選用壓縮方式,得到的PO中有L+1個(gè)字節(jié)。如果選用不壓縮或者混合形式,得到的PO中有2L+1個(gè)字節(jié)。(其中,
按照如下步驟進(jìn)行點(diǎn)到八位字節(jié)串的轉(zhuǎn)換獲得PO:
(1)將x坐標(biāo)xp轉(zhuǎn)換成八位字節(jié)串XP;
(2)如果選擇壓縮形式,則采用如下步驟:
①計(jì)算zp;
②如果zp為0,則設(shè)置單字節(jié)變量PC=02,如果zp為1,則設(shè)置PC=03;
(3)如果選擇不壓縮形式,則采用如下步驟:
①將y坐標(biāo)yp轉(zhuǎn)換成八位字節(jié)串YP;
(4)如果采用混合形式,則采用如下步驟:
①將y坐標(biāo)yp轉(zhuǎn)換成八位字節(jié)串YP;
②計(jì)算zp;
③如果zp為0,則設(shè)置單字節(jié)變量PC=06,如果zp為1,則設(shè)置PC=07;
1.2.2 八位字節(jié)串到點(diǎn)的轉(zhuǎn)換
輸入:定義在素?cái)?shù)域Fp上橢圓曲線的域元素a和b,一個(gè)八位字節(jié)串PO。如果選用壓縮方式,PO的長度為L+1字節(jié)。如果選用不壓縮或者混合形式,PO的長度為2L+1字節(jié)。(其中,
按照如下步驟進(jìn)行八位字節(jié)串到點(diǎn)的轉(zhuǎn)換獲得P:
(1)如果選用壓縮形式,PO可以解析為如果選用非壓縮形式或混合形式,PO可以解析為。其中,PC是一個(gè)字節(jié),XP是一個(gè)長度為L的字節(jié)串,YP是一個(gè)長度為L的字節(jié)串;
(2)將八位字節(jié)串XP轉(zhuǎn)換為xp;
(3)如果使用的是壓縮形式,則采用如下步驟:
①檢查PC是02還是03,如果都不是則報(bào)錯(cuò);
②如果PC是02,則設(shè)置;如果PC是03,則設(shè)置
(4)如果使用的是未壓縮形式,則采用如下步驟:
①檢查PC是否是04,如果不是則報(bào)錯(cuò);
②將八位字節(jié)串YP轉(zhuǎn)換為yp;
(5)如果使用的是混合形式,則采用如下步驟:
①檢查PC是06還是07,如果都不是則報(bào)錯(cuò);
②將八位字節(jié)串YP轉(zhuǎn)換為yp;
③如果PC是06,則設(shè)置;如果PC是07,則設(shè)置
④執(zhí)行以下一個(gè)或兩個(gè)步驟:
(6)如果q是一個(gè)素?cái)?shù),則驗(yàn)證,如果不是這種情形則報(bào)錯(cuò)。如果,則驗(yàn)證,如果不是這種情形則報(bào)錯(cuò);
其實(shí),采用OpenSSL簽發(fā)出的ECC證書,可以通過修改OpenSSL源碼,去掉這個(gè)橢圓曲線點(diǎn)的壓縮形式標(biāo)識(shí)“04”,通過Windows證書查看器看到的公鑰就是實(shí)際的公鑰。
在OpenSSL中關(guān)于橢圓曲線點(diǎn)的壓縮形式定義在cryptoecec.h文件中,是一個(gè)名為point_conversion_form_t的枚舉類型,具體如下:
/** Enum for the point conversion form as defined in X9.62(ECDSA)
*for the encoding of a elliptic curve point(x,y)*/
typedef enum {
/** the point is encoded as z||x,where the octet z specifies
*which solution of the quadratic equation y is */
POINT_CONVERSION_COMPRESSED = 2,
/** the point is encoded as z||x||y,where z is the octet 0x02 */
POINT_CONVERSION_UNCOMPRESSED=4,
/** the point is encoded as z||x||y,where the octet z specifies
技術(shù)與應(yīng)用
* which solution of the quadratic equation y is */
POINT_CONVERSION_HYBRID = 6,
} point_conversion_form_t;
2.2.1 修改定義
雖然在OpenSSL中只定義了上述三種標(biāo)識(shí),但是從IEEE標(biāo)準(zhǔn)1363aTM-2004可以看出,還有08等幾種定義。因此,需要在point_conversion_form_t枚舉中增加一種與之不沖突的定義POINT_CONVERSION_COPYED=16,即對(duì)x和y直接拷貝,或者可以理解為將點(diǎn)直接編碼為的形式。
2.2.2 修改點(diǎn)到八位字節(jié)串的轉(zhuǎn)換處理
OpenSSL在其源碼中提供了素?cái)?shù)域和二元擴(kuò)域兩個(gè)橢圓曲線點(diǎn)EC_POINT到八位字節(jié)串的轉(zhuǎn)換。因此,需要分別修改cryptoecec2_oct.c中的ec_GF2m_simple_point2oct函數(shù)和cryptoececp_oct.c中的ec_GFp_simple_point2oct函數(shù)。兩者的修改方式基本相同:當(dāng)form參數(shù)為POINT_CONVERSION_COPYED時(shí),不再將form填入輸出緩沖區(qū)buf的首字節(jié)中,并且返回值為兩倍的模長2*field_len。
2.2.3 修改八位字節(jié)串到點(diǎn)的轉(zhuǎn)換處理
OpenSSL中素?cái)?shù)域和二元擴(kuò)域上八位字節(jié)串轉(zhuǎn)換成橢圓曲線點(diǎn)EC_POINT實(shí)現(xiàn)函數(shù)是:cryptoecec2_oct.c中的ec_GF2m_simple_oct2point函數(shù)和cryptoececp_oct.c中的ec_GFp_simple_oct2point函數(shù)。如果八位字節(jié)串的長度為2*field_len,則認(rèn)為橢圓曲線點(diǎn)的壓縮形式form 為POINT_CONVERSION_COPYED,即只對(duì)x和y進(jìn)行了自然連接,并從正確的位置提取x和y。
2.2.4 修改從緩沖區(qū)解碼私鑰對(duì)象的處理
修改OpenSSL中從緩沖區(qū)解碼獲得私鑰對(duì)象的d2i_ECPrivateKey函數(shù)實(shí)現(xiàn)。用獲取到的公鑰八位字節(jié)串的長度pub_oct_len對(duì)模長field_len求余數(shù),余數(shù)為0時(shí),則認(rèn)為只對(duì)x和y進(jìn)行了自然連接,壓縮形式為POINT_CONVERSION_COPYED,余數(shù)為1時(shí)則通過公鑰部分的首字節(jié)計(jì)算壓縮形式。最后將獲得的壓縮形式,賦值給私鑰對(duì)象的conv_form屬性。
采用相同的方式修改OpenSSL中從緩沖區(qū)解碼獲得公鑰對(duì)象的o2i_ECPublicKey函數(shù)實(shí)現(xiàn)。
在調(diào)用OpenSSL時(shí),簽發(fā)證書時(shí),需要明確使用POINT_CONVERSION_COPYED標(biāo)識(shí),作為form的值傳遞給證書簽發(fā)函數(shù)。
如果僅僅是進(jìn)行證書簽發(fā)測(cè)試,通過OpenSSL自身提供的工具就可實(shí)現(xiàn)。不過還需要修改該工具,使其能夠支持POINT_CONVERSION_COPYED。修改apps目錄中的ec.c和ecparam.c中對(duì)“-conv_form”選項(xiàng)的處理,當(dāng)參數(shù)為“copyed”時(shí),將form設(shè)置為POINT_CONVERSION_COPYED使用。
然后按照如下步驟簽發(fā)橢圓曲線證書:
(1)采用prime256v1橢圓曲線產(chǎn)生一個(gè)密鑰文件:openssl ecparam -out Ecc.key -name prime256v1 –genkey;
(2)利用密鑰文件產(chǎn)生證書請(qǐng)求,并輸入證書相關(guān)信息:openssl req -key Ecc.key -new -out Ecc.req;
(3)使用密鑰文件Ecc.key將證書請(qǐng)求Ecc.req簽發(fā)成證書文件,即一個(gè)自簽發(fā)證書,或者叫做根證書:openssl x509 -req -in Ecc.req -signkey Ecc.key -out Ecc.cer。
通過上述步驟簽發(fā)出的證書Ecc.cer,通過Windows查看器打開后,能夠看到該證書的公鑰部分已經(jīng)沒有“04”了。
通過對(duì)ANSI X9.62、IEEE 1363TM-2000、IEEE 1363aTM-2004、SM2橢圓曲線公鑰密碼算法等標(biāo)準(zhǔn)的解讀,對(duì)OpenSSL源碼的修改,不但可以簽發(fā)出不帶壓縮形式標(biāo)識(shí)的橢圓曲線證書,也可以利用已修改的OpenSSL,對(duì)橢圓曲線證書進(jìn)行驗(yàn)證。
經(jīng)過修改的OpenSSL,可在一些非常規(guī)標(biāo)準(zhǔn)特殊行業(yè)中進(jìn)行應(yīng)用。簽發(fā)出的橢圓曲線證書,可在嵌入式應(yīng)用等無法集成龐大的OpenSSL的小微型應(yīng)用中使用。