生成密钥对:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "e_os.h"
#include "sm2ToOC.h"
#include "string.h"
# include <openssl/bn.h>
# include <openssl/ec.h>
# include <openssl/evp.h>
# include <openssl/rand.h>
# include <openssl/engine.h>
# include <openssl/sm2.h>
# include "sm2_lcl.h"
# include "pkcs12.h"
#include <openssl/pem.h>
#include "ec/ec_lcl.h"
#include "bn/bn_lcl.h"int genkey()
{EC_KEY *keypair = NULL;EC_GROUP *group1 = NULL;keypair = EC_KEY_new();if(!keypair) {printf("Failed to Gen Key");exit(1);}group1 = EC_GROUP_new_by_curve_name(NID_sm2p256v1);if(group1 == NULL){printf("Failed to Gen Key");exit(1);}int ret1 = EC_KEY_set_group(keypair, group1);if(ret1 != 1){printf("Failed to Gen Key");exit(1);}int ret2 = EC_KEY_generate_key(keypair);if(ret2 != 1){printf("Failed to Gen Key");exit(1);}size_t pri_len;size_t pub_len;char *pri_key = NULL;char *pub_key = NULL;BIO *pri = BIO_new(BIO_s_mem());BIO *pub = BIO_new(BIO_s_mem());PEM_write_bio_ECPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);PEM_write_bio_EC_PUBKEY(pub, keypair);BIO *bio_out = BIO_new_file("private.key", "w");PEM_write_bio_ECPrivateKey(bio_out, keypair, NULL, NULL, 0, NULL, NULL);BIO_free(bio_out);bio_out = BIO_new_file("public.key", "w");PEM_write_bio_EC_PUBKEY(bio_out, keypair);BIO_free(bio_out);pri_len = BIO_pending(pri);pub_len = BIO_pending(pub);pri_key = (char *)malloc(pri_len + 1);pub_key = (char *)malloc(pub_len + 1);BIO_read(pri, pri_key, pri_len);BIO_read(pub, pub_key, pub_len);pri_key[pri_len] = '\0';pub_key[pub_len] = '\0';EC_KEY_free(keypair);BIO_free_all(pub);BIO_free_all(pri);free(pri_key);free(pub_key);return 1;
}void main(void)
{genkey();
}

签字验签:


#include <stdio.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ecdsa.h>
#include <openssl/sha.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/sm2.h>#include <apps/apps.h>int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
{BIO *mem;int len, ret;unsigned char tbuf[1024];mem = BIO_new(BIO_s_mem());if (mem == NULL)return -1;for (;;) {if ((maxlen != -1) && maxlen < 1024)len = maxlen;elselen = 1024;len = BIO_read(in, tbuf, len);if (len < 0) {BIO_free(mem);return -1;}if (len == 0)break;if (BIO_write(mem, tbuf, len) != len) {BIO_free(mem);return -1;}maxlen -= len;if (maxlen == 0)break;}ret = BIO_get_mem_data(mem, (char **)out);BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);BIO_free(mem);return ret;
}static int sm2utl_sign(const EVP_MD *md, BIO *in, BIO *out, const char *id,ENGINE *e, EC_KEY *ec_key, int sign)
{int ret = 0;EVP_MD_CTX *md_ctx = NULL;ECDSA_SIG *sig = NULL;unsigned char buf[1024];size_t siz = sizeof(buf);unsigned int ulen = sizeof(buf);int len;printf("sm2utl_sign\n");if (!(md_ctx = EVP_MD_CTX_new())|| !EVP_DigestInit_ex(md_ctx, md, e)|| !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)|| !EVP_DigestUpdate(md_ctx, buf, siz)) {}while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {if (!EVP_DigestUpdate(md_ctx, buf, len)) {}}if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {}len = (int)ulen;if (sign) {unsigned char *p = buf;if (!(sig = SM2_do_sign(buf, len, ec_key))|| (len = i2d_ECDSA_SIG(sig, &p)) <= 0) {}}if (BIO_write(out, buf, len) != len) {}ret = 1;
end:EVP_MD_CTX_free(md_ctx);ECDSA_SIG_free(sig);return ret;
}static int sm2utl_verify(const EVP_MD *md, BIO *in, BIO *out, BIO *sig,const char *id, ENGINE *e, EC_KEY *ec_key)
{int ret = 0;EVP_MD_CTX *md_ctx = NULL;unsigned char *sigbuf = NULL;unsigned char buf[1024];size_t siz = sizeof(buf);unsigned int ulen = sizeof(buf);int siglen, len;siglen = bio_to_mem(&sigbuf, 256, sig);if (siglen < 0) {}if (!(md_ctx = EVP_MD_CTX_new())|| !EVP_DigestInit_ex(md_ctx, md, e)|| !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)|| !EVP_DigestUpdate(md_ctx, buf, siz)) {}while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {if (!EVP_DigestUpdate(md_ctx, buf, len)) {}}siz = sizeof(buf);if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {}/* SM2_verify() can check no suffix on signature */ret = SM2_verify(NID_undef, buf, ulen, sigbuf, siglen, ec_key);if (ret == 1) {printf("Signature Verification Successful\n");} else {printf("Signature Verification Failure\n");ret = 0;}end:OPENSSL_free(sigbuf);EVP_MD_CTX_free(md_ctx);return ret;
}int signature(char *msg)
{BIO *in = NULL, *out = NULL, *sig = NULL;char *keyfile = NULL;EVP_PKEY *pkey = NULL;EC_KEY *ec_key = NULL;int keyform = FORMAT_PEM;const EVP_MD *md = EVP_sm3();in  =  BIO_new_file("text.txt", "rb"); out = BIO_new_file("text.sig", "wb");BIO  * key  =  NULL;key = BIO_new_file("private.key", "r");pkey=PEM_read_bio_PrivateKey(key, NULL, 0, NULL);if (!(ec_key = EVP_PKEY_get0_EC_KEY(pkey))|| !EC_KEY_is_sm2p256v1(ec_key)) {printf("Invalid key type\n");return -1;}sm2utl_sign(md, in, out, "1234567812345678", 0, ec_key, 1);return 1;
}int verify_sig(void)
{const EVP_MD *md = EVP_sm3();BIO *in = NULL, *out = NULL, *sig = NULL;in  =  BIO_new_file("text.txt", "rb"); sig = BIO_new_file("text_1.sig", "rb");//FILE *fp = fopen("public_cert.pem", "r");//X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);FILE *fp = fopen("public.cer", "r");X509 *cert = d2i_X509_fp(fp, NULL);EVP_PKEY *evk = X509_get_pubkey(cert);EC_KEY *ec_key=EVP_PKEY_get0_EC_KEY(evk);if (1==sm2utl_verify(md, in, out, sig, "1234567812345678", 0, ec_key)){printf("verify success\n");}else{printf("verify fail\n");}return 1;
}void main(void)
{signature("1234567890123456");//verify_sig();
}

SM2签名及验证过程中,并不是直接计算被签名数据的摘要,而是要经过专门的预处理过程得到摘要。此过程包含两个阶段的摘要计算:

1)Z = SM3(ENTL || ID || a || b || x_G || y_G || x_A || y_A)

ENTL || ID || a || b || x_G || y_G || x_A || y_A表示签名元素数据的拼接(级联)。

其中,ENTL 是签名者 ID 的位长度,占两个字节;ID是签名者ID,国密标准里定义的缺省签名者ID用UFT_8字符串表示是“1234567812345678”,用十六进制表示是0x31323334353637383132333435363738。所以在缺省情况下,ENTL值是0x0080.a, b, x_G, y_G 都是SM2算法标准中给定的值。a和b是椭圆曲线y=x+ax+b的系数,x_G, y_G是SM2算法选定的基点的坐标。上述参数都是固定值:a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC

b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93

x_G= 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7

y_G=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

x_A || y_A就是公钥两部分值的拼接,注意,没有0x04的部分;将上述各元素拼接值进行SM3运算,得到结果Z。2) H=SM3(Z || M)

Z是第一步运算得到的摘要,M是签名的原文,将两者拼接,再进行SM3摘要运算。得到的摘要就是预处理得到的结果,将用于后续的签名及验证运算。

参考:

https://www.pianshen.com/article/2043152732/
https://github.com/guanzhi/GmSSL/

https://baijiahao.baidu.com/s?id=1674018830496556781&wfr=spider&for=pc

gmssl国密sm2(生成密钥对-私钥签字-证书验签)相关推荐

  1. mysql国密算法_【国密SM2算法】通过公钥证书获取JAVA对象

    网上关于国密算法的资料较单一,大部分代码都是写的怎么通过java代码生成公私钥串. 实际项目中对方已经给了他们的公钥证书,这里记录如何通过代码解析获得Ecpoint对象并输出 关键代码 String ...

  2. php gmssl,支持国密SM2/SM3/SM4/SM9/ZUC/SSL的密码工具箱GmSSL

    GmSSL概述 GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法.SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码 ...

  3. 基于mbedTLS算法库实现国密SM2签名和验签算法

    网上有大量的基于OpenSSL实现的国密算法库,比如著名的GmSSL,可以直接拿来用.我自己常用的是mbedTLS的算法库,比较小巧简单,在mbedTLS的大数算法的基础上实现了国密SM2的签名和验签 ...

  4. Spring Security-用户密码自定义国密SM2加密

    为什么80%的码农都做不了架构师?>>>    由于甲方要求需要把密码的加密方式改为国密SM2的方式,网上看了一些写的代码,结合了一下SpringSecurity用户自定义加密,直接 ...

  5. 通过网页查看服务器算法,服务器使用国密(SM2/SM3/SM4)证书,通过浏览器访问

    1. Apache + Gmssl Apache 本身不支持国密,需要修改代码支持GMTLS 下载解压: wget http://archive.apache.org/dist/httpd/httpd ...

  6. 使用 Python 脚本执行国密 sm2 加解密

    一.场景 工作中的一个场景:Go 需要对信息加解密,但是研究了 GmSSL Go API 文档之后,发现是依赖于 CGO 的,同事配了半天环境没配成功.于是换了一个方法,选择 Go 调 Python ...

  7. 服务器使用国密(SM2/SM3/SM4)证书,通过浏览器访问

    1. Apache + Gmssl Apache 本身不支持国密,需要修改代码支持GMTLS 下载解压: wget http://archive.apache.org/dist/httpd/httpd ...

  8. vue前端国密SM2, SM4 算法实现

    vue前端国密SM2, SM4 算法实现 整体加密逻辑是,首先生成16位key值 用SM2 公钥加密该key值,后端用sm2私钥 解密出key值,然后采用sm4方法根据key值对返回值进行加密,前端采 ...

  9. gmssl 国密ssl流程测试

    gmssl 国密ssl流程测试 前言 一 gmssl ssl流程测试 单证书单向认证 二 gmssl ssl 流程 单证书 双向认证 三 gmssl gmtls 流程 双证书 单向认证 四 gmssl ...

最新文章

  1. Python 面向对象 基础
  2. Funtion:POPUP_TO_DECIDE_LIST
  3. Python之路_Day13
  4. Software Engineering at Google
  5. 【渝粤题库】陕西师范大学201691 日语(二) 作业
  6. 云+X案例展 | 民生类:基于AWS PaaS构建基础集团企业级中台
  7. 每个tabpage中都有一个dategridview_每个女人,都有一个礼服梦
  8. Qt creator5.7 OpenCV249之图片腐化(含源码下载)
  9. Jeewx捷微 , 免费微信公众账号管家系统发布,采用JAVA语言
  10. ionic3 html调用摄像头,Ionic3项目实战
  11. 喵喵的QQ小程序登录
  12. SAP ERP 安全管理平台系统
  13. 自动化测试——接口测试——增删改查
  14. python 代码命令大全-深度学习中python常用命令
  15. pcl dll load failed: 找不到指定的模块。_解决cuda10.1+tensorflow-gpu出现“cudart64_100.dll”问题...
  16. vue 显示日期只显示年月_Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示...
  17. 基于matlab的图像识别分类实验(一)
  18. 跨境电商倍受青睐缘由为何,木瓜移动带你一探究竟
  19. STM32 F103 外部晶振8M改为12M
  20. 基于微信小程序的新生自助报到系统小程序

热门文章

  1. 如何翻译DeepFaceLab(DeepFake)的交互式合成器
  2. c200系列服务器主板,主板厂商的曲线救主,E3-1230 v5/技嘉X150-PLUS WS主板评测
  3. python编写一个名片_python基础-实现名片功能
  4. 烛光晚餐矢量图(编号:82204)_日常生活_矢量人物_矢量素材
  5. 疯狂python讲义学习日志11——并发编程
  6. 台式计算机进入安全模式蓝屏,电脑蓝屏不能进入安全模式的解决方法
  7. CSS中margin属性详解
  8. 代码随想录30——回溯:332重新安排行程、51N皇后、37解数独
  9. illustrator插件-常用功能开发-打开多页PDF-js脚本开发-AI插件
  10. 01前端入门HTML5 +Css3+电商网页制作:HTML5