某电信安信息安全数学基础实验要求实现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),现在无值