sm2国密算法的纯c语言版本,使用于单片机平台(静态内存分配)

简介: sm2国密算法的纯c语言版本,使用于单片机平台(静态内存分配)

终于搞定了sm2算法在smt32单片机上的移植。源码可联系我索取。


之前的动态内存分配,在上面总是莫名其妙的崩。不知道堆和栈空间该改多大合适。且总共64K的内存,太受限了。


几次想放弃,最后还是坚持了一下,终于搞定啦!


看miracl库官方说明文档,是使用了内存吃紧的设备的。可以使用静态内存分配。但是文档上介绍的太简单了,一笔带过。


还得自己调试这摸索。


文档中描述:


受限环境


在版本5的中,有一个对在非常小和受限的环境中的MIRACL实现的新支持。使用config实用程序,它现在支持各种时空交换(time/space trade-offs),最主要的革新是在一个不支持堆的环境中生成和使用MIRACL。通常big变量的空间从堆中分配,但通过在配置头文件中指定MR_STATIC,可以生成一个总是尝试从静态内存或栈,而不是堆中分配内存的版本。


这带来的主要负面影响是big变量的最大尺寸必须在编译时确定(生成库的时候)。如往常一样,在这个过程中最好让config实用程序引导你创建一个合适的配置头文件mirdef.h。


对于C程序员,使用下列方式从栈中为big变量分配内存:


big x, y, z;
char mem[MR_BIG_RESERVE(3)];
memset(mem, 0, MR_BIG_RESERVE(3));


为三个big变量分配的空间都在栈上并且被清零,然后每个变量应如下初始化:


x = mirvar_mem(mem, 0);
y = mirvar_mem(mem, 1);
z = mirvar_mem(mem, 2);


从单个内存块中为多个big变量分配所有空间是有意义的,那样可以更快的初始化,而且可以对变量对齐进行完整的控制——编译器有时会出错。请注意big初始化函数mirvar在这种模式中不再有效,分配操作应像上面描述的那样实现。


最后,可以选择性地在函数末尾调用memset来在离开前清空内存块——出于保密原因,这可能很重要。请参考示例程序brent.c。


这种机制在实现一个使用椭圆曲线的非常小的程序时可能非常有用。椭圆曲线要求的big数字要比其它加密技术的小得多。从栈中为椭圆曲线的点分配内存:


epoint *x, *y, *z;
char mem[MR_ECP_RESERVE(3)];
memset(mem, 0, MR_ECP_RESERVE(3));


初始化这些点:


x = epoint_init_mem(mem, 0);
y = epoint_init_mem(mem, 1);
z = epoint_init_mem(mem, 2);


同样,在离开函数前清空相关内存是明智的。



总结几点注意事项吧,


#define MR_STATIC 20,


这个值,不能低于20,太大也不行


然后,注意把sm2中,使用动态内存分配的地方都替换掉。


原来的释放内存的,也不需要了。可以注释掉。


//  mirkill(y);
  //  epoint_free(g);
  //  epoint_free(w);

如:


p = mirvar(0);


换成:


char mem[MR_BIG_RESERVE(10)];
memset(mem, 0, MR_BIG_RESERVE(10));
 //p=mirvar(0);
 p = mirvar_mem(mem, 0);
 a=mirvar_mem(mem, 1);
//=============================
  //g=epoint_init();
 //w=epoint_init();


这两个,换成如下的写法:


char mem1[MR_ECP_RESERVE(2)]; 
 memset(mem1 ,0, MR_ECP_RESERVE(2));
 g = epoint_init_mem(mem1,0);
 w = epoint_init_mem(mem1,1);


调用rand(time(NULL))的地方,


在单片机环境下,调用time会出现莫名其妙的错误,反正是取随机数种子的嘛,干掉time()函数。


可用静态变量,每次加1来作为种子。


在单片机环境中,还有一点需要注意的是:


单片机的内存和栈空间都不大。尤其是栈空间,如果函数中定义的局部变量太多的话,会导致应用崩溃。


如果是多任务环境里,应用里得调大点儿单个任务的堆栈空间。


或者把一些函数里面使用的局部变量,定义为外部全局变量吧,大的变量数组不要在函数内部占用栈空间了,栈空间紧张。


或者声明为static也可以。


国密算法介绍:


随着金融安全上升到国家安全高度,近年来国家有关机关和监管机构站在国家安全和长远战略的高度提出了推动国密算法应用实施、加强行业安全可控的要求。摆脱对国外技术和产品的过度依赖,建设行业网络安全环境,增强我国行业信息系统的“安全可控”能力显得尤为必要和迫切。


密码算法是保障信息安全的核心技术,尤其是最关键的银行业核心领域长期以来都是沿用3DES、SHA-1、RSA等国际通用的密码算法体系及相关标准,为从根本上摆脱对国外密码技术和产品的过度依赖。2010年底,国家密码管理局公布了我国自主研制的“椭圆曲线公钥密码算法”(SM2算法)。为保障重要经济系统密码应用安全,国家密码管理局于2011年发布了《关于做好公钥密码算法升级工作的通知》,要求“自2011年3月1日期,在建和拟建公钥密码基础设施电子认证系统和密钥管理系统应使用SM2算法。自2011年7月1日起,投入运行并使用公钥密码的信息系统,应使用SM2算法。


国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,在金融领域目前主要使用公开的SM2、SM3、SM4三类算法,分别是非对称算法、哈希算法和对称算法。


SM2算法:SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。


SM3算法:SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。


SM4算法:SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。


SM2算法单片机平台下的实现:


#include <stdio.h>
#include <stdlib.h>
#include<string.h>
//#include <memory.h>
#include <time.h>
#include "sm2.h"
#include "tmsm2.h"
#define SM2_PAD_ZERO TRUE
//#define SM2_PAD_ZERO FALSE
#define SM2_DEBUG   0
/*
#define QBITS 256
#define PBITS 3072
#define MAX_ECC_KEY_LEN   256
#define MAX_ECC_KEY_SIZE  (MAX_ECC_KEY_LEN/8)
*/
struct FPECC{
char *p;
char *a;
char *b;
char *n;
char *x;
char *y;
};
void PrintBuf(unsigned char *buf, int buflen)
{
  int i;
  printf("\n");
  printf("len = %d\n", buflen);
  for(i=0; i<buflen; i++) {
    if (i % 32 != 31)
      printf("%02x", buf[i]);
      else
      printf("%02x\n", buf[i]);
  }
  printf("\n");
  return;
}
void Printch(unsigned char *buf, int  buflen)
{
  int i;
  for (i = 0; i < buflen; i++) {
    if (i % 32 != 31)
      printf("%c", buf[i]);
    else
      printf("%c\n", buf[i]);
  }
  printf("\n");
  //return 0;
}
#if SM2_DEBUG
void PrintBig(big data)
{
 int len=0;
 unsigned char buf[10240];
 len=big_to_bytes(0,data,(char *)buf,0);
 PrintBuf(buf,len);
}
unsigned char radom[]  = {0x6C,0xB2,0x8D,0x99,0x38,0x5C,0x17,0x5C,0x94,0xF9,0x4E,0x93,0x48,0x17,0x66,0x3F,0xC1,0x76,0xD9,0x25,0xDD,0x72,0xB7,0x27,0x26,0x0D,0xBA,0xAE,0x1F,0xB2,0xF9,0x6F};
unsigned char radom1[] = {0x4C,0x62,0xEE,0xFD,0x6E,0xCF,0xC2,0xB9,0x5B,0x92,0xFD,0x6C,0x3D,0x95,0x75,0x14,0x8A,0xFA,0x17,0x42,0x55,0x46,0xD4,0x90,0x18,0xE5,0x38,0x8D,0x49,0xDD,0x7B,0x4F};
unsigned char randkey[] = {0x83,0xA2,0xC9,0xC8,0xB9,0x6E,0x5A,0xF7,0x0B,0xD4,0x80,0xB4,0x72,0x40,0x9A,0x9A,0x32,0x72,0x57,0xF1,0xEB,0xB7,0x3F,0x5B,0x07,0x33,0x54,0xB2,0x48,0x66,0x85,0x63};
unsigned char randkeyb[]= {0x33,0xFE,0x21,0x94,0x03,0x42,0x16,0x1C,0x55,0x61,0x9C,0x4A,0x0C,0x06,0x02,0x93,0xD5,0x43,0xC8,0x0A,0xF1,0x97,0x48,0xCE,0x17,0x6D,0x83,0x47,0x7D,0xE7,0x1C,0x80};
struct FPECC Ecc256={
"8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",
"787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",
"63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",
"8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",
"421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",
"0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2",
};
unsigned char sm2_par_dig[128] = {
0x78,0x79,0x68,0xB4,0xFA,0x32,0xC3,0xFD,0x24,0x17,0x84,0x2E,0x73,0xBB,0xFE,0xFF,
0x2F,0x3C,0x84,0x8B,0x68,0x31,0xD7,0xE0,0xEC,0x65,0x22,0x8B,0x39,0x37,0xE4,0x98,
0x63,0xE4,0xC6,0xD3,0xB2,0x3B,0x0C,0x84,0x9C,0xF8,0x42,0x41,0x48,0x4B,0xFE,0x48,
0xF6,0x1D,0x59,0xA5,0xB1,0x6B,0xA0,0x6E,0x6E,0x12,0xD1,0xDA,0x27,0xC5,0x24,0x9A,
0x42,0x1D,0xEB,0xD6,0x1B,0x62,0xEA,0xB6,0x74,0x64,0x34,0xEB,0xC3,0xCC,0x31,0x5E,
0x32,0x22,0x0B,0x3B,0xAD,0xD5,0x0B,0xDC,0x4C,0x4E,0x6C,0x14,0x7F,0xED,0xD4,0x3D,
0x06,0x80,0x51,0x2B,0xCB,0xB4,0x2C,0x07,0xD4,0x73,0x49,0xD2,0x15,0x3B,0x70,0xC4,
0xE5,0xD7,0xFD,0xFC,0xBF,0xA3,0x6E,0xA1,0xA8,0x58,0x41,0xB9,0xE4,0x6E,0x09,0xA2,
};
#else
/*SM2*/
struct FPECC Ecc256={
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
};
unsigned char sm2_par_dig[128] = {
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,0x9E,0x4B,0xCF,0x65,0x09,0xA7,
0xF3,0x97,0x89,0xF5,0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,0x0E,0x93,
0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,0x04,0x46,0x6A,0x39,0xC9,0x94,
0x8F,0xE3,0x0B,0xBF,0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,0x74,0xC7,
0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,0xCE,0xE3,0x6B,0x69,0x21,0x53,
0xD0,0xA9,0x87,0x7C,0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,0xF0,0xA0,
};
unsigned char enkey[32] = {
0xB1,0x6B,0xA0,0xDA,0x27,0xC5,0x24,0x9A,0xF6,0x1D,0x6E,0x6E,0x12,0xD1,0x59,0xA5,
0xB6,0x74,0x64,0x34,0xEB,0xD6,0x1B,0x62,0xEA,0xEB,0xC3,0xCC,0x31,0x5E,0x42,0x1D,
};
#endif
#define SEED_CONST 0x1BD8C95A
int sm3_e(unsigned char *userid, int userid_len, unsigned char *xa, int xa_len, unsigned char *ya, int ya_len, unsigned char *msg, int msg_len, unsigned char *e)
{
/*
功能:根据用户ID及公钥,求用于签名或验签的消息HASH值
[输入] userid: 用户ID
[输入] userid_len: userid的字节数
[输入] xa: 公钥的X坐标
[输入] xa_len: xa的字节数
[输入] ya: 公钥的Y坐标
[输入] ya_len: ya的字节数
[输入] msg:要签名的消息
[输入] msg_len: msg的字节数
[输出] e:32字节,用于签名或验签
返回值:
    -1:内存不足
      0:成功
*/
  return 0;
}
void sm2_keygen(unsigned char *wx, int *wxlen, unsigned char *wy, int *wylen,unsigned char *privkey, int *privkeylen)
{
}
int kdf(unsigned char *zl, unsigned char *zr, int klen, unsigned char *kbuf)
{
}
int sm2_encrypt(unsigned char *msg,int msglen, unsigned char *wx,int wxlen, unsigned char *wy,int wylen, unsigned char *outmsg)
{
}
int sm2_decrypt(unsigned char *msg,int msglen, unsigned char *privkey, int privkeylen, unsigned char *outmsg)
{
}
int sm2_key_get_y(unsigned char *wx,int wxlen, unsigned char *wy,int wylen,int cb)
{
  /*
  功能:验证SM2签名
  [输入] wx:   公钥的X坐标
  [输入] wxlen: wx的字节数,不超过32字节
  [输入] wy:   公钥的Y坐标
  [输入] wylen: wy的字节数,不超过32字节
  返回值:
   -1:验证失败
    0:验证通过
  */
}
int sm2_verify_tm(unsigned char *hash,int hashlen,unsigned char  *cr,int rlen,unsigned char *cs,int slen, unsigned char *wx,int wxlen, unsigned char *wy,int wylen)
{
/*
功能:验证SM2签名
[输入] hash:    sm3_e()的结果
[输入] hashlen: hash的字节数,应为32
[输入] cr:  签名结果的第一部分
[输入] rlen:cr的字节数
[输入] cs:  签名结果的第二部分。
[输入] slen:cs的字节数
[输入] wx:   公钥的X坐标
[输入] wxlen: wx的字节数,不超过32字节
[输入] wy:   公钥的Y坐标
[输入] wylen: wy的字节数,不超过32字节
返回值:
     -1:验证失败
    0:验证通过
*/
}
/*
int main()
{
  printf("sm2 test....\n");
  unsigned char dB[] = { 0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0xFE,0x28,0x3F,0xBF,0x35,0x35,0x34,0xAA,0x7F,0x7C,0xB8,0x94,0x63,0xF2,0x08,0xDD,0xBC,0x29,0x20,0xBB,0x0D,0xA0 };
  unsigned char xB[] = { 0x43,0x5B,0x39,0xCC,0xA8,0xF3,0xB5,0x08,0xC1,0x48,0x8A,0xFC,0x67,0xBE,0x49,0x1A,0x0F,0x7B,0xA0,0x7E,0x58,0x1A,0x0E,0x48,0x49,0xA5,0xCF,0x70,0x62,0x8A,0x7E,0x0A };
  unsigned char yB[] = { 0x75,0xDD,0xBA,0x78,0xF1,0x5F,0xEE,0xCB,0x4C,0x78,0x95,0xE2,0xC1,0xCD,0xF5,0xFE,0x01,0xDE,0xBB,0x2C,0xDB,0xAD,0xF4,0x53,0x99,0xCC,0xF7,0x7B,0xBA,0x07,0x6A,0x42 };
  unsigned char tx[256];
  unsigned char etx[256];
  unsigned char mtx[256];
  FILE *fp=0;
  int wxlen, wylen, privkeylen,len;
  //fopen(&fp, "5.txt", "r");
  //len=fread_s(tx, 256,sizeof(unsigned char), 256, fp);
  fp = fopen("5.txt","r");
  len=fread(tx,1,256,fp);
  tx[len] = 0;
  sm2_keygen(xB, &wxlen, yB, &wylen, dB, &privkeylen);
  printf("dB: ");
  PrintBuf(dB, 32);
  printf("xB: ");
  PrintBuf(xB, 32);
  printf("yB: ");
  PrintBuf(yB, 32);
  sm2_encrypt(tx,len,xB,32,yB,32,etx);
  printf("\n``````````````````this is encrypt```````````````````\n");
  PrintBuf(etx, 64 +len + 32);
  printf("\n``````````````````this is decrypt```````````````````\n");
  sm2_decrypt(etx,64+len+32,dB,32,mtx);
  if(sm2_decrypt(etx,64+len+32,dB,32,mtx) < 0)
    printf("sm2_decrypt error!\n");
  else
  {
    PrintBuf(mtx, len);
    Printch(mtx, len);
  }
  printf("\n``````````````````this is end```````````````````````\n");
  return 0;
}
*/
int sm2_test()
{
  printf("sm2 test....\n");
  unsigned char dB[] = { 0x16,0x49,0xAB,0x77,0xA0,0x06,0x37,0xBD,0x5E,0x2E,0xFE,0x28,0x3F,0xBF,0x35,0x35,0x34,0xAA,0x7F,0x7C,0xB8,0x94,0x63,0xF2,0x08,0xDD,0xBC,0x29,0x20,0xBB,0x0D,0xA0 };
  unsigned char xB[] = { 0x43,0x5B,0x39,0xCC,0xA8,0xF3,0xB5,0x08,0xC1,0x48,0x8A,0xFC,0x67,0xBE,0x49,0x1A,0x0F,0x7B,0xA0,0x7E,0x58,0x1A,0x0E,0x48,0x49,0xA5,0xCF,0x70,0x62,0x8A,0x7E,0x0A };
  unsigned char yB[] = { 0x75,0xDD,0xBA,0x78,0xF1,0x5F,0xEE,0xCB,0x4C,0x78,0x95,0xE2,0xC1,0xCD,0xF5,0xFE,0x01,0xDE,0xBB,0x2C,0xDB,0xAD,0xF4,0x53,0x99,0xCC,0xF7,0x7B,0xBA,0x07,0x6A,0x42 };
  unsigned char tx[257];
  unsigned char etx[256];
  unsigned char mtx[256];
  //FILE *fp=0;
  int wxlen, wylen, privkeylen,len;
  //fopen(&fp, "5.txt", "r");
  //len=fread_s(tx, 256,sizeof(unsigned char), 256, fp);
  //fp = fopen("5.txt","r");
  //len=fread(tx,1,256,fp);
    tx[0] = 0x31;
    tx[1] = 0x31;
    tx[2] = 0x31;
    tx[3] = 0x31;
    len = 256;
  tx[len] = 0;
  sm2_keygen(xB, &wxlen, yB, &wylen, dB, &privkeylen);
  printf("dB: ");
  PrintBuf(dB, 32);
  printf("xB: ");
  PrintBuf(xB, 32);
  printf("yB: ");
  PrintBuf(yB, 32);
  sm2_encrypt(tx,len,xB,32,yB,32,etx);
  printf("\n``````````````````this is encrypt```````````````````\n");
  PrintBuf(etx, 64 +len + 32);
  printf("\n``````````````````this is decrypt```````````````````\n");
  sm2_decrypt(etx,64+len+32,dB,32,mtx);
  if(sm2_decrypt(etx,64+len+32,dB,32,mtx) < 0)
    printf("sm2_decrypt error!\n");
  else
  {
    PrintBuf(mtx, len);
    Printch(mtx, len);
  }
  printf("\n``````````````````this is end```````````````````````\n");
  unsigned char ca_publickey[] ={0x4a,0xb4,0x60,0x23,0xee,0x81,0x43,0xd0,0x89,0x0f,0x5b,0xe5,0x88,0x22,0x5e,0x17,0xcd,0x7e,0x19,0x88,0x64,0x74,0xa2,0x4a,0xa4,0xc3,0x3f,0x35,0x9c,0xb7,0xdb,0xe4,0x83,0xb4,0x72,0x95,0x48,0x4e,0x8d,0x3b,0xef,0x03,0x45,0x09,0x8b,0xd5,0x61,0x96,0xd4,0x75,0x0d,0xd4,0x40,0xf0,0x4d,0xbe,0x81,0xa0,0x9d,0x06,0x5c,0xa1,0x59,0xae};
  unsigned char ca_sign[]={0x5f,0xda,0x05,0x59,0x52,0xfe,0xdc,0xcf,0xd0,0x6d,0x46,0xad,0xe4,0xf2,0xbd,0x85,0x59,0x8c,0x12,0xba,0x7c,0xda,0x6c,0xbb,0xa9,0x5d,0x17,0xb9,0x4f,0xa1,0x72,0xdf,0x1f,0x54,0xef,0x50,0x04,0xe9,0x76,0xb4,0x34,0xb4,0x7f,0xf1,0x08,0xcc,0x91,0x22,0x0d,0xcb,0x9f,0x75,0x5c,0xbb,0xf5,0x87,0xa1,0x35,0x18,0xdf,0xc0,0x71,0xa9,0x6e};
  unsigned char ca_source[]={0x12,0x00,0x00,0x00,0x00,0x12,0x99,0x00,0x00,0x00,0x04,0x04,0x00,0x33,0x03,0xa0,0x80,0x98,0x56,0xe4,0xfd,0xd3,0x6d,0xba,0x5d,0x38,0x06,0x14,0xe0,0x69,0x84,0x48,0xfa,0x40,0x4d,0xc4,0x9e,0x2d,0xf3,0x70,0xb9,0x65,0x74,0xff,0xaf,0x39,0x0d};
  int ret = mt_sm2_verify(ca_publickey,sizeof(ca_publickey),ca_sign,sizeof(ca_sign),ca_source,sizeof(ca_source));
  if(ret == 1){
      printf("\n``````````````````this is success```````````````````````\n");
  }else
  { 
      printf("\n``````````````````this is failed```````````````````````\n");
  }
  unsigned char ca_publickey1[] ={0x46,0xd2,0x68,0x06,0xfa,0xda,0x1d,0xc0,0x0a,0xb8,0xca,0x28,0x48,0x85,0x37,0x05,0x26,0x11,0x59,0xca,0xf5,0x5c,0xe8,0xc5,0x12,0x5b,0xc1,0x71,0x77,0x05,0x39,0x2a,0xca,0xd4,0xd4,0x65,0x84,0x09,0x97,0xdc,0xde,0xc2,0x58,0x02,0x5a,0xa2,0x71,0xfe,0xec,0xf4,0xda,0x60,0xf8,0x6a,0xc2,0x3d,0x96,0x20,0xe9,0x13,0x82,0x9f,0x0e,0x4c};
  unsigned char ca_sign1[]={0xbe,0x00,0x1b,0x1b,0xf6,0x0e,0x9e,0x02,0x1e,0xba,0x5e,0x7d,0xf5,0xa5,0x2f,0x43,0xe1,0x4f,0xce,0x66,0xd9,0xb2,0x55,0xa4,0x95,0x48,0xef,0xfb,0x3c,0x2e,0x18,0xca,0x42,0xd7,0xf2,0x0b,0xb4,0xb8,0x87,0xfb,0xb0,0x44,0x67,0x3b,0x50,0x3a,0x58,0xdc,0x1f,0x85,0x99,0x04,0x9d,0x51,0xe0,0xfc,0x99,0x5e,0x40,0x55,0xbe,0x58,0x15,0x6a};
  unsigned char ca_source1[]={0x12,0x03,0x60,0x42,0x70,0x01,0x31,0x14,0x45,0x01,0x04,0x04,0x00,0x21,0x02,0xe1,0xcb,0x8e,0xae,0x77,0xa1,0xb5,0x88,0xca,0xb9,0x1e,0x02,0x20,0xfd,0xa2,0x0b,0x30,0x95,0x9f,0xc9,0x30,0xc9,0x67,0xd1,0xba,0x10,0x61,0x41,0xf4,0x29,0xf2,0xb6};
  ret = tm_sm2_verify(ca_publickey1,sizeof(ca_publickey1),ca_sign1,sizeof(ca_sign1),ca_source1,sizeof(ca_source1));
  if(ret == 1){
      printf("\n``````````````````this is success```````````````````````\n");
  }else
  { 
      printf("\n``````````````````this is failed```````````````````````\n");
  }
  return 0;
}


#include "tmsm2.h"
#include "sm2.h"
#include <string.h>
/*
功能:使用压缩钥匙XSM2验签
pubkeyx:压缩公钥X,17字节,0x02/0x03开头
pubkeylen:缩公钥X长度
sign:签名字符串
signlen:签名字符串长
data:数据字符串
datalen:数据字符串长度
*/
int tm_sm2_verify_compress(
        unsigned char* pubkeyX, int pubkeylen, unsigned char* sign, int signlen, unsigned char* data, int datalen) {
    //参数校验
    if (pubkeyX == NULL || pubkeylen < 0 || sign == NULL || signlen <= 0 || data == NULL || datalen <= 0) {
        return SM2_ERROR_PARAM;
    }
    int bc = -1;
    unsigned char pubkeyY[32], he[32];
    //签名数据长度
    if (signlen != 64)
        return SM2_ERROR_SIGNLEN;
    //公钥X长度
    if (pubkeylen != 33)
        return SM2_ERROR_PUBLICLEN;
    //公钥X压缩码
    switch (pubkeyX[0]) {
        case 0x02:
            bc = 0;
            break;
        case 0x03:
            bc = 1;
            break;
        default:
            return SM2_ERROR_COMPRESSCODE;
    }
    //获取公钥Y
    if (sm2_key_get_y(&pubkeyX[1], 32, pubkeyY, 32, bc) < 0) {
        return SM2_ERROR_GETPUBLICY;
    }
    //计算sm3 hash
    char userid[] = "1234567812345678";
    if (sm3_e((unsigned char *)userid, strlen(userid), &pubkeyX[1], 32, pubkeyY, 32, data, datalen, he) < 0) {
        return SM2_ERROR_SM3HASH;
    }
    // SM2验签
    if (sm2_verify_tm(he, 32, &sign[0], 32, &sign[32], 32, &pubkeyX[1], 32, pubkeyY, 32) < 0) {
        return SM2_ERROR_VERIFY;
    }
    return SM2_OK;
}
/*
功能:非压缩方式SM验签
pubkeyx:压缩公钥X,17字节,0x02/0x03开头
pubkeylen:缩公钥X长度
sign:签名字符串
signlen:签名字符串长
data:数据字符串
datalen:数据字符串长度
*/
int tm_sm2_verify(void* pubkey, int pubkeylen, void* sign, int signlen, void* data, int datalen) {
    //参数校验
    if (pubkey == NULL || pubkeylen <= 0 || sign == NULL || signlen <= 0 || data == NULL || datalen <= 0) {
        return MT_SM2_ERROR_PARAM;
    }
    unsigned char* pubk = (unsigned char*)pubkey;
    unsigned char* signdata = (unsigned char*)sign;
    unsigned char* data_c = (unsigned char*)data;
    unsigned char he[32];
    //签名数据长度
    if (signlen != 64)
        return SM2_ERROR_SIGNLEN;
    //公钥X长度
    if (pubkeylen != 64)
        return SM2_ERROR_PUBLICLEN;
    //计算sm3 hash
    char tmp[] = "1234567812345678";
    if (sm3_e((unsigned char *)tmp, strlen(tmp), &pubk[0], 32, &pubk[32], 32, data_c, datalen, he) < 0) {
        return SM2_ERROR_SM3HASH;
    }
    // SM2验签
  int sm2_res = sm2_verify_tm(he, 32, &signdata[0], 32, &signdata[32], 32, &pubk[0], 32, &pubk[32], 32);
    if (sm2_res < 0) {
        return SM2_ERROR_VERIFY;
    }
    return SM2_OK;
}


相关文章
|
19天前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
45 4
|
4月前
|
存储 算法 C语言
"揭秘C语言中的王者之树——红黑树:一场数据结构与算法的华丽舞蹈,让你的程序效率飙升,直击性能巅峰!"
【8月更文挑战第20天】红黑树是自平衡二叉查找树,通过旋转和重着色保持平衡,确保高效执行插入、删除和查找操作,时间复杂度为O(log n)。本文介绍红黑树的基本属性、存储结构及其C语言实现。红黑树遵循五项基本规则以保持平衡状态。在C语言中,节点包含数据、颜色、父节点和子节点指针。文章提供了一个示例代码框架,用于创建节点、插入节点并执行必要的修复操作以维护红黑树的特性。
106 1
|
21天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
65 8
|
21天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
59 7
|
3月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
98 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
2月前
|
算法 安全 物联网
如何应用SM2算法进行身份认证
【10月更文挑战第5天】如何应用SM2算法进行身份认证
82 1
|
2月前
|
存储 算法 安全
SM2算法的应用场景有哪些?
【10月更文挑战第5天】SM2算法的应用场景有哪些?
107 1
|
29天前
|
算法 安全 物联网
关于SM2、SM3、SM4、SM9这四种国密算法
本文介绍了四种国密算法——SM2、SM3、SM4和SM9。SM2是一种基于椭圆曲线的非对称加密算法,用于数据加密和数字签名;SM3是哈希算法,用于数字签名和消息完整性验证;SM4是对称加密算法,用于数据加密和解密;SM9是基于标识的非对称密码算法,适用于物联网环境中的数据安全和隐私保护。
195 0
|
3月前
|
机器学习/深度学习 人工智能 算法
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台。果蔬识别系统,本系统使用Python作为主要开发语言,通过收集了12种常见的水果和蔬菜('土豆', '圣女果', '大白菜', '大葱', '梨', '胡萝卜', '芒果', '苹果', '西红柿', '韭菜', '香蕉', '黄瓜'),然后基于TensorFlow库搭建CNN卷积神经网络算法模型,然后对数据集进行训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地文件方便后期调用。再使用Django框架搭建Web网页平台操作界面,实现用户上传一张果蔬图片识别其名称。
61 0
【果蔬识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
4月前
|
存储 SQL 消息中间件
B端算法实践问题之设计一套实时平台能力如何解决
B端算法实践问题之设计一套实时平台能力如何解决
45 1