基于国密SM3算法(openssl接口)密钥派生函数KDF的实现

前言

最近项目需要使用KDF生成秘钥,对比国密标准(GB_T 32918.4-2016)及网络资料,发现确实没有让我满意的, 自己结合标准和大佬:Heidlyn的帖子《国密SM2算法密钥派生函数KDF的实现》动手写了一个并成功通过标准下面的测试用例,个人认为更加通俗易懂。现分享给大家
在这里插入图片描述

代码

//KDF函数的实现基于GB_T32918_4-2016 5.3.4章《密钥派生函数》实现
//函数功能:KDF秘钥派生函数
//输入参数: Z     -用于计算的比特串
//			Zlen   -Z的字节数
//          klen   -需要获得秘钥数据的字节长度
//输出参数: K      -长度为klen的秘钥数据比特串K(这里设置为128位)
void my_KDF(const unsigned char* Z, const unsigned int Zlen, const unsigned int Klen, unsigned char* K)
{
	unsigned int ct = 1;					//计数器
	unsigned char cCt[4] = { 0 };           //计数器的内存表示值

	unsigned char *pData = new unsigned char[Zlen + 4];
	unsigned char cdgst[32] = { 0 };        //摘要
	int nDgst = 32;						    //摘要长度 单位:字节
	unsigned int hash_len;					//sm3输出串长度  
	int index = (Klen + 32) / 32;			//需要计算的次数,这里+32表示至少要进行一次循环

	if (Z == NULL || Klen <= 0 || Zlen < 0 || K == NULL)
	{
		return -1;
	}
	//初始化空间
	memset(pData, 0, Zlen + 4);
	//复制比特串Z
	memcpy(pData, Z, Zlen);

	for (size_t i = 0; i < index ; i++)
	{
		//内存表示计数器
		{
			cCt[0] = (ct >> 24) & 0xFF;
			cCt[1] = (ct >> 16) & 0xFF;
			cCt[2] = (ct >> 8) & 0xFF;
			cCt[3] = (ct) & 0xFF;
		}
		//拼接比特串
		memcpy(pData + Zlen, cCt, 4);
		//sm3函数处理,这里使用openssl内的EVP_SM3接口处理
		SM3_HASH(pData, Zlen + 4, cdgst, &hash_len);
		//最后一次计算,根据klen/32是否整除,若未整除,则截取最后一次hash的值
		if (i == index - 1)
		{
			if (Klen % 32 != 0)
			{
				nDgst = (Klen) % 32;
			}
		}
		memcpy(K + 32 * i, cdgst, nDgst);
		ct++;
	}
	return ;
}

测试部分

测试用例截取(GB_T 32918.4-2016)标准中的部分涉及到KDF的计算,下面是截图
在这里插入图片描述
图里的用例是将坐标x2和y2拼接后进行KDF运算,其中生成消息比特长度为152
我将截图里的测试用例文字显示出,方便各位测试:

坐标x2: 64D20D27D0632957F8028C1E024F6B02EDF23102A566C932AE8BD613A8E865FE
坐标y2: 58D225ECA784AE300A81A2D48281A828E1CEDF11C4219099840265375077BF78
应 得: 006E30DAE231B071DFAD8AA379E90264491603

测试结果:
在这里插入图片描述
上述代码中使用到的SM3函数为openssl中的EVP_SM3接口,我自己做了简单封装,可以直接调用EVP_SM3使用。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值