SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库)
SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库)
- 实验环境
- 预备知识
- FpF_pFp 及椭圆曲线
- 素域 FpF_pFp
- FpF_pFp 上的椭圆曲线
- FpF_pFp 上椭圆曲线系统参数
- FpF_pFp 上椭圆曲线系统参数的验证
- SM2 公钥密码算法
- 密钥对的生成
- FpF_pFp 上椭圆曲线公钥的验证
- SM2 加密算法
- SM2 解密算法
- Miracl大数运算库相关函数
- 程序代码
- 样例数据测试
- 注意事项
实验环境
Windows 10,Visual Studio 2019,Miracl大数库
预备知识
FpF_pFp 及椭圆曲线
素域 FpF_pFp
当 qqq 是奇素数 ppp 时,素域 FpF_pFp 中的元素用整数 0,1,2,⋯,p−10,1,2,⋯,p-10,1,2,⋯,p−1 表示。说明:
- 加法单位元是整数 000
- 乘法单位元是整数 111
- 域元素的加法是整数的模 ppp 加法,即若 a,b∈Fpa,b∈F_pa,b∈Fp ,则 a+b=(a+b)mod pa+b=(a+b) \text { mod } pa+b=(a+b) mod p ;
- 域元素的乘法是整数的模 ppp 乘法,即若 a,b∈Fpa,b∈F_pa,b∈Fp ,则 a+b=(a⋅b)mod pa+b=(a \cdot b) \text { mod } pa+b=(a⋅b) mod p 。
FpF_pFp 上的椭圆曲线
定义在 FpF_pFp ( ppp 是大于3的素数)上的椭圆曲线方程为:y2=x3+ax+by^2=x^3+ax+by2=x3+ax+b其中 a,b∈Fpa,b∈F_pa,b∈Fp ,且 (4a3+27b2)mod p≠0(4a^3+27b^2 )\text { mod } p≠0(4a3+27b2) mod p=0
椭圆曲线 E(Fp)E(F_p)E(Fp) 定义为:
E(Fp)={(x,y)│x,y∈Fp,且满足椭圆曲线方程}⋃{O}E(F_p )=\left\{ (x,y)│x,y∈F_p,\text {且满足椭圆曲线方程}\right\}⋃\left\{O\right\}E(Fp)={(x,y)│x,y∈Fp,且满足椭圆曲线方程}⋃{O},其中O是无穷远点
椭圆曲线E(Fp)E(F_p)E(Fp)上的点的数目用 #E(Fp)E(F_p)E(Fp) 表示,称为椭圆曲线 E(Fp)E(F_p)E(Fp) 的阶。
FpF_pFp 上椭圆曲线系统参数
FpF_pFp 上椭圆曲线系统参数包括:
- 域的规模 q=pq=pq=p,ppp 是大于3的素数;
- FpF_pFp 中的两个元素 aaa 和 bbb ,它们定义椭圆曲线 EEE 的方程: y2=x3+ax+by^2=x^3+ax+by2=x3+ax+b;
- 基点 G=(xG,yG)∈E(Fp),G≠OG=(x_G,y_G )∈E(F_p),G≠ΟG=(xG,yG)∈E(Fp),G=O;
- 基点 GGG 的阶 nnn ,要求:n>2191且 n>4p12n>2^{191} \text{ 且 }n>4p^\frac{1}{2}n>2191 且 n>4p21。
FpF_pFp 上椭圆曲线系统参数的验证
下面的条件应由椭圆曲线系统参数的生成者加以验证。椭圆曲线系统参数的用户可选择验证这些条件。
- 验证 q=pq=pq=p 是奇素数
- 验证 aaa、bbb、xGx_GxG 和 yGy_GyG 是区间 [0,p−1][0,p-1][0,p−1] 中的整数;
- 验证 (4a3+27b2)mod p≠0(4a^3+27b^2 ) \text { mod } p≠0(4a3+27b2) mod p=0;
- 验证 yG2≡xG3+axG+bmod py_G^2≡x_G^3+ax_G+b \text { mod } pyG2≡xG3+axG+b mod p;
- 验证 nnn 是素数,n>2191且 n>4p12n>2^{191} \text{ 且 }n>4p^\frac{1}{2}n>2191 且 n>4p21;
- 验证 [n]G=O[n]G=O[n]G=O。
SM2 公钥密码算法
密钥对的生成
- 用随机数生成器产生整数 d∈[1,n−2]d∈[1,n-2]d∈[1,n−2] ;
- GGG 为基点,计算点 P=(xP,yP)=[d]GP=(x_P,y_P )=[d]GP=(xP,yP)=[d]G ;
- 密钥对是 (d,P)(d,P)(d,P) ,其中 ddd 为私钥, PPP 为公钥。
FpF_pFp 上椭圆曲线公钥的验证
- 验证 PPP 不是无穷远点 OOO ;
- 验证公钥 PPP 的坐标 xPx_PxP 和 yPy_PyP 是域 FpF_pFp 中的元素;(即验证 xPx_PxP 和 yPy_PyP 是区间 [0,p−1][0,p-1][0,p−1] 中的整数。)
- 验证 yP2=xP3+ax+bmod p{y_P}^2={x_P}^3+ax+b \text { mod } pyP2=xP3+ax+b mod p ;
- 验证 [n]P=O[n]P=O[n]P=O 。
SM2 加密算法
设发送方是 A,A 要发送的消息表示成比特串 MMM ,MMM 的长度为 klenklenklen 。加密运算如下:
- 选择随机数 k∈[1,n−1]k∈[1,n-1]k∈[1,n−1] ;
- 计算椭圆曲线点 C1=[k]G=(x1,y1)C_1=[k]G=(x_1,y_1)C1=[k]G=(x1,y1) ,将 (x1,y1)(x_1,y_1)(x1,y1) 表示为比特串;
- 计算椭圆曲线点 S=[h]PBS=[h]P_BS=[h]PB ,若 SSS 是无穷远点,则报错并退出;
- 计算椭圆曲线点 [k]PB=(x2,y2)[k] P_B=(x_2,y_2)[k]PB=(x2,y2) ,将 (x2,y2)(x_2,y_2)(x2,y2) 表示为比特串;
- 计算 t=KDF(x2∥y2,klen)t=KDF(x_2∥y_2,klen)t=KDF(x2∥y2,klen) ,若 ttt 为全为 000 的比特串,则返回步骤1;
- 计算 C2=M⊕tC_2=M \oplus tC2=M⊕t ;
- 计算 C3=Hash(x2∥M∥y2)C_3=Hash(x_2∥M∥y_2)C3=Hash(x2∥M∥y2) ;
- 输出密文 C=(C1,C2,C3)C=(C_1,C_2,C_3 )C=(C1,C2,C3) 。
其中步骤5 KDF(·)是密钥派生函数,其本质上就是一个伪随机数产生函数,用来产生密钥,取为密码哈希函数 SM3。步骤7的Hash 函数也取为 SM3。
SM2 加密算法流程图如下:
SM2 解密算法
B收到密文后,执行以下解密运算:
- 从 CCC 中取出比特串 C1C_1C1 ,将 C1C_1C1 表示为椭圆曲线上的点,验证 C1C_1C1 是否满足椭圆曲线方程,若不满足则报错退出;
- 计算椭圆曲线点 S=[h]C1S=[h] C_1S=[h]C1 ,若 SSS 是无穷远点,则报错退出;
- 计算 [dB]C1=(x2,y2)[d_B ] C_1=(x_2,y_2 )[dB]C1=(x2,y2) ,将坐标 (x2,y2)(x_2,y_2)(x2,y2) 表示为比特串;
- 计算 t=KDF(x2∥y2,klen)t=KDF(x_2∥y_2,klen)t=KDF(x2∥y2,klen) ,若 ttt 为全 000 比特串,则报错并退出;
- 从 CCC 中取出比特串 C2C_2C2 ,计算 M’=C2⊕tM’=C_2⊕tM’=C2⊕t ;
- 计算 u=Hash(x2∥M’∥y2)u=Hash(x_2∥M’∥y_2 )u=Hash(x2∥M’∥y2) ,从 CCC 中取出 C3C_3C3 ,若 u≠C3u≠C_3u=C3 ,则报错并退出;
- 输出明文 M’M’M’ 。
SM2 解密算法流程图如下:
Miracl大数运算库相关函数
函数原型: miracl *mirsys(int nd, int nb);
功能说明: 初始化MIRACL系统,该函数必须在调用MIRACL库函数之前先执行
函数原型: void add(big x, big y, big z);
功能说明: 两个大数相加,z=x+y
函数原型: void bigrand(big w, big x);
功能说明: 使用内置的随机数发生器,产生一个小于w的大数随机数,x<w
函数原型: void copy(big x, big y);
功能说明: 将一个大数赋值给另一个大数,y=x
函数原型: int cotstr(big x, char *s);
功能说明: 将一个大数根据其进制转换成一个字符串
返回值: 字符串长度
函数原型: void incr(big x, int n, big z);
功能说明: 将一个大数加上一个整数, z=x+n
函数原型: void decr(big x, int n, big z) ;
功能说明: 将一个大数减去一个整数, z=x-n.
函数原型: void divide(big x, big y, big z);
功能说明: 两个大数相除,z=x/y; x=x mod y,当变量y和z相同时,x为余数,商不返回(即y的值不变);当x和z相同时,x为商,余数不返回。
函数原型: void multiply(big x, big y, big z);
功能说明: 两个大数相乘,z=xy
函数原型: void powmod(big x, big y,big z, big w);
功能说明: 模幂运算,w=x^y(mod z)
函数原型: int mr_compare(big x, big y);
功能说明: 比较两个大数的大小
返回值: x>y时返回+1, x=y时返回0, x<y时返回-1
函数原型: void sftbit(big x, int n, big z);
功能说明: 将一个大数左移或右移n位,n为正数时左移,负数时右移
函数原型: void mirexit();
功能说明: 清除MIRACL系统,释放所有内部变量
程序代码
因代码过长,源代码已上传Github代码仓库,克隆到本地后即可查看运行。
样例数据测试
选取如下英文文段作为测试明文
“The Little Prince is a novella by French aristocrat, writer.
It was first published in English and French in the US by Reynal & Hitchcock in April 1943.
The story follows a young prince who visits various planets in space, including Earth, and addresses themes of loneliness, friendship, love, and loss. Despite its style as a children’s book, The Little Prince makes observations about life and human nature.”
运行结果
可以看到,程序成功实现了对消息的加解密。
注意事项
源代码下载至本地无法直接运行,需在 Visual Studio 中对 Miracl 大数库进行相关配置。
Miracl 大数库编译及配置教程见 编译并使用Miracl大数运算库(使用Visual Studio 2019)
SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库)相关推荐
- 中国剩余定理(孙子定理)的算法实现(基于miracl大数运算库)
中国剩余定理(孙子定理)的算法实现: 一.实现目标: 根据中国剩余定理,设正整数两两互素,那么对于任意k个整数,同余方程组: 必有解,模的解数为1.方程组元素的传入是通过文本文件读入的,顺序是,,每个 ...
- 国密算法Go语言实现(详解)(九) ——SM2(椭圆曲线公钥密码算法)
国密算法Go语言实现(详解)(九) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...
- 国密算法Go语言实现(详解)(十) ——SM2(椭圆曲线公钥密码算法)
国密算法Go语言实现(详解)(十) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...
- SM2椭圆曲线公钥密码算法(Python实现)
本文目录 一.实验目的(包括实验环境.实现目标等等) 1. 实验环境 2. 实现目标 3. 实验中需要导入的库 二.方案设计(包括背景.原理.必要的公式.图表.算法步骤等等) 1. 实验背景 2. 实 ...
- GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法1
2021SC@SDUSC 一.相关术语以及定义 二.数字签名算法 1.辅助函数 密码杂凑算法和随机数发生器 杂凑运算:这个输出串称为该消息的杂凑值. 就是一种可将一个 key 对应到一个索引的函数,一 ...
- 12、SM2椭圆曲线公钥密码算法
参考推荐: 国家密码管理局关于发布<SM2椭圆曲线公钥密码算法>公告(国密局公告第21号)_国家密码管理局 https://blog.csdn.net/u013137970/article ...
- GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法4
2021SC@SDUSC 目录 一.ECDSA介绍 二.代码分析 一.ECDSA介绍 ECDSA的全名是Elliptic Curve DSA,即椭圆曲线DSA.它是Digital Signature ...
- SM2椭圆曲线公钥密码算法的JAVA实现
2019独角兽企业重金招聘Python工程师标准>>> package com.zpc.cryptography;import java.io.ByteArrayInputStrea ...
- GMSSL :SM2椭圆曲线公钥密码算法-密钥交换协议
2021SC@SDUSC 目录 一.整体架构 二.具体分析 前一篇文章写了密钥交换协议的基本流程,这一篇文章看一下代码实现 一.整体架构 整体来看这一部分有6个函数,相对重要的是序号3,4代表的函数 ...
最新文章
- 部署Chromedriver
- config database.php,CodeIgniter配置之database.php用法实例分析
- 如何编写更少,更好的代码,或Project Lombok
- python计算目录大小_使用Python计算目录的大小?
- 如何一边训练一遍验证
- 团体程序设计天梯赛-练习集-L1-046. 整除光棍
- 心酸血泪前端路,不断成长任我行,零碎知识点笔记(vue踩坑日记)
- 单片机实验计数显示器C语言代码,单片机 计数显示器实验报告
- C#50个经典小程序代码
- 区块链-超级账本Hyperledger-fabric初步认识
- 一个网游盗号木马的汇编源码分析
- BZOJ 2751: [HAOI2012]容易题(easy)( )
- GNSS/INS组合导航(1)-- 姿态矩阵
- QQ群78928780记录整理:90514技术话题-部分
- 反走崛起之路1:创新之西部——西雅图
- ansible dnf模块详解
- autocad2014点击保存闪退_cad2014闪退的原因和解决方法
- @Autowired的原理简识
- MacOS 的任务管理器
- 计算机辅助绘图考试题,CAD绘图员(往年考试题)练习题