SM2椭圆曲线公钥密码算法,完整c代码,前人栽树,后人乘凉

这篇博客介绍了如何实现SM2椭圆曲线公钥密码算法,提供了基于mircal库的C代码,包括四个文件:SM2.c, SM2.h, SM3.c, SM3.h。适合作为电信安信息安全数学基础实验的参考,读者可以在此基础上进行学习和开发。" 123162469,12410974,Java在线小说阅读系统(前后端分离+SpringBoot+Vue),"['Java', 'Spring框架', '前端开发', '数据库管理', 'Web开发']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某电信安信息安全数学基础实验要求实现SM2椭圆曲线公钥密码算法

这是基于mircal库实现的,没有mircal库的下载我以前的博客发的文件,根据教程在vs上搭建。

一共四个文件  SM2.c SM2.h SM3.c SM3.h

SM2.c

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include<string.h>
#include "sm2.h"

void Buf_Out(unsigned char *buf, int	buflen) //每32项为一行输出buf
{
	int i;
	printf("\n");
	for (i = 0; i < buflen; i++) {
		if (i % 32 != 31)
			printf("%02x", buf[i]);
		else
			printf("%02x\n", buf[i]);
	}
	printf("\n");
	return;
}
#define SEED_CONST 0x1BD8C95A
struct QXCS
{
	char *p;//椭圆曲线的参数
	char *a;
	char *b;
	char *n;  //G的阶
	char *x;   //g=(x,y)
	char *y;
};

struct QXCS pdf = {"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7","BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
};




//接收方B的私钥和公钥产生
void sm2_keygen(unsigned char *wx, int *wxlen, unsigned char *wy, int *wylen,unsigned char *privkey, int *privkeylen) 
{
	struct QXCS *cfig = &pdf;
	epoint *g,*pB;
	big a,b,p,n,x,y,key1;
	miracl *mip = mirsys(20,0);   //初始化大数系统
	mip->IOBASE = 16;   //输入为16进制数改为大数

       p = mirvar(0);
	a = mirvar(0);
       b = mirvar(0);
       n = mirvar(0);
       x = mirvar(0);
       y = mirvar(0);
       key1 = mirvar(0);

       cinstr(p,cfig->p);      //将大数字符串转换成大数,这里是16进制的字符串转换大数
	cinstr(a,cfig->a);
       cinstr(b,cfig->b);
	cinstr(n,cfig->n);
	cinstr(x,cfig->x);
       cinstr(y,cfig->y);

	ecurve_init(a,b,p,MR_PROJECTIVE);   //初始化椭圆曲线
       g = epoint_init();
	pB = epoint_init();
       epoint_set(x,y,0,g);    //g=(x,y)为基点G
	//产生私钥
       irand(time(NULL)+SEED_CONST);   //初始化种子
       bigrand(n,key1);    //生成随机数key1
       ecurve_mult(key1,g,pB);   //pB=key1*g
       epoint_get(pB,x,y);    //取pB上的点(x,y)x和y即为公钥
	
       *wxlen = big_to_bytes(0, x, (char *)wx, FALSE);    //公钥写入wx,长度wxlen
   	*wylen = big_to_bytes(0, y, (char *)wy, FALSE);
	*privkeylen = big_to_bytes(0, key1, (char *)privkey, FALSE);
	
	mirkill(key1);
	mirkill(p);
	mirkill(a);
	mirkill(b);
	mirkill(n);
	mirkill(x);
	mirkill(y);
	epoint_free(g);
	epoint_free(pB);
	mirexit();
}


int kdf(unsigned char *zl, unsigned char *zr, int klen, unsigned char *kbuf)  //zl,zr为(x2,y2)
{                                          

	unsigned char buf[70];
	unsigned char digest[32];
	unsigned int ct = 0x00000001;
	int i, m, n;
	unsigned char *p;

	memcpy(buf, zl, 32);                   //把x2,y2传入buf
	memcpy(buf+32, zr, 32);

	m = klen / 32;
	n = klen % 32;
	p = kbuf;

	for(i = 0; i < m; i++)       //buf 64-70
	{
		buf[64] = (ct >> 24) & 0xFF;   //ct前8位
		buf[65] = (ct >> 16) & 0xFF;    
		buf[66] = (ct >> 8) & 0xFF;
		buf[67] = ct & 0xFF;
		sm3(buf, 68, p);                       //sm3后结果放在p中
		p += 32;
		ct++;
	}

	if(n != 0)
	{
		buf[64] = (ct >> 24) & 0xFF;
		buf[65] = (ct >> 16) & 0xFF;
		buf[66] = (ct >> 8) & 0xFF;
		buf[67] = ct & 0xFF;
		sm3(buf, 68, digest);
	}

	memcpy(p, digest, n);

	for(i = 0; i < klen; i++)
	{
		if(kbuf[i] != 0)      //kbuf中有i+1个0
			break;
	}

	if(i < klen)
		return 1;   //kbuf(t)中的bit全是0, kdf判断通过,执行下一步C2=M异或t
	else
		return 0;   

}

int A_encrypt(char *msg,int msglen, char *wx,int wxlen, char *wy,int wylen, char *outmsg)//wx,wy公钥的x,y的坐标
{
       struct QXCS *cfig = &pdf;
       big x2, y2, x1, y1, k;
       big a,b,p,n,x,y;
	epoint *g, *w, *pb, *c1,*kpb;
	int ret = -1;
	int i;
	unsigned char zl[32], zr[32];
	unsigned char *tmp;
       miracl *mip;
	tmp = malloc(msglen+64);
	if(tmp == NULL)
		return -1;
	mip = mirsys(20, 0);
	mip->IOBASE = 16;          //读入16进制数
    
        p=mirvar(0);
        a=mirvar(0);
        b=mirvar(0);
        n=mirvar(0);
        x=mirvar(0);
        y=mirvar(0);
	 k=mirvar(0);
	 x2=mirvar(0); 
	 y2=mirvar(0); 
	 x1=mirvar(0); 
	 y1=mirvar(0); 

       cinstr(p,cfig->p);                    //大数字符串变为大数
	cinstr(a,cfig->a);
       cinstr(b,cfig->b);
	cinstr(n,cfig->n);
	cinstr(x,cfig->x);
       cinstr(y,cfig->y);                                   //g=(x,y)

	ecurve_init(a,b,p,MR_PROJECTIVE);     //椭圆曲线方程初始化  y2 =x3 + Ax + B mod p
	g=epoint_init();                                   //点坐标初始化
	pb=epoint_init(); 
	kpb = epoint_init();
	c1= epoint_init();
	w= epoint_init();
       epoint_set(x,y,0,g);                             //点坐标设置  g=(x,y),现在无值
	
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值