兼容RSA及国产商用密码算法的智能密匙签名方法与流程

文档序号:22581318发布日期:2020-10-20 17:03阅读:697来源:国知局
兼容RSA及国产商用密码算法的智能密匙签名方法与流程

【技术领域】

本发明涉及金融证券技术领域,具体涉及兼容rsa及国产商用密码算法的智能密匙签名方法。



背景技术:

在金融证券领域,登记存管、清算交收、资金划拨等的非交易指令传输,通常采用身份验证和签名等加密方式,进行通信保护。

随着国产商用密码算法的推广,金融证券领域的相关系统都面临应用系统进行国产商用密码算法改造的需求。在改造过程中,提供兼容rsa算法及国产商用密码算法的解决方案,符合市场实际,有利于系统平稳过渡,使得rsa算法及国产商用密码算法可并行运作。



技术实现要素:

本发明的目的在于针对现有技术的缺陷和不足,提供兼容rsa及国产商用密码算法的智能密匙签名方法。

本发明所述的兼容rsa及国产商用密码算法的智能密匙签名方法,采用如下步骤:

步骤一:封装:对pkcs#11接口定义的数据结构和函数进行封装;

步骤二:调用:利用步骤一的封装,调用pkcs#11接口获取证书的slot、session,获取到证书、公钥、私钥的object_handle;

步骤三:将包含rsa智能密码钥匙的私钥映射为evp_pkey,实现一个rsa数据结构,rsa_method中的签名函数指针用自身定义的sign函数代替,自身定义的sign函数调用pkcs#11接口的签名函数,通过智能密码钥匙ekey进行签名;

步骤四:适配支持pkcs#11接口的装载rsa证书的ekey;

步骤五:根据中国密码行业标准《gm/t0016-2012智能密码钥匙密码应用接口规范》中定义的skf接口,对接口中定义的数据结构和函数进行封装;

步骤六:利用步骤五的封装,调用skf接口枚举智能密码钥匙设备device,获取应用applictation、容器container,在相应的存储国产商用密码的container中获取sm2签名证书和加密证书;

步骤七:适配支持skf接口的装载sm2证书的ekey;

步骤八:使用skf接口通过智能密码钥匙完成sm2签名,并且应用于中国密码行业标准《gm/t0024-2014sslvpn技术规范》定义的密码套件和tls通信方法中;

步骤九:变更和扩展openssl中的ssl握手协议状态机中从ssl3_st_cw_cert_vrfy_a状态转换为ssl3_st_cw_cert_vrfy_b的相关函数;

基于步骤九的变更,使本方法兼容以上步骤三中的rsa智能密码钥匙签名、同时也兼容rsa私钥文件证书签名,兼容步骤八中sm2智能密码钥匙签名、同时也兼容sm2私钥文件证书签名;

步骤十:对pkcs#11和skf接口的使用、智能密码钥匙ekey的读取再进行一层封装,通过判断ekey中证书的签名算法,自动加载相应驱动库和接口函数,从而能自适应选择相应的处理分支,使用rsa算法进行签名或者使用国产商用密码算法进行签名。

本发明有益效果为:本发明所述的兼容rsa及国产商用密码算法的智能密匙签名方法,它采用将智能密码钥匙的一系列操作抽象实现为一个ekey接口层,实现可水平拓展的框架,包含枚举证书、签名等统一操作接口;对于rsa智能密码钥匙ekey,采用将证书私钥映射的方法,签名时指向自身定义的sign函数;对于国产商用密码算法智能密码钥匙ekey,采用扩展openssl中客户端发送验证的相关函数,调用国产商用密码标准规定的接口完成签名;它具有能够根据智能密码钥匙中证书的签名算法,采用rsa和国产商用密码算法,实现签名。

【附图说明】

此处所说明的附图是用来提供对本发明的进一步理解,构成本申请的一部分,但并不构成对本发明的不当限定,在附图中:

图1是本发明的pkcs11封装图

图2本发明的evp_pkey转化图;

图3本发明的rsasign函数流程图;

图4本发明的skf封装图;

图5本发明的skf签名流程图;

图6本发明的变更前流程图;

图7本发明的变更后流程图;

图8本发明的进一步封装结构图;

图9本发明的整体实现活动图。

【具体实施方式】

下面将结合附图以及具体实施例来详细说明本发明,其中的示意性实施例以及说明仅用来解释本发明,但并不作为对本发明的限定。

如图1-图9所示,本具体实施方式所述的兼容rsa及国产商用密码算法的智能密匙签名方法,采用如下步骤:

步骤一:封装:对pkcs#11接口定义的数据结构和函数进行封装;

步骤二:调用:利用步骤一的封装,调用pkcs#11接口获取证书的slot、session,获取到证书、公钥、私钥的object_handle;

步骤三:将包含rsa智能密码钥匙的私钥映射为evp_pkey,实现一个rsa数据结构,rsa_method中的签名函数指针用自身定义的sign函数代替,自身定义的sign函数调用pkcs#11接口的签名函数,通过智能密码钥匙ekey进行签名;

步骤四:适配支持pkcs#11接口的装载rsa证书的ekey;

步骤五:根据中国密码行业标准《gm/t0016-2012智能密码钥匙密码应用接口规范》中定义的skf接口,对接口中定义的数据结构和函数进行封装;

步骤六:利用步骤五的封装,调用skf接口枚举智能密码钥匙设备device,获取应用applictation、容器container,在相应的存储国产商用密码的container中获取sm2签名证书和加密证书;

步骤七:适配支持skf接口的装载sm2证书的ekey;

步骤八:使用skf接口通过智能密码钥匙完成sm2签名,并且应用于中国密码行业标准《gm/t0024-2014sslvpn技术规范》定义的密码套件和tls通信方法中;

步骤九:变更和扩展openssl中的ssl握手协议状态机中从ssl3_st_cw_cert_vrfy_a状态转换为ssl3_st_cw_cert_vrfy_b的相关函数;

基于步骤九的变更,使本方法兼容以上步骤三中的rsa智能密码钥匙签名、同时也兼容rsa私钥文件证书签名,兼容步骤八中sm2智能密码钥匙签名、同时也兼容sm2私钥文件证书签名;

步骤十:对pkcs#11和skf接口的使用、智能密码钥匙ekey的读取再进行一层封装,通过判断ekey中证书的签名算法,自动加载相应驱动库和接口函数,从而能自适应选择相应的处理分支,使用rsa算法进行签名或者使用国产商用密码算法进行签名。

本发明就其工作原理,结合附图,作进一步详细陈述,陈述如下:

s1:对pkcs#11接口定义的数据结构和函数进行封装,利用此封装,调用pkcs#11接口获取证书的slot、session,获取到证书、公钥、私钥的object_handle等。如图1所示,图1为pkcs#11封装图。

[1]定义一个接口context,封装pkcs#11中的数据结构槽slot,记录slot的id(slotidx);

[2]将各硬件智能密码钥匙在各平台下的驱动库库,抽象映射为dso(dso_st数据结构),通过dso_load加载windows平台的驱动库dll和linux平台的驱动库so(pkcs11.dll/so);

[3]通过bind系列中dso_bind_func实现动态加载硬件驱动库中实现的接口函数,为接下来的证书提取和签名操作提供统一的接口(methodlisthandle);

[4]在创建一个context接口时,实现上述1,2,3中封装智能密码钥匙驱动实现的接口函数,得到统一操作接口methodlist,利用此操作接口,调用c_initialize初始化;

[5]将c_getinfo封装为getcryptokiinfo,指向ck_info信息单元,获取智能密码钥匙硬件的cryptoki信息;

[6]在context中封装initslots,使用c_getslotlist,获取智能密码钥匙硬件中的槽slot的名单,由此得到以ck_slot_id为单位的slot缓冲列表;

[7]封装一个slot接口,在initslots后,使用getslotinfo调用c_getslotinfo获取特定槽的信息;

[8]通过[6]中获取到的特定槽id,使用gettokeninfo调用c_gettokeninfo获取当前的智能密码钥匙硬件的信息,指向ck_token_info;

[9]封装一个接口session,其包括会话session的一系列操作,以建立智能密码钥匙与应用程序的逻辑链接;

[10]newsession时,封装调用c_opensession,打开应用程序和目前操作的智能密码钥匙之间的连接;

[11]在一个session中,搜索对象object,object为智能密码钥匙中存储的一个项目,为证书、密钥等。封装一系列object操作对象为refresssession,主要执行c_findobjectinit、c_findobjects、c_findobjectsfinal完成对象的搜索;

[12]利用中[11]搜索得到ck_object_class,并封装getcertificates,其用于获取包含公钥的证书对象cko_certificate;

[13]封装getpublicekey,为获得公钥对象cko_public_key;

[14]封装getprivatekey,为获取私钥对象cko_private_key。

s2、将包含rsa智能密码钥匙的私钥映射为evp_pkey,实现一个rsa数据结构,其rsa_method中的签名函数指针用自身定义的sign函数代替。如图2所示,图2为evp_pkey转化图。

[1]由s1[11]中的会话session中搜索object,使用1[14]中中getprivatekey,获取到私钥对象cko_private_key;

[2]封装一个getevppkey接口,将cko_private_key转化为可供后续签名的evp_pkey;

[3]初始化一个evp_pkey结构pkey;

[4]应用evp_pkey_get1_rsa接口,输入为[3]中pkey,初始化一个rsa(rsa_st)数据结构;

[5]如果[4]执行获得的rsa数据结构为null,则使用rsa_new新建一个rsa数据结构rsa_st1,应用evp_pkey_set1_rsa接口,输入为rsa_st1及[3]中的pkey;

[6]定制此rsa数据结构rsa;

[7]定制模数n,使用getattributebn接口,输入cka_modulus作为参数;

[8]定制公钥指数e,使用getattributebn接口,输入cka_public_exponent;

[9]若n、e都定制成功,定制rsa数据结构中的rsa_method函数链meth;

[10]函数链meth中的签名函数指向自身重定义的签名函数sign;

[11]设置rsa数据结构中的flag或等运算rsa_flag_sign_ver;

[12]rsa数据结构中的crypto_ex_data不能为空,使用x509_get_ex_new_index接口重构freefunc,指向key的释放,key是转化为evp_pkey的密钥对象的智能指针集合;

[13]完成[12]的重构后,使用rsa_set_ex_data接口设置crypto_ex_data。

s3、自身重定义的sign函数调用pkcs#11接口的签名函数,通过智能密码钥匙ekey进行签名。参考图3rsasign函数流程图。

[1]sign函数的输入为摘要类型type,待签名的数据m,签名数据长度(占用字节数)m_len,接收签名的单元sigret,接收签名的单元长度siglen,2中通过定制的rsa数据结构rsa;

[2]初始化一个key对象,此key对象为转化为evp_pkey后的密钥对象的智能指针key;

[3]使用2[13]中rsa_set_ex_data的逆向接口rsa_get_ex_data,输入为2中定制的rsa数据结构rsa,取出其定制的特殊数据,指向key;

[4]初始化一系列结构,包括x509_sig结构sig,asn1_type结构parameter,签名数据长度临时变量i,接收签名的单位长度临时变量j,要签名数据的临时存储指针p、s,x509_algor结构algor,asn1_octet_string结构digest,ck_mechanism签名机制mechanism_rsa;

[5]通过输入的摘要类型type判断摘要类型;

[6]如果摘要类型等于nid_md5_sha1,设置ssl结构中摘要长度为ssl_sig_length,签名数据长度临时变量i=ssl_sig_length。待签名的数据m指向要签名数据的临时存储指针s;

[7]如果摘要类型不等于nid_md5_sha1,设置x509_sig结构sig;

[8]将x509_sig结构sig和x509_algor结构algor关联起来,sig中的x509_algor的地址指向algor;

[9]algor中的asn1_object结构algorithm算法,使用obj_nid2obj接口赋值,参数为输入的摘要类型type。执行后,注意判断algorithm算法是否为null,并且其asn1_object_st结构中的length是否为0;

[10]设置asn1_type结构parameter的type为v_asn1_null;

[11]设置x509_sig结构sig的x509_algor结构algor,其算法parameter指向[10]中设置的parameter;

[12]设置x509_sig结构sig的asn1_octet_string结构为digest;

[13]设置digest结构中的签名数据data为输入的待签名的数据m;

[14]设置digest结构中的签名数据长度length为输入的m_len;

[15]调用i2d_x509_sig接口,输入是上述经过设置的sig,输出是签名数据长度临时变量i;

[16]应用rsa_size接口,量度定制的rsa数据结构rsa,赋值给接收签名的单位长度临时变量j;

[17]如果输入的摘要类型type不等于nid_md5_sha1,调用openssl_malloc,参数为j+1,通过函数malloc_ex_func(malloc)分配内存,通过函数crypto_malloc_dbg把申请的信息存入哈希表中,输出s;

[18]调用i2d_x509_sig接口,输入是上述经过设置的x509_sig结构sig、s;

[19]如果key中session的操作句柄获取成功,取得驱动中封装的数据结构和函数的methodlist句柄,调用pkcs#11的接口c_signinit,输入为session的操作句柄(gethandle),签名机制mechanism_rsa,设置为ckm_rsa_pkcs;

[20]利用methodlist操作句柄,调用智能密码钥匙中的pkcs#11的接口c_sign,输入session的操作句柄(gethandle)、待签名的数据s、签名数据的长度i、接收签名的单元sigret、接收签名的单位长度j,使用硬件进行签名。

s4、根据国产商用密码标准《gm/t0016-2012智能密码钥匙密码应用接口规范》中定义的skf接口,对接口中定义的数据结构和函数进行封装,参考图4skf接口封装图。

[1]封装加载驱动的数据结构和函数为init_skf_api,不同的操作系统调用不同的如在windows中包含loadlibrary、getprocaddress的使用,在linux中包含dlopen、dlsym的使用;

[2]init_skf_api后同样获得智能密码钥匙驱动中实现的skfmethodlist函数列表及对应的函数操作指针;

[3]应用methodlist中得到的skf_enumdev接口操作指针枚举接入的智能密码钥匙设备,映射为device;

[4]应用skf_connectdev接口链接相应的设备,并用skf_getdevinfo取得设备的信息,同时得到设备的操作指针devhandle;

[5]利用上述得到的devhandle,使用skf_enumapplication枚举device中的应用application;

[6]应用skf_openapplication接口获取应用的操作指针happlication;

[7]利用上述得到的happlication,应用skf_enumcontainer接口枚举application中的容器container,容器中包含签名公钥、签名私钥,加密公钥、加密私钥,及会话密钥;

[8]应用skf_opencontainer接口打开对应的containter,获取container的操作指针hcontainer;

[9]利用上述得到的hcontainer,调用skf_exportcertificate获取需要的证书。

s5、调用skf接口枚举智能密码钥匙设备device,获取应用applictation、容器container、在相应的存储国产商用密码的container中获取sm2签名证书和加密证书,并且使用skf接口通过智能密码钥匙完成sm2签名。参考图5skf签名流程图,以下为概况的步骤,详细的实现方法见以下s7中描述的变更后的流程。

[1]根据s4中的封装,获取到设备、应用、容器的操作指针hdevice、happlication、hcontainer,并且获得智能密码钥匙驱动中实现的skf接口函数操作指针hskfmethodhandle;

[2]判断系统接入的是否是国产商用密码算法的智能密码钥匙ekey;

[3]如果不是,采用上述提到的转化私ekey私钥为evp_pkey,并重定义sign函数的方法处理;

[4]如果是国产商用密码算法ekey,采用hskfmethodhandle调用skf_exportpublickey接口从ekey中导出签名公钥结构;

[5]对此公钥结构进行处理;

[6]计算z值;

[7]设置evp摘要算法为sm3;

[8]创建一个evp_md_ctx上下文;

[9]进行evp_digest系列函数处理;

[10]使用硬件ekey,利用hskfmethodhandle调用skf_eccsigndata接口计算sm3(z||digest);

[11]计算握手头的长度;

[12]设置握手头的长度;

[13]改变状态机状态从ssl3_st_cw_cert_vrfy_a状态转换为ssl3_st_cw_cert_vrfy_b状态;

s6、变更和扩展openssl中的ssl握手协议状态机中从ssl3_st_cw_cert_vrfy_a状态转换为ssl3_st_cw_cert_vrfy_b的相关函数,主要的函数为ssl\s3_clnt.c中的ssl3_send_client_verify,输入为ssl上下文s,先说明变更前的ssl3_send_client_verify函数流程,参考图6。

[1]初始化临时变量,包括evp_pkey结构pkey,evp_pkey_ctx上下文pctx,evp_md_ctx结构mctx;

[2]使用evp_md_ctx_int初始化摘要上下文,输入为[1]中mctx;

[3]判断状态机的状态是否为ssl3_st握手,cw_cert_vrfyclientwrite客户端写状态,刚进入状态certverify证书校验,是否为ssl3_st_cw_cert_vrfy_a状态;

[4]调用ssl_handshake_start,输入为ssl上下文s,输出为指针p;

[5]ssl上下文s的key中私钥指针privatekey指向[1]中定义的pkey;

[6]调用evp_pkey_ctx_new使用pkey初始化[1]中evp_pkey_ctx上下文pctx;

[7]调用evp_pkey_sign_init,输入为pctx,进行签名初始化;

[8]使用evp_pkey_ctx_set_signature_md设置pctx的摘要算法结构为evp_sha1(sha1);

[9]如果采用tls1.2发送签名算法和结构,进行特殊处理:

a.调用tls12_get_sigandhash,输入为[4]中p,[5]中pkey,ssl上下文s中配置的key中的摘要信息evp_md结构md;

b.计算摘要,使用evp_sign系列函数(evp_signinit_ex、evp_signupdate、evp_signfinal),输入为[1]中定义的mctx,a中的md,[5]中的pkey;

c.计算握手消息头n。

[10]如果不采用tls1.2发送签名算法和结构。需要根据pkey的类型type进行判断;

[11]当pkey的类型为evp_pkey_rsa时,进行mac校验,利用pkey中rsa结构调用rsa_sign进行签名,并计算握手消息头n;

[12]当pkey的类型为evp_pkey_dsa时,利用pkey中的dsa结构调用dsa_sign进行签名,并计算握手消息头n;

[13]当pkey的类型为evp_pkey_ec时,利用pkey中的ec结构调用ecdsa_sign进行签名,并计算握手消息头n。

s7、详细说明变更后的ssl3_send_client_verify函数流程,参考图7。基于此的变更,可兼容以上3中的rsa智能密码钥匙签名、同时也兼容rsa私钥文件证书签名,兼容5中sm2智能密码钥匙签名、同时也兼容sm2私钥文件证书签名。

[1]初始化临时变量,包括evp_pkey结构pkey,evp_pkey_ctx上下文pctx,evp_md_ctx结构mctx;

[2]初始化中增加:

a.ec_key结构指针sm2key,预备存储使用x坐标和y坐标构成的sign_pubkey计算后的sm2公钥,并转化为ec_key的ec_key_st结构;

b.skf接口:ecc加密密钥对的公钥结构eccpublickeyblob(模式长度,椭圆曲线上基点g的k倍点x坐标,y坐标);

c.skf接口:ecc签名数据结构(r,s)eccsignatureblob;

d.要处理的摘要值digest;

e.evp_md_ctx摘要上下文指针ctx;

f.evp_md摘要算法结构体指针md;

g.临时签名数据存放字节数组;

sign_publice_key;

h.签名临时存储数组data,长度为2倍的最长sha512摘要的长度。

[3]使用evp_md_ctx_int初始化摘要上下文,输入为[1]中mctx;

[4]判断状态机的状态是否为ssl3_st握手,cw_cert_vrfyclientwrite客户端写状态,刚进入状态certverify证书校验,是否为ssl3_st_cw_cert_vrfy_a状态;

[5]调用ssl_handshake_start,输入为ssl上下文s,输出为指针p;

[6]ekey签名算法判断,如果是rsa智能密码钥匙ekey,进入[7]处理,如果是国产商用密码算法ekey,进入[16]处理;

[7]ssl上下文s的key中私钥指针privatekey指向[1]中定义的pkey;

[8]调用evp_pkey_ctx_new使用pkey初始化[1]中evp_pkey_ctx上下文pctx;

[9]判断是否摘要算法是否为sm3,采用ssl_get_algorithm2,输入为ssl上下文s,若为ssl_handshake_mac_sm3,摘要算法结构采用sm3;

[10]否则摘要算法结构采用sha1;

[11]调用evp_pkey_sign_init,输入为pctx,进行签名初始化;

[12]根据[9]、[10]中摘要算法结构的类型,使用evp_pkey_ctx_set_signature_md设置pctx的摘要算法结构为sm3或者sha1;

[13]如果采用tls1.2发送签名算法和结构,进行特殊处理:

a.调用tls12_get_sigandhash,输入为[4]中p,[5]中pkey,ssl上下文s中配置的key中的摘要信息evp_md结构md;

b.计算摘要,使用evp_sign系列函数(evp_signinit_ex、evp_signupdate、evp_signfinal),输入为[1]中定义的mctx,a中的md,[5]中的pkey;

c.计算握手消息头n。

[14]如果不采用tls1.2发送签名算法和结构。需要根据pkey的类型type进行判断;

[15]当pkey的类型为evp_pkey_rsa时,

a.如果[9]中摘要算法结构为sha1,进行mac校验,利用pkey中rsa结构调用rsa_sign进行签名,并计算握手消息头n;

b.如果[9]中摘要算法结构为sm3,进行特殊处理,利用pkey中rsa结构调用rsa_sign进行签名,但指向签名临时存储数组data[16]开始的地址。

[16]当pkey的类型为evp_pkey_dsa时,利用pkey中的dsa结构调用dsa_sign进行签名,并计算握手消息头n;

[17]当pkey的类型为evp_pkey_ec时,

a.若椭圆曲线的nid如果是sm2,使用evp_pkey_size,输入pkey,输出到j;

b.摘要算法结构采用sm3,指向临时evp_md结构sm3_md;

c.进行evp_digest系列处理,利用evp_digestinit,输入为上述mctx、sm3_md、pkey;

d.利用evp_digestupdate,将&(data[md5_digest_length])中sm3_md摘要结构md_size字节数据进行信息摘要到mctx结构中去;

e.利用evp_digestsignfinal将mctx结构中的摘要信息数据返回到p[2]的地址中,摘要数据的长度(字节)写入到参数j中;

f.采用s2n,输入上述j、p,存成双字节值;

g.设置握手头长度n为j+2;

h.若椭圆曲线的nid如果不是sm2,利用pkey中的ec结构调用ecdsa_sign进行签名,并计算握手消息头n。

[18]判断如果不是在签名前使用签名算法扩展,在实际的ssl记录层协议执行过程中,使用cert_verify_mac->ssl3_handshake_mac对通信数据进行mac校验;

[19]将[2].b中定义的ecc加密密钥对的公钥结构eccpublickeyblob所在的内存清零,进行初始化;

[20]使用skf接口skf_exportpublickey从接入系统的智能密码钥匙ekey中导出签名公钥,输出ecc公钥结构,指向[17]中eccpublickeyblob;

[21]ecc公钥结构处理:格式化eccpublickeyblob中的x坐标值写入sign_publice_key;

[22]ecc公钥结构处理:格式化eccpublickeyblob中的y坐标值写入sign_publice_key;

[23]计算sm2公钥,使用x坐标和y坐标构成的sign_publice_key计算sm2公钥,转化为ec_key结构,指向[2].a中定义的sm2key;

[24]计算z值,输入[21]中sm2key,输出放入[2].d中定义的要处理的摘要值digest;

[25]其中z值的计算按照国产商用密码标准《gm/t003.2-2012sm2椭圆曲线公钥密码算法第二部分:数字签名算法》中规定,

za=sm3(entla||ida||a||b||xg||yg||xa||ya),entl为两个字节表示的id的比特长度,id为用户表示,id的长度16字节,a、b为椭圆曲线参数,xg、yg为椭圆曲线的基点,x坐标和y坐标从ekey中读出到eccpublickeyblob签名公钥结构中,由[21]中指定;

[26]设置evp摘要算法结构为sm3,摘要算法结构采用sm3,指向[2].f中的evp_md指针md;

[27]创建evp_md_ctx上下文evp_md_ctx_creat,指向[2].e中的evp_md_ctx指针ctx;

[28]evp_digest系列函数处理:利用evp_digestinit,输入为上述ctx和md;

[29]在杂凑算法计算过程中,根据输入数据的长度,两次调用压缩函数分段计算输入数据的杂凑值,

a.利用evp_digestupdate,将digest中的32字节数据进行信息摘要到ctx结构中去,对给定长度数据块的杂凑值计算,根据消息的实际长度,再迭代执行一次;

b.将(data[md5_digest_length])地址中的32字节数据进行信息摘要到ctx结构中去。

[30]利用evp_digestfinal结束计算并输出指定长度的杂凑值,将ctx结构中的摘要信息数据返回到参数digest中,摘要数据的长度(字节)写入到参数dgst_len中;

[31]sm3(z||digest),利用[5].1中获取的skf接口函数操作指针hskfmethodhandle和容器指针hcontainer调用skf_exportpublickey,采用ecc算法和硬件智能密码钥匙的私钥,对待签名的指定数据digest进行数字签名。签名后的结果存放到[2].c中ecc签名数据结构(r,s)eccsignatureblob;

[32]bn_new()创建一个大数结构bn;

[33]对签名结果的r部分处理,利用bn_bin2bn函数,赋二进制值signature.r+32到大数结构bn;

[34]利用bn_num_bits获取bn的位数;

[35]判断bn的位数和0x7按位与是否为1,以此判断是否r部分要做padding;

[36]对签名结果的s部分处理,利用bn_bin2bn函数,赋二进制值signature.s+32到大数结构bn;

[37]利用bn_num_bits获取bn的位数;

[38]判断bn的位数和0x7按位与是否为1,以此判断是否s部分要做padding;

[39]偏移值t初始化为0;

[40]如果r部分的大数不够7位,要进行处理:将已开辟内存空间p+2+偏移值t的长度为1的值清零;

[41]将签名的r部分内存拷贝至p+2+t,偏移值位移32位;

[42]如果s部分的大数不够7位,要进行处理:将已开辟内存空间p+2+偏移值t的长度为1的值清零;

[43]将签名的s部分内存拷贝至p+2+t,偏移值位移32位;

[44]p为[5]中,调用ssl_handshake_start,输入为ssl上下文s,输出的指针p;

[45]采用s2n,输入上述t、p,存成双字节值;

[46]设置握手头长度n为偏移值+2;

[47]设置ssl上下文s的状态为ssl3_st_cw_cert_vrfy_b。

s8.对pkcs#11和skf接口的使用、智能密码钥匙ekey的读取再进行一层封装,参考图8进一步封装结构图。

[1]将应用系统中接入的一个智能密码钥匙ekey,或者一个厂商支持的某型号驱动的多张ekey,抽象为一个ekey对象;

[2]将指向抽象ekeyd的智能指针集合封装为ekeys;

[3]封装一个initapi接口,读入ekey驱动文件(dll/so),将驱动中实现的硬件令牌接口函数(pkcs#11或skf),映射为methodlisthandle以便进一步调用操作;

[4]封装一个enumerateallekeys接口,枚举ekey,返回[1]中多个ekey对象;

[5]login接口封装需要访问ekey对象中的证书的相关函数,如校验pin码verifypin;

[6]将ekey对象中的证书智能指针集合封装为certificates;

[7]将转化为evp_pkey后的密钥对象的智能指针集合封装为keys;

[8]获取访问ekey对象中的证书权限后,封装获取证书certificates的操作为统一的接口getcerficates;

[9]封装获取私钥的对应evp_pkey结构的操作为统一的接口getprivatekey。

s9.基于s7的变更,通过s8的进一步封装,可实现判断ekey中证书的签名算法,自动加载相应驱动库和接口函数,从而能自适应选择相应的处理分支,使用rsa算法进行签名或者使用国产商用密码算法进行签名,参考图9整体实现活动图。

[1]在用户客户端,一个场景是登录服务器时,检验ekey。客户端程序检验ekey时,可以藉此判断ekey中证书的签名算法;

[2]以windows.netfreamwork实现框架为例,通过x509store接口找出相应的接入的智能密码钥匙在注册表中的存储区。通过遍历存储区内的证书,映射至x509证书x509certificate2接口对象;

[3]获取x509certificate2接口对象中用于创建证书签名的算法signaturealgorithm;

[4]按照国产商用密码算法标准中《gmt0006-2012密码应用标识规范》定义的oid,匹配signaturealgorithm进行判断;

[5]例如,签名算法signaturealgorithm值为"1.2.156.10197.1.501",即为sm3withsm2,国产商用密码算法ekey;

[6]例如,签名算法signaturealgorithm值为"1.2.840.113549.1.1.5",即为sha1withrsaencryption,rsa算法ekey;

[7]封装的ekey中间件,实现上述封装pkcs#11和skf接口数据结构和相关接口;

[8]通过enumerateallekeys将接入系统的智能密码钥匙映射为ekey抽象接口;

[9]在运行时判断使用何种接口(pkcs#11、skf);

[10]获取相应接口操作函数的methodlist指针;

[11]pkcs11#接口:通过enumerateekeys,使用getcertificates接口映射证书操作对象,使用getprivatekey,getevppkey接口,将私钥转化为evp_pkey对象,定制rsa结构,将其签名函数指向重定义的sign函数;

[12]sign函数中通过methodlist操作指针调用c_signinit,c_sign接口,使用硬件智能密码钥匙进行签名,此操作对应s7变更后ssl3_send_client_verify中的处理,主要是rsa_sign的处理;

[13]skf接口:通过enumerateekeys,枚举device、application、container,从container中枚举证书对象certificates,并保存hdevice、happlication、hcontainer操作指针;

利用methodlist操作指针,调用相应的skf接口,主要是skf_exportpublickey接口从智能密码钥匙ekey中导出签名公钥结构,使用skf_eccsigndata接口进行智能密码钥匙签名,实现sm3(z||digest)的运算,参与到s7变更后ssl3_send_client_verify中的处理中。

本发明的有益效果如下:

(1)智能密码钥匙的系列操作被抽象实现为一个接口层,ekey接口层封装了适配ekey的驱动及驱动支持的操作函数。应用层无需关心接入的智能密码钥匙ekey是何种型号而可以直接进行使用。

(2)对原有openssl函数进行变更扩展,实现了一种使用国产商用密码算法智能密码钥匙ekey的签名方法。

(3)对原有openssl函数的变更扩展,不影响原openssl的功能,使得可以达到兼容国产商用密码算法智能密码钥匙ekey签名、国产商用密码算法文件证书签名,rsa算法智能密码钥匙ekey签名、rsa算法文件证书签名的效果。

(4)结合(1)中的抽象接口方法,达到接入rsa和国产商用密码算法智能密码钥匙时自适应选择接口和处理分支进行rsa和国产商用密码算法签名。

(5)应用以上方法的程序,安全可靠;架构和算法上可平行扩展,可以支持纳入任意多种rsaekey和国产商用密码ekey,兼容性强。

本发明所述的兼容rsa及国产商用密码算法的智能密匙签名方法,它采用将智能密码钥匙的一系列操作抽象实现为一个ekey接口层,实现可水平拓展的框架,包含枚举证书、签名等统一操作接口;对于rsa智能密码钥匙ekey,采用将证书私钥映射的方法,签名时指向自身定义的sign函数;对于国产商用密码算法智能密码钥匙ekey,采用扩展openssl中客户端发送验证的相关函数,调用国产商用密码标准规定的接口完成签名;它具有能够根据智能密码钥匙中证书的签名算法,采用rsa和国产商用密码算法,实现签名。

以上所述仅是本发明的较佳实施方式,故凡依本发明专利申请范围所述特征及原理所做的等效变化或修饰,均包括于本发明专利申请范围内。

当前第1页1 2 
网友询问留言 已有1条留言
  • 177226... 来自[中国] 2021年09月28日 10:13
    有点料,值得肯定的技术!
    0
1