netty实现gmssl_SM2加解密算法(基于GMSSL的C代码实现)

一、椭圆曲线密码算法

椭圆曲线:是一类二元多项式方程,它的解构成一个椭圆曲线。

椭圆曲线参数:定义一条唯一的椭圆曲线。介绍其中两个参数G(基点)和n(阶)。G点(xG, yG)是椭圆曲线上的基点, 有限域椭圆曲线上所有其他的点都可以通过G点的倍乘运算计算得到,即P=[d]G, d也是属于有限域,d的最大值为素数n。

有限域上的椭圆曲线:椭圆曲线上的解不是连续的,而是离散的,解的值满足有限域的限制。有限域有两种,Fp和F2m。

E(Fq):Fq上椭圆曲线E 的所有有理点(包括无穷远点O)组成的集合。

Fp:一个素整数的集合,最大值为P-1,集合中的值都是素数,里面元素满足以下模运算: a+b=(a+b) mod p 和 ab=(ab) mod p。

SM2:有限域Fp上的一条椭圆曲线,其椭圆曲线参数是固定值。

公私钥:P=[d]G,G是已知的,大数d为私钥,点P(XP, YP)为公钥。

SM2推荐使用素数域256位椭圆曲线:

-->EC_GROUP_new_by_curve_name(NID_sm2p256v1)

//可以得出固定参数

//Sm2 中指定的参数 确定下y2 = x3 + ax + b 曲线

#define _P "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"

#define _a "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"

#define _b "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"

#define _n "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"

#define _Gx "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"

#define _Gy "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"

OpenSSL部分涉及代码

//初始化一个空算法组

EC_GROUP *group = EC_GROUP_new(EC_GFp_mont_method());

//初始化一个推荐椭圆曲线的算法组

EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

//上下文

BN_CTX *ctx = BN_CTX_new();

//创建EC_KEY,使用推荐椭圆曲线

EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1)

//生成公钥私钥

EC_KEY_generate_key(ec_key);

//设置私钥

EC_KEY_set_private_key(ec_key, d);

//设置公钥

EC_KEY_set_public_key(ec_key, P);

//通过ec_key获取算法组

EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);

//获取基点G

EC_POINT * G = EC_GROUP_get0_generator(ec_group);

//大数初始化

BIGNUM *rand = BN_new();

//EC_POINT初始化

EC_POINT *P = EC_POINT_new(ec_group);

//获取坐标点p的x,y值

EC_POINT_get_affine_coordinates_GFp(ec_group,p,x,y,ctx);

//Gets the order of a EC_GROUP -- n阶 对应上面固定参数的_n

EC_GROUP_get_order(ec_group, order, ctx);

//随机数生成

do {

BN_rand_range(rand,order);

} while (BN_is_zero(rand));

//大数转二进制

int len = BN_bn2bin(bn, outChar);

//获取坐标点p转大数bn

EC_POINT_point2bn(ec_group, p, POINT_CONVERSION_COMPRESSED, bn, ctx);

//点的乘积 lP = P * rand

EC_POINT_mul(ec_group, lP, NULL, P, rand, ctx);

//验证点C1是否在椭圆曲线上

EC_POINT_is_on_curve(ec_group, c1, ctx);

马上开始

二、SM2加密算法(手动实现和使用GMSSL库实现)

PS:加解密中,加密时椭圆曲线点C1转换方式必须和解密时椭圆曲线点C1转换方式一致,否则无法解出C1。

1、手动实现

流程

image.png

算法:

1、产生随机数k, k的值从1到n-1;

BIGNUM *n,*k;

n = BN_new();

k = BN_new();

EC_GROUP_get_order(ec_group, n, ctx);

do {

BN_rand_range(k,n);

} while (BN_is_zero(k));

2、计算椭圆曲线点C1=[k]G=(x1,y1), 将C1使用EC_POINT_point2oct转换成比特串;

//获取基点G

const EC_POINT *G = EC_GROUP_get0_generator(ec_group);

EC_POINT *c1 = NULL;

c1 = EC_POINT_new(ec_group);

unsigned char c1bin[65];

unsigned long c1binlen = 65;

EC_POINT_mul(ec_group, c1, NULL, G, k, ctx);

EC_POINT_point2oct(ec_group, c1, POINT_CONVERSION_UNCOMPRESSED, c1bin, c1binlen, ctx);

3、 验证公钥PB, 计算S=[h] PB,如果S是无穷远点,出错退出;

EC_POINT_is_on_curve(ec_group, PB, ctx);

EC_POINT_is_at_infinity(ec_gr

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值