SM2算法的加密签名消息语法规范(四)如何构造envelopedData

前面的文章中已经介绍了国密规范中的数字信封数据envelopedData类型。接下来讲一下怎么构造出这种类型的数据~~\( ̄︶ ̄)/ 

1、构造流程

根据RFC规范,在结合GM/T 0010规范的要求,构造数字信封数据的过程如下:    
    a. 产生一个对应于特定加密算法的内容加密密钥(即会话密钥或对称密钥);
    b. 将内容加密密钥用每个接收者的公钥加密。(算法为:sm2-3 公钥加密算法   OID:1.2.156.10197.1.301.3)
    c. 对于每一个接收者,把加了密的内容加密密钥和接收者的其他信息放入RecipientInfo值中。
    d. 用内容加密密钥加密内容。
    e. 将所有接收者的RecipientInfo值和加了密的内容放入EnvelopedData值中。      

2、编码实现

国密规范中定义的数字信封结构相较于RFC规范中,新增了2个字段用于存放协商好的共享信息。但是是可选的,小编这里并不需要这俩字段。因此可直接使用gmssl中定义的PKCS7_ENVELOPE结构。

然后通过ASN.1库自定义oid类型为envelopedData(1.2.156.10197.6.1.4.2.3)的类型来实现DER编码。自定义ASN结构方案请查看小编之前的文章。这里就不在赘述了。

/*******************************************************

(=゚ω゚)ノ ---===≡≡≡一顿操作猛如虎......

OK 小编已自定义好了针对数字信封数据的结构(SM2EnvelopedData);

然后根据构造流程中,调用相关算法计算得到了会话密钥密文(经接收者公钥加密)、被会话密钥加密后的内容密文;并将密文结构数据均进行了DER编码。

*******************************************************/

构造部分主要代码如下:

封装pkcs7数字信封///
	if ((p7 = SM2EnvelopedData_new()) == NULL)
	{
		//TODO. 错误处理
		goto end;
	}
	//------------设置类型为NID_pkcs7_enveloped
	if (!SM2_EnvelopedData_set_type(p7, OID_SM2_Enveloped)) {
		//TODO. 错误处理
		goto end;
	}

	//------------构造recipientinfo
	PKCS7_RECIP_INFO *ri = NULL;
	if ((ri = PKCS7_RECIP_INFO_new()) == NULL)
	{
		//TODO. 错误处理
		goto end;
	}
	//设置版本信息
	if (!ASN1_INTEGER_set(ri->version, 0))
	{
		//TODO. 错误处理
		goto end;
	}
	//填充issuer_and_serial 颁发者信息
	if (!X509_NAME_set(&ri->issuer_and_serial->issuer, X509_get_issuer_name(enc_cert)))
	{
		//TODO. 错误处理
		goto end;
	}
	ASN1_INTEGER_free(ri->issuer_and_serial->serial);
	if (!(ri->issuer_and_serial->serial = ASN1_INTEGER_dup(X509_get_serialNumber(enc_cert))))
	{
		//TODO. 错误处理
		goto end;
	}
	//设置接收者证书
	ri->cert = enc_cert;  //注。ri->cert已指向了enc_cert, enc_cert内存将由p7对象释放
	//指定算法和相应的参数  //digestAlgorithms  用接收者公钥加密数据加密密钥的算法
	ri->key_enc_algor->algorithm = OBJ_txt2obj(OID_SM2_3, 1);
	ri->key_enc_algor->parameter = ASN1_TYPE_new();
	ri->key_enc_algor->parameter->type = V_ASN1_NULL;
	//3. 把加了密的内容加密密钥和接收者的其他信息放入RecipientInfo值中。
	/*ASN1_STRING_set0内部是直接进行指针指向,故而ek内存将由ASN1对象去释放。将ek指向NULL,防止重复释放*/
	ASN1_STRING_set0(ri->enc_key, ek, ekLen);
	ek = NULL;

	//------------将接收者加入到PKCS7_ENVELOPE的接收者信息集合
	if (!SM2_EnvelopedData_add_recipient_info(p7, ri))
	{
		//TODO. 错误处理
		goto end;
	}

	//------------构造enc_data
	if (0 == SM2_EnvelopedData_dataInit(p7, uiSymmAlgorithm, iv, 16))
	{
		//TODO. 错误处理
		goto end;
	}
	if (0 == SM2_EnvelopedData_dataFinal(p7, cont, contLen))
	{
		//TODO. 错误处理
		goto end;
	}

	//------------PKCS7对象Der编码输出
    //pucDerEnvelopedData为缓冲区,用来存放DER编码后的数据;
	pTmp = NULL;
	pTmp = pucDerEnvelopedData;
	if ((derP7Len = i2d_SM2EnvelopedData(p7, &pTmp)) <= 0)
	{
		//TODO. 错误处理
		goto end;
	}	

SM2_EnvelopedData_set_type该方法是根据SM2EnvelopedData结构设计的方法,用于根据OID设置其type。 内部会创建PKCS7_ENVELOPE数字信封结构对象,并设置PKCS7_ENVELOPE对象的版本号。(大家可以根据自己自定义的结构去进行设置

    ASN1_OBJECT *obj;

	obj = OBJ_txt2obj(oid, 1);

	if (0 == strcmp(oid, OID_SM2_Enveloped))
	{
		p7->type = obj;
		if ((p7->enveloped = PKCS7_ENVELOPE_new()) == NULL)
			goto err;
		if (!ASN1_INTEGER_set(p7->enveloped->version, 0))
			goto err;
		p7->enveloped->enc_data->content_type = OBJ_txt2obj(OID_SM2_Data, 1);
	}

SM2_EnvelopedData_dataInit方法是根据SM2EnvelopedData结构设计的方法,用于初始化结构中存储加密内容的算法及参数等

int SM2_EnvelopedData_dataInit(SM2EnvelopedData *p7, int symmAlg, unsigned char *iv, unsigned int ivlen)
{
	char objtmp[80] = { 0x00 };
	X509_ALGOR *xalg = NULL;

	OBJ_obj2txt(objtmp, sizeof(objtmp), p7->type, 1);
	if (0 == strcmp(objtmp, OID_SM2_Enveloped))
	{
		xalg = p7->enveloped->enc_data->algorithm;
	}
	else
	{
		LError("SM2_EnvelopedData_dataInit, PKCS7_R_WRONG_CONTENT_TYPE");
		return (0);
	}

	//指定内容加密算法
	int nid_alg = NID_undef;
	switch (symmAlg)
	{
	case SGD_SM4_ECB:
		nid_alg = NID_sms4_ecb;
		break;
	case SGD_SM4_CBC:
		nid_alg = NID_sms4_cbc;
		break;
	case SGD_SM4_CFB:
		nid_alg = NID_sms4_cfb128;
		break;
	case SGD_SM4_OFB:
		nid_alg = NID_sms4_ofb128;
		break;
	default:
		LError("Symm Algorithm undef.");
		nid_alg = NID_undef;
		return 0;
	}
	xalg->algorithm = OBJ_nid2obj(nid_alg);

	if (xalg->parameter == NULL)
		xalg->parameter = ASN1_TYPE_new();
	if (xalg->parameter == NULL)
		return 0;

	if (nid_alg == NID_sms4_ecb)
	{
		ASN1_TYPE_free(xalg->parameter);
		xalg->parameter = NULL;
	}
	else
	{
		//SM4算法非ECB模式,需要将IV向量值存放到enc_data中
		//存放到V_ASN1_OCTET_STRING类型中
		ASN1_TYPE_set_octetstring(xalg->parameter, iv, ivlen);
	}
	return 1;
}

SM2_EnvelopedData_dataFinal方法是根据SM2EnvelopedData结构设计的方法,填入加密后的内容。

int SM2_EnvelopedData_dataFinal(SM2EnvelopedData *p7, unsigned char *cont, unsigned int contlen)
{
	char objtmp[80] = { 0x00 };
	ASN1_OCTET_STRING *os = NULL;

	OBJ_obj2txt(objtmp, sizeof(objtmp), p7->type, 1);
	if (0 == strcmp(objtmp, OID_SM2_Enveloped))
	{
		os = p7->enveloped->enc_data->enc_data;
		if (os == NULL) {
			os = ASN1_OCTET_STRING_new();
			if (os == NULL) {
				LError("SM2_EnvelopedData_dataFinal, ERR_R_MALLOC_FAILURE");
				return 0;
			}
			p7->enveloped->enc_data->enc_data = os;
		}
	}
	else
	{
		LError("SM2_EnvelopedData_dataFinal, PKCS7_R_WRONG_CONTENT_TYPE");
		return (0);
	}

	if (os == NULL)
		return 0;
	ASN1_OCTET_STRING_set(os, cont, contlen);

	return 1;
}

以上仅贴出了一些主要代码,供大家参考的同时也记录下方便自己记忆。

最后DER编码输出的envelopedData数据用Asn1View打开查看,如下:

 

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
GMT 0009-2012 SM2 密码算法使用规范,详细描述SM2算法使用规范 GM/T0010-2012 目次 前言 1范围…… 2规范性引用文件…………… 3术语和定义 ·· 4符号和缩略语… 5OID定义… 6基入类型定义…………………… 6.1 Certilicate revocationlists 6.2 Content Encryption AlgorithmIdentifier………………………………………… 6.3 Digest algorithmldentifie 6.4 Digest Encryption algorithmIdentifier…………………… 6.5 Extended certificate OrCertificate 6,6 Extended certificatesAnd certificates……………………… 6,7 Issuer AndserialNumber……………… 6.8 KeyEncryptionAlgorithmldentilier 6,9 Version………………………………………………………………………………… 6.10 Contentinfo 7数据类型data 8签名数据类型 signedData…………… 8.1 signedData类型 8.2 SignerInfo类型…… 9数字信封数据类型 envelopeddata… 9.1 envelopedData类型 9,2 RecipientInfo类型……… 10签名数字信封数据类型 signed And EnvelopedData……… 11加密数据类型 encryptedData 12密钥协商类型 key AgreementInfo 附录A(规范性附录)SM2密钥格式 A.1椭圆曲线参数语法… A.2公钥语法 A.3私钥语法 参考文献…………………………… GM/T0010-2012 前言 本标准按照GB/T1.12009的规则编写 请注意本文件的某些内容可能涉及专利。本文件的发布机构不承担识别这些专利的责任 本标准由国家密码管理局提出并归口 本标准中的附录A为规范性附录。 木标准起草单位:上海格尔软件股份有限公司、北京海泰方圆科技有限公司、北京数字认证股份有 限公司、无锡江南信息安全工程技术中心、成都卫士通信息产业股份有限公司、上海巾数字证书认证中 心有限公司、兴唐通信科技有限公司、上海颐东网络信息有限公司、山东得安信息技术有限公司、国家信 息安全工程技术研究中心。 本标准起草人:刘平、谭武征、柳増寿、李述胜、徐强、李元正、刘承、王妮娜、夏东山、蒋红宇、孔凡玉 袁峰。 本标准涉及的密码算法按照国家密码管理部门的要求使用 Ⅱ GM/T0010—2012 SM2密码算法加密签名消息语法规范 1范 本规范定义了使用SM2密码算法加密签名消息语法。 本规范适用于使用SM2密码算法进行加密签名操作时对操作结果的标准化封装。 2规范性引用文件 下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仪注日期的版本适用于本文 件,凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件。 GM/T0006密码应用标识规范 GM/ T AAAA SV2密码算法使用规范 PKCS #5 Extended-Certificate Syntax 3术语和定义 下列术语适用于本规范算法标识 algorithm identifier 用于标明算法机制的数字化信息 SM2算法SM2 algorithM 一种椭圆曲线密杩算法,密钥长度为256比特。 4符号和缩略语 下列缩略语适用于本规范 ECC 椭圆曲线密码算法( Elliptic Curve cryptography) 用户标识( Identity) OID 对象标识符( Object Identity) 5OID定义 本规范对6个对象data, signeddata, envelopedData, signedAnd Data, encryptedData和 key AgreementInfo的标识符进行了定义,详见表1 GM/T0010-2012 表1对象标识符 对象标识符OID 对象标识符定义 1.2,156.10197.6.1.4.2 SM2密码算法加密签名消息语法规范 1.2.156.10197.6.1.4.2.1 数据类型data 1.2.156.10197.6.1.4.2.2 签名数据类型 signedData 1.2,156,10197.6.1.4.2,3 数字信封数据类型 enveloped Data 签名数字信封数据类型 1.2.156.1C197.6.1.4.2.4 signedAndEnvelopedData 1.2,156,10197.6.1.4.2.5 加密数据类型 encryptedData 1.2,156,10197.6.1.4.2,6 密钥协商类型 key AgreementInfo 6基本类型定义 6.1 Certificate Revocation lists Certificaterevocationlists类型标明一个证书撤销列表的集合。 Certificatereyocationlists;:= SET OF Certificaterevocation list 6. 2 ContentEncryptionAlgorithmldentificr Content Encryptionalgorithmldentifier类型标明一个数据加密算法。其OI见GM/T0006 Content Encryption AlgorithmIdentifier :: AlgorithmIdentifier 6.3 DigestAlgorithm ldentifier DigestAlgorithmIdentifier类型标明一个消息摘要算法,夲规范为SM3算法,其OID见GM/ T0006。 DigestAlgorithmIdentifier : AlgorithmIdentifier 6. 4 DigestEncryptionAlgorithmIdentifier Digest Encryption algorithmIdentifier类型标明一个签名算法,本规范SM2密码算法,其OI见 GM/T OOO Digest EncryptionAlgorithmIdentifier AlgorithmIdentifier 6.5 ExtendedcertificateorCertificate ExtendedcertificateOrCertificate类型指定一个PKCS#6扩展证书或者一个X.509证书。这一类 型见PKCS=6第6节推荐的语法 ExtendedCertificate OrCertificate ::=CHOICE I certificate Certificate.--.509 extendedCertificate [o IMPLICIT Extended Certificate GM/T0010—2012 6.6 ExtendedCertificates And Certificates ExtendedcertificatesAndcertificates类型指定一个扩展证书和X.509证书的集合。它表示集合足 以包含从可识别的“根”或“顶级CA”到所有签名者的证书链。 ExtendedcertificatesandCertificates : SET OF Extendedcertificate orcertificate 6. Issuer AndSeriaINumber Issuer And SerialNumber类型标明一个证书颁发者可识别名和颁发者确定的证书序列号,可据此 确定一份证书和与此证书对应的实体及公钥。 IssuerAndSerialNumber SEQUENCE issuer name serialNumber certificate SerialNumber 6.8 Kcy EncryptionAlgorithmldentificr KeyEncryptionAlgorithmIdentifier类型标明加密对称密钥的加密算法。 Key encryptionalgorith mldentilier :: Algorithmlden 6.9ⅴ ersion Version类型标明语法版本号。 Version :: INTEGER(1 6. 10 ContentInfo ContentInfo类型标眀内容交换通用语法结构,内容交换的通用语法结构定义如下」 ContentInfo :: SEQUENCE contentType Content type contentO] EXPLICIT ANY DEFINED BY content Type OPTIONAL ContentType OBJECT IDEN TⅠFIER 其中 ContentType内容类型是一个对象标识符,其定义见本规范第5章。 content内容,可选。 7数据类型data data数据类型结构定义如下: Data .. OCTET STRING Data数据类型表示任意的字节串,比如ASCI文本文件。 GM/T0010—2012 8签名数据类型 signed Data 8.1 signed Data类型 signeddata数据类型由任意类型的数据和至少一个签名者的签名值组成。任意类型的数据能够同 时被任意数量的签名签名。 signeddata数据类型结构定义如下 SignedData ::= SEQUENCE versionⅤ ersion, digest algorithms digest algorithmIc entities. contentInfo sm2signature certificates o IMPLICIT ExtendedCertificates And Certificates OPTIONAL crls[ 1] IMPLICIT Certificate Revocation Lists OPTIONAI Signerinlos Signerinlos Digestalgorithm Identifiers : SET OF Digest AlgorithmIdentifier SignerInfos::= SET OF SignerInfo 结构中各项含义见表2 表2 signedData数据类型 字段名称 数据类型 含义 version (1) V ersion 语法的版木号 digestAlgorithms DigestAlgorithmIdentifiers 消息摘要算法标识符的集合 contention SM2Signaturc 被名的数据内谷,数据类型见GM/ T AAAA ExtendedCertificatesAndcertif certifica PKCS#6扩展证书和X.509证书的集合 Icates CrIs Certificate Revocation lists 证书撤销列表的集合 signIngs SignerInfos 每个签名者信息的集合 8.2 Signerlnfo类型 gnerInfo类型结构定义如下: SignerInfo :: SEQUENCE version version issuer And SerialNumber IssuerAndSerial Number digest Algorithm DigestAlgorithmldentifier authenticated AttributesLO] IMPLICIT Attributes OPTIONAL digest Encryption Algorithm Digest EncryptionAlgorithmIdentifier
sm2算法是一种国家密码学标准算法,它主要用于椭圆曲线公钥密码体制中的加密数字签名sm2算法基于椭圆曲线离散对数问题,具有安全性和高效性的特点。 sm2算法的C语言实现主要包括以下几个步骤: 1. 选择椭圆曲线参数:sm2算法使用的是国家标准椭圆曲线参数,可以在标准文档中找到。选择合适的参数,初始化椭圆曲线。 2. 生成密钥对:使用随机数生成器生成一个私钥,并通过椭圆曲线上的点运算得到对应的公钥。 3. 加密过程:假设要加密的明文为M,首先将M转换成点P,再生成一个随机数k。通过点运算得到C1=kG,其中G为基点。然后计算点S=kP,将S的x坐标转换成字节数组,作为SM3算法的输入,得到哈希值H。最后计算C2=M⨁H,C3=k^-1·(hash(kP)+C2)。 4. 解密过程:给定密文C=(C1,C2,C3),首先计算C1的k倍点为kC1,并将kC1的x坐标作为SM3算法的输入,得到哈希值H。然后计算C2=M⨁H,并利用C1的k倍点计算kP。最后计算hash(kP)+C2,乘以C3的k^-1得到明文M。 5. 数字签名过程:给定要签名消息M和私钥d,首先计算消息的哈希值H。然后生成一个随机数k,并通过点运算得到点R=kG。将R的x坐标转换成字节数组,作为SM3算法的输入,得到哈希值h。计算s=(h+d·r)·⁻¹·k。最后签名为(R,s)。 以上是sm2算法的简要介绍和C语言实现的整体步骤,实现过程中需注意安全性和正确性。具体的C语言代码实现需要详细研究和阅读sm2算法的相关标准文档,理解椭圆曲线运算和密码哈希算法的具体细节,然后按照算法规范进行编码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值