博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
国密算法--Openssl 实现国密算法(基础介绍和产生秘钥对)
阅读量:6271 次
发布时间:2019-06-22

本文共 5335 字,大约阅读时间需要 17 分钟。

国密非对称加密算法

又称sm2,它是采取了ECC(曲线加密算法)中的一条固定的曲线,实际上就是ECC算法。 因为openssl里面不包含sm2算法,所以就要重新进行封装…. …


对于ECC算法我就不介绍了,网上关于它的介绍一抓一大把,丢给你们一个链接介绍。

现在对ECC加密算法做个大致的介绍:

所有非对称加密算法都有公钥和私钥,它们都可以用下面这个公式概括:

A = k * G公钥:A , G 私钥:k , G

在ECC加密中 G是基准点,k是小于n(基准点的阶)的一个素数, A是加密曲线上的一个点

ECC的加密曲线是不固定的,选择一条好的加密曲线是很重要的,而且无论是加密还是解密我们都需要用到这条曲线,固定一条ECC加密曲线需要六个参数:

P(参数范围) a,b(曲线参数) (Gx,Gy)(基准点) n(基准点的阶) h(余因子, h = #E(Fq)/n,其中n是基点G的阶,这个是可选参数。)

相比到这我们已经有些头大了,这么多参数要设置?别慌这些在sm2算法里面都是固定的

/*Sm2 中指定的参数 确定下y2 = x3 + ax + b 曲线*/#define _P  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"#define _a  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"#define _b  "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"#define _n  "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"#define _Gx "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"#define _Gy "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"

我们所做的一切都是基于sm2中的那条曲线,以上就是理论知识的介绍。


下面我们将如何利用openssl中的ECC算法去实现sm2,这里不得不说,openssl这个东西…有点难用啊。这个大家做好心理准备,要写很多期的,我们今天先说如何生成sm2的key;

首先我们要先得到国密这条曲线,直接贴代码有点太不负责任了,我先给大家先说一写基本的东西:

先讲几个结构体

//BN_CTX openssl中加密算法结构体,里面包含各种加密算法的函数指针typedef struct bignum_ctx BN_CTX;//EC_GROUP ecc算法中的组结构体,里面包含着曲线信息typedef struct ec_group_st    /*     EC_METHOD *meth;     -- field definition     -- curve coefficients     -- optional generator with associated information (order, cofactor)     -- optional extra data (precomputed table for fast computation of multiples of generator)     -- ASN1 stuff    */    EC_GROUP;//EC_POINT ecc算法中的点结构体,里面有x,y,z三个值来确地曲线上的一个点typedef struct ec_point_st EC_POINT;//EC_KEY ecc算法中的秘钥结构体,里面包含私钥、公钥、曲线信息typedef struct ec_key_st EC_KEY;

然后我说一下生成key的过程:

//1.先要获取sm2曲线//先实例化一个 组对象  EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)//说明:生成二进制域上的椭圆曲线,输入参数为p,a和b//传入曲线参数int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)//说明:设置素数域椭圆曲线参数;//设置基准坐标点 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)//说明:设置素数域椭圆曲线上点point的几何坐标;//将基准座标传入组对象 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)//说明:设置椭圆曲线的基G;generator、order和cofactor为输入参数;//2.生成秘钥对//在sm2曲线上生成秘钥对int EC_KEY_generate_key(EC_KEY *eckey)//说明:生成椭圆曲线公私钥;//获取公钥坐标点const EC_POINT* EC_KEY_get0_public_key(EC_KEY *eckey)//说明:获取公钥。//获取私钥素数const BIGNUM* EC_KEY_get0_private_key(EC_KEY *eckey) //说明:获取私钥

好了 ,下面到了最重要的一步,贴代码:

include 
#include
#include
#include
/*Sm2 中指定的参数 确定下y2 = x3 + ax + b 曲线*/#define _P "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"#define _a "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"#define _b "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"#define _n "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"#define _Gx "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"#define _Gy "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"....int sm2_gen_key(PSM2_KEY sm2key){ int ret = -1; EC_KEY* key = NULL; BN_CTX *ctx = NULL; EC_GROUP* group = NULL; EC_POINT* point_p = NULL; const EC_POINT *point_q = NULL; BIGNUM *p, *a, *b, *gx, *gy, *z; assert(sm2key); p = BN_new(); a = BN_new(); b = BN_new(); gx = BN_new(); gy = BN_new(); z = BN_new(); //初始化一个空算法组 group = EC_GROUP_new(EC_GFp_mont_method()); //将国密算法的参数转为大数 BN_hex2bn(&p, _P); BN_hex2bn(&a, _a); BN_hex2bn(&b, _b); BN_hex2bn(&gx, _Gx); BN_hex2bn(&gy, _Gy); BN_hex2bn(&z, _n); //素数P的阶 ctx = BN_CTX_new(); //先确定sm2曲线 //传入a,b参数 if (!EC_GROUP_set_curve_GFp(group, p, a, b,ctx)) { goto err_process; } //取曲线上的三个点 point_p = EC_POINT_new(group); //设置基点坐标 if (!EC_POINT_set_affine_coordinates_GFp(group, point_p, gx, gy, ctx)) { goto err_process; } // 确定P点事否在曲线上 if (!EC_POINT_is_on_curve(group, point_p, ctx)) { ret = -2; goto err_process; } //设置椭圆曲线的基G,完成了国密曲线 if(!EC_GROUP_set_generator(group, point_p, z, BN_value_one())) { ret = -3; goto err_process; } //生成国密Key key = EC_KEY_new(); if (!EC_KEY_set_group(key, group)) { ret = -4; goto err_process; } if(!EC_KEY_generate_key(key)) { ret = -5; goto err_process; } printf("gen key success:\n the prv is %s\n", BN_bn2hex(EC_KEY_get0_private_key(key))); sm2key->prv_key.bytes = BN_bn2bin(EC_KEY_get0_private_key(key), sm2key->prv_key.k); point_q = EC_KEY_get0_public_key(key); if(!EC_POINT_get_affine_coordinates_GFp(group, point_q, gx, gy , NULL)) { goto err_process; } sm2key->pub_key.bytes = BN_bn2bin(gx, sm2key->pub_key.x); BN_bn2bin(gy, sm2key->pub_key.y); ret = 0;err_process: if (point_p != NULL) { EC_POINT_free(point_p); } if (group != NULL) { EC_GROUP_free(group); } if (ctx != NULL) { BN_CTX_free(ctx); } if (key != NULL) { EC_KEY_free(key); } return ret;}

转载于:https://www.cnblogs.com/cnblogs-wangzhipeng/p/9933562.html

你可能感兴趣的文章
fmt标签如何计算两个日期之间相隔的天数
查看>>
Spark核心技术原理透视一(Spark运行原理)
查看>>
《Gradle权威指南》--Gradle任务
查看>>
IntelliJ IDEA创建文件时自动填入作者时间 定制格式
查看>>
Android app启动activity并调用onCreate()方法时都默默地干了什么?
查看>>
远程监视jboss应用java内存的配置
查看>>
前端如何接收 websocket 发送过来的实时数据
查看>>
JavaWeb下载文件response
查看>>
Laravel的三种安装方法总结
查看>>
SpringMVC加载配置Properties文件的几种方式
查看>>
C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginat...
查看>>
java 项目相关 学习笔记
查看>>
numpy opencv matlab eigen SVD结果对比
查看>>
WPF获取某控件的位置,也就是偏移量
查看>>
Boost C++ 库 中文教程(全)
查看>>
solr查询优化(实践了一下效果比较明显)
查看>>
jdk目录详解及其使用方法
查看>>
说说自己对RESTful API的理解s
查看>>
通过layout实现可拖拽自动排序的UICollectionView
查看>>
服务器错误码
查看>>