国密非对称加密算法

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


对于ECC算法我就不介绍了,网上关于它的介绍一抓一大把,丢给你们一个链接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 <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ebcdic.h>
#include <openssl/ecdsa.h> /*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;
}

国密算法--Openssl 实现国密算法(基础介绍和产生秘钥对)的更多相关文章

  1. 国密算法--Openssl 实现国密算法(加密和解密)

    上一次讲了产生密钥,这次我们讲一下加密解密的实现. 先说一下加密解密的流程,一下这些内容都是从国密局发布的国密标准文档里面摘录出来的.大家可以去国密局的网站上自己下载. 下列符号适用于本部分. A,B ...

  2. openssl解析国密X509证书

    openssl解析国密X509证书,把公钥拿出来重写一下就行了        x = strToX509(pbCert, pulCertLen);dwRet = getCertPubKey(x, &a ...

  3. 源代码方式向openssl中加入新算法完整具体步骤(演示样例:摘要算法SM3)【非engine方式】

    openssl简单介绍 openssl是一个功能丰富且自包括的开源安全工具箱.它提供的主要功能有:SSL协议实现(包括SSLv2.SSLv3和TLSv1).大量软算法(对称/非对称/摘要).大数运算. ...

  4. 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)

    其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...

  5. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  6. [Algorithm] 群体智能优化算法之粒子群优化算法

    同进化算法(见博客<[Evolutionary Algorithm] 进化算法简介>,进化算法是受生物进化机制启发而产生的一系列算法)和人工神经网络算法(Neural Networks,简 ...

  7. ZeroMQ接口函数之 :zmq_z85_encode – 使用Z85算法对一个二进制秘钥进行加密,输出可打印的文本

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq-z85-encode zmq_z85_encode(3)          ØMQ Manual - ØMQ/4. ...

  8. 【转】常用聚类算法(一) DBSCAN算法

    原文链接:http://www.cnblogs.com/chaosimple/p/3164775.html#undefined 1.DBSCAN简介 DBSCAN(Density-Based Spat ...

  9. JVM内存管理------GC算法精解(复制算法与标记/整理算法)

    本次LZ和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一章在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算 ...

随机推荐

  1. Java并发编程--4.Executor框架

    简介 Executor框架是启动,管理线程的API, 它的内部实现是线程池机制,它有很多好处,比如使任务提交和任务执行解耦合,防止this逃逸:它的主要API包括: Executor,  Execut ...

  2. [转]SVN服务器搭建和使用(一)

    Location是指VisualSVN Server的安装目录,Repositorys是指定你的版本库目录.Server Port指定一个端口,Use secure connection勾山表示使用安 ...

  3. 东芝线阵CCD芯片TCD1305DG驱动时序设计

    最近在做微型光谱仪,用到了东芝的CCD芯片TCD1305DG,该芯片是单行3648像素,输出信号是时间上离散的模拟信号,典型输出速率为0.5M,即每2000ns输出一个像素值(模拟信号),芯片内部集成 ...

  4. 从公司服务器C盘被删说起

    事情起因 一个阳(严)光(重)明(雾)媚(霾)的周二,对于我们从周二到周六的班次来说,这是新的一周开始.我像往常一样,打开电脑,倒上一杯水,开始翻阅从大洋彼岸发来的各种邮件.突然看到一封紧急的邮件,内 ...

  5. 如何取得SharePoint Timer Job的历史成功数和失败数,并按照日期计算排列

    [问题]. 如何取得SharePoint Timer Job的历史成功数和失败数,并按照日期计算排列 [分析] 管理中心只是罗列了所有job的历史和上一次是否成功,没有关于成功和失败的统计数据 [解决 ...

  6. iOS 用KVC设置结构体

    iOS 用KVC设置结构体 在Fundation中KVC提供的键值路径只能访问对象,不能访问结构体.这很不面向对象. 执行下面的语句将会报错: [self setValue:@() forKeyPat ...

  7. 对象关系映射(ORM)

    1.什么是 对象-关系映射 对象-关系映射(Object Relational Mapping,简称ORM,对象关系映射)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,OR ...

  8. Ubuntu 16.04 下简单安装使用golang之备忘

      刚开始学习Go语言,这里记录下我在Ubuntu 16.04下安装使用golang的过程,方便以后查询.   一.安装   1.添加源   如果使用默认的源安装golang的话,版本太低,只到1.6 ...

  9. Web 前端性能优化相关内容解析

    Web 前端性能优化相关内容,来源于<Google官方网页载入速度检测工具PageSpeed Insights 使用教程>一文中PageSpeed Insights 的相关说明.大家可以对 ...

  10. 使用git管理代码

    上传工程 1.登录github后,点击右上角带有+号的图标,输入仓库名创建仓库(Repository). 2.在项目文件夹下执行以下命令: touch README.md git init 如果工程中 ...