国密SM2算法系列操作

1. GMSSL安装
  GMSSL安装步骤
  装好之后可以调用命令行
2. GMSSL签发SM2密钥证书
 GMSSL生成SM2证书

     //生成私钥:
gmssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:sm2p256v1 -pkeyopt ec_param_enc:named_curve -out skey.pem
     //生成公钥gmssl pkey -pubout -in skey.pem -out vrfykey.pem

  公钥证书发给对方用于加密,私钥证书留存己方用于解密。

3. SM2概述
  SM2是一种基于椭圆曲线密码算法的非对称加解密算法。

3.1椭圆曲线
  方式一:自己指定椭圆曲线的参数。有限域上的一条椭圆曲线一共由六个量确定。有限域由两种(Fp和F2m,其中Fp为素数域)。六个量分别是:
p    //素数域内点的个数
a    //域内的一个大数
b    //域内的一个大数,p、a、b确定一条椭圆曲线
x    //基点的x坐标
y    //基点的y坐标
n    //基点的阶
有时,还会用到h(椭圆曲线上所有点的个数p与n相除的整数部分)。
  根据这六个参数即可自己创建一个椭圆曲线

//详情参见GMSSL的sm2test.cconst char p_hex[64] = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF";const char a_hex[64] = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC";const char b_hex[64] = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"const char x_hex[64] = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";const char y_hex[64] = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";const char n_hex[64] = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123";EC_GROUP *group = NULL;BN_CTX *ctx = NULL;BIGNUM *p = NULL;BIGNUM *a = NULL;BIGNUM *b = NULL;BIGNUM *x = NULL;BIGNUM *y = NULL;BIGNUM *n = NULL;EC_POINT *G = NULL;point_conversion_form_t form = SM2_DEFAULT_POINT_CONVERSION_FORM;BN_hex2bn(&p, p_hex);   //首先需要把hex转化为大数类型...BN_hex2bn(&n, n_hex);group = EC_GROUP_new_curve_GFp(p, a, b, ctx); //根据pab生成素数域(阿贝尔群)G = EC_POINT_new(group);                      //根据group生成基点EC_POINT_set_affine_coordinates_GFp(group, G, x, y, ctx);//生成素数域上的仿射坐标
//若有限域为F2m,则为EC_POINT_set_affine_coordinates_GF2m(group, G, x, y, ctx);EC_GROUP_set_asn1_flag(group, 0);             //设置是否asn1编码,这关系到密文转换是o2i i2o还是i2d d2iEC_GROUP_set_point_conversion_form(group, form);return group;

  方式二:采用SM2默认推荐的素数域256位的椭圆曲线

//初始化一个推荐椭圆曲线的算法组EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

3.2 SM2密钥生成
  SM2公私钥:P=[d]G,G是基点已知的,大数d为私钥,点P(xP, yP)为公钥,xP、yP分别为生成公钥所需的xy坐标。

  方式一:自己指定参数。

//生成加密用的公钥const char xP[64] = "435B39CCA8F3B508C1488AFC67BE491A0F7BA07E581A0E4849A5CF70628A7E0A";const char yP[64] = "75DDBA78F15FEECB4C7895E21C1CDF5FE01DEBB2CDBADF45399CF77BBA076A42";BIGNUM *x = NULL;BIGNUM *y = NULL;EC_KEY *ec_key = NULL;ec_key = EC_KEY_new();EC_KEY_set_group(ec_key, group);    //指定密钥所用的算法组BN_hex2bn(&x, xP);                  //将16进制数转化为大数BN_hex2bn(&y, yP);EC_KEY_set_public_key_affine_coordinates(ec_key, x, y);  //设置公钥
//生成解密用的私钥const char d_hex[64] = "1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0";BIGNUM *d = NULL;BN_hex2bn(&d,d_hex);EC_KEY *ec_key = NULL;ec_key = EC_KEY_new();EC_KEY_set_group(ec_key, group);    //指定密钥所用的算法组EC_KEY_set_group(ec_key, d);        //设置私钥

  方式二:随机生成密钥对。

    EC_KEY *keypair = NULL;int ret1,ret2;keypair = EC_KEY_new();EC_GROUP *group1 = EC_GROUP_new_by_curve_name(NID_sm2p256v1);ret1 = EC_KEY_set_group(keypair, group1);ret2 = EC_KEY_generate_key(keypair);  //随机生成密钥对

  方式三:从证书里读取公私钥。

//从证书文件中读取公钥(公钥为xy坐标确定的一个点)char pub_pem_file_path[128] = "/tmp/vrfykey.pem";BIO *pub_in = NULL;pub_in = BIO_new(BIO_s_file());    //openssl输入输出流if(BIO_read_filename(pub_in, pub_pem_file_path) <= 0){    //把pem文件信息读入文件流return -1;}EC_KEY *pub_key = NULL;PEM_read_bio_EC_PUBKEY(pub_in, &pub_key, NULL, NULL);  //从文件流中读取公钥//打印公钥const EC_POINT *point_pub_key = EC_KEY_get0_public_key(pub_key);    //从公钥中拿到点const EC_GROUP *group = NULL;
group = EC_KEY_get0_group(pub_key);    //从公钥中获取密钥生成时所用的算法组BIGNUM *pub_x_bn = NULL;BIGNUM *pub_y_bn = NULL;BN_CTX *bn_ctx = NULL;if(!(pub_x_bn = BN_new()) || !(pub_y_bn = BN_new()) || !(BN_CTX_new())){return -1;}EC_POINT_get_affine_coordinates_GFp(group, point_pub_key, pub_x_bn, pub_y_bn, bn_ctx); //依据算法组从公钥点中拿坐标char *pub_x = BN_bn2hex(pub_x_bn);  //将公钥坐标由大数转化为十六进制char *pub_y = BN_bn2hex(pub_y_bn);printf("公钥的x坐标为:%s\n", pub_x);printf("公钥的y坐标为:%s\n", pub_y);
//从证书文件中读取私钥char *passin = NULL;               //读取私钥证书所需的密码,无密码则为空char pri _pem_file_path[128] = "/tmp/skey.pem";BIO *pri_in = NULL;pri_in = BIO_new(BIO_s_file());    //openssl输入输出流if(BIO_read_filename(pri_in, pri_pem_file_path) <= 0){    //把pem文件信息读入文件流return -1;
}EC_KEY *pri_key = NULL;PEM_read_bio_ECPrivateKey(pri_in, &pri_key, NULL, passin);  //从文件流中读取私钥//打印私钥const BIGNUM *pri_key_bn = EC_KEY_get0_private_key(pri_key);  //私钥转为大数char *private_key = BN_bn2hex(pri_key_bn);  //大数转为十六进制,方便打印printf("私钥为:%s\n", private_key);

3.3 SM2加密

  GM标准规定的SM2加密算法流程为:

旧标准的密文为C = C1 || C2 || C3,后来也有C = C1 || C3 || C2的形式,共两种。
  实际运用中,GMSSL中已实现了该算法,函数名:SM2_do_encrypt(),我们只需要调用即可。

 printf("/***********SM2加密测试***********/");const char *plaintext = "test message";const size_t plaintext_len = strlen(plaintext);printf("明文为:%s\n", plaintext);//进行加密SM2Ciphertextvalue *cv = NULL;    //标准格式的密文const EVP_MD *md = EVP_sm3();     //SM2加密所用的摘要算法默认为SM3if(!(cv = SM2_do_encrypt(md, (unsigned char *)plaintext, plaintext_len, pub_key))){  //杂凑函数、明文、明文长度、公钥printf("SM2_do_encrypt fail.");return -1;}//打印密文const EC_GROUP *group = EC_KEY_get0_group(pub_key);unsigned char cipher_buf[512] = {0};unsigned char *cipher_text = cipher_buf;int cipher_text_len = i2o_SM2CiphertextValue(group, cv, &cipher_text);  //将标准密文cv转化为字符形式,存在cipher_buf中//注意,若EC_GROUP_set_asn1_flag设置为1,则用i2d_SM2CiphertextValue(cv, &cipher_text)这个接口。//EC_GROUP_new_by_curve_name(NID_sm2p256v1)出来的group默认asn1_flag为1.printf("加密后的密文为:%s\n", cipher_buf);printf("密文长度为:%d", cipher_text_len);printf("密文的十六进制为:");int i = 0;for(i = 0; i < cipher_text_len; i++){printf("%02x", cipher_buf[i]);  //不足两位补齐,如6AB输出为06AB}printf("\n");

也可以往上调一层,调用sm2utl.c中的SM2_encrypt()函数。该函数本质上也是调用SM2_do_encrypt(),只是做了一层封装。调用如下:

4.
------------------------------未完待续------------------------------

SM2算法全套(基于GMSSL)相关推荐

  1. 【sm2算法】基于mbedtls开源库国密算法的使用(一)

    基础知识 (1)公钥:在代码编程中,公钥是使用64个字节来存储的. (2)私钥:在代码编程中,公钥是使用32个字节来存储的. 对应的代码具体实现 (1)mbedtls sm2环境 在 mbedtls ...

  2. 基于 gmssl实现的sm2加密(C++)

    项目中需要用到sm2加密,在网上搜索了一下相关的库,发现只有openssl和gmssl这两个库可以用,于是基于gmssl库做了封装,gmssl的版本是:GmSSL 2.5.4 - OpenSSL 1. ...

  3. 国密算法—SM2介绍及基于BC的实现

    国密算法-SM2介绍及基于BC的实现 文章目录 国密算法-SM2介绍及基于BC的实现 简介 私钥 公钥 数据格式 密钥数据格式 私钥数据格式 公钥数据格式 加密数据格式 签名数据格式 计算过程 生成密 ...

  4. 基于gmssl SM2 签名验签测试程序

    基于gmssl SM2 签名验签测试程序 前言 一.sm2 签名流程 二.sm2 验签流程 三.测试结果 总结 前言 在之前的文章中讲解了基于gmssl 的SM2的加解密接口的测试程序,这里主要讲解签 ...

  5. 基于GmSSL的国密SSL单向验证客户端C源码

    1 搭建测试服务器 基于GmSSL搭建Nginx国密反代服务器 2 C 源码 #include <stdio.h> #include <string.h> #include & ...

  6. PBOC3.0中使用的国密SM2算法

    一.知识准备 PBOC3.0规范就是<中国金融集成电路(IC)卡规范>3.0版本. SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用密码算法.本身是基于ECC椭圆曲线算法的, ...

  7. C语言实现SM3(基于GMSSL)

    上一篇文章已经完成了调用gmssl测试Sm4算法实现,https://blog.csdn.net/lingdukafeibj/article/details/107493356 本文继续测试SM3算法 ...

  8. SM2算法与原生RSA、ECDSA算法的比较

    基于问题不同 RSA算法基于大数分解问题(integer factorization problem IFP),可靠性由对极大整数做因数分解的难度决定.换言之,对一极大整数做因数分解愈困难,RSA算法 ...

  9. C语言KDF密钥源代码,区块链中的数学-SM2算法与KDF密钥导出函数

    本节讲了SM2算法的KDF函数,从一般用途到SM2特定实现 ## 写在前面 上一节说了[sm2概述和加密过程](https://learnblockchain.cn/article/1516)实现, ...

  10. 谈谈PBOC3.0中使用的国密SM2算法

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主 ...

最新文章

  1. 商贸通服装鞋帽版客户端无法连接服务器的问题(自己遇到的,已解决)
  2. 华为S5700系列交换机配置文件导出、导入
  3. exchange 删除邮件
  4. HDU 1207 汉诺塔II (递推)
  5. python绘制动态条形图_Python 绘图与可视化 matplotlib 动态条形图 bar
  6. DirectX修复工具使用技巧之一——解除被占用的文件,完整修复C++
  7. k近邻(kNN)算法的Python实现(基于欧氏距离)
  8. 计算机辅储存器有什么,计算机辅存储器包括
  9. C# 开发的 webBrowser打开网页出现脚本错误解决
  10. 福莫特罗行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  11. OutputFormat类——Hadoop
  12. Stata-交乘项专题: 主效应项可以忽略吗?
  13. mysql删除指令_mysql怎么用命令删除数据?
  14. 报错:‘Concatenate’layer requires inputs with matching shapes expect for the concat axis. 解决思路
  15. [从头读历史] 第309节 星球战争 BC2499 至 BC2400(公元前25世纪)
  16. 客快物流大数据项目(八十五):实时OLAP分析需求
  17. 别了,开拓者的小伙们!
  18. 高防CDN怎么防攻击,能防什么攻击?
  19. 花旗金融2020春招面经(offer)
  20. 华为设备基本ACL和高级ACL综合配置

热门文章

  1. # 华为数通IE学习 第一节
  2. 2022/2023届-Matlab数字图像处理—选题推荐
  3. java 正则表达式 html,java正则表达式语法大全
  4. c语言坐标轮换法_优化设计-鲍威尔法程序(c语言)
  5. 适配器模式(Adapter模式)详解
  6. b2c京东流程图_京东商城的商业模式及其运作流程(精)
  7. 英伟达显卡排名天梯图2022
  8. 腾讯云TDSQL分布式数据库安装部署
  9. ​越狱iOS必备神器Flex使用指南-屏蔽越狱检测的破解利器
  10. 走向Java架构师之路:成为架构师要掌握的8大能力