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 表示。说明:

  1. 加法单位元是整数 000
  2. 乘法单位元是整数 111
  3. 域元素的加法是整数的模 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 ;
  4. 域元素的乘法是整数的模 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​ 上椭圆曲线系统参数包括:

  1. 域的规模 q=pq=pq=p,ppp 是大于3的素数;
  2. FpF_pFp​ 中的两个元素 aaa 和 bbb ,它们定义椭圆曲线 EEE 的方程: y2=x3+ax+by^2=x^3+ax+by2=x3+ax+b;
  3. 基点 G=(xG,yG)∈E(Fp),G≠OG=(x_G,y_G )∈E(F_p),G≠ΟG=(xG​,yG​)∈E(Fp​),G​=O;
  4. 基点 GGG 的阶 nnn ,要求:n>2191且 n>4p12n>2^{191} \text{ 且 }n>4p^\frac{1}{2}n>2191 且 n>4p21​。

FpF_pFp​ 上椭圆曲线系统参数的验证

下面的条件应由椭圆曲线系统参数的生成者加以验证。椭圆曲线系统参数的用户可选择验证这些条件。

  1. 验证 q=pq=pq=p 是奇素数
  2. 验证 aaa、bbb、xGx_GxG​ 和 yGy_GyG​ 是区间 [0,p−1][0,p-1][0,p−1] 中的整数;
  3. 验证 (4a3+27b2)mod p≠0(4a^3+27b^2 ) \text { mod } p≠0(4a3+27b2) mod p​=0;
  4. 验证 yG2≡xG3+axG+bmod py_G^2≡x_G^3+ax_G+b \text { mod } pyG2​≡xG3​+axG​+b mod p;
  5. 验证 nnn 是素数,n>2191且 n>4p12n>2^{191} \text{ 且 }n>4p^\frac{1}{2}n>2191 且 n>4p21​;
  6. 验证 [n]G=O[n]G=O[n]G=O。

SM2 公钥密码算法

密钥对的生成

  1. 用随机数生成器产生整数 d∈[1,n−2]d∈[1,n-2]d∈[1,n−2] ;
  2. GGG 为基点,计算点 P=(xP,yP)=[d]GP=(x_P,y_P )=[d]GP=(xP​,yP​)=[d]G ;
  3. 密钥对是 (d,P)(d,P)(d,P) ,其中 ddd 为私钥, PPP 为公钥。

FpF_pFp​ 上椭圆曲线公钥的验证

  1. 验证 PPP 不是无穷远点 OOO ;
  2. 验证公钥 PPP 的坐标 xPx_PxP​ 和 yPy_PyP​ 是域 FpF_pFp​ 中的元素;(即验证 xPx_PxP​ 和 yPy_PyP​ 是区间 [0,p−1][0,p-1][0,p−1] 中的整数。)
  3. 验证 yP2=xP3+ax+bmod p{y_P}^2={x_P}^3+ax+b \text { mod } pyP​2=xP​3+ax+b mod p ;
  4. 验证 [n]P=O[n]P=O[n]P=O 。

SM2 加密算法

设发送方是 A,A 要发送的消息表示成比特串 MMM ,MMM 的长度为 klenklenklen 。加密运算如下:

  1. 选择随机数 k∈[1,n−1]k∈[1,n-1]k∈[1,n−1] ;
  2. 计算椭圆曲线点 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​) 表示为比特串;
  3. 计算椭圆曲线点 S=[h]PBS=[h]P_BS=[h]PB​ ,若 SSS 是无穷远点,则报错并退出;
  4. 计算椭圆曲线点 [k]PB=(x2,y2)[k] P_B=(x_2,y_2)[k]PB​=(x2​,y2​) ,将 (x2,y2)(x_2,y_2)(x2​,y2​) 表示为比特串;
  5. 计算 t=KDF(x2∥y2,klen)t=KDF(x_2∥y_2,klen)t=KDF(x2​∥y2​,klen) ,若 ttt 为全为 000 的比特串,则返回步骤1;
  6. 计算 C2=M⊕tC_2=M \oplus tC2​=M⊕t ;
  7. 计算 C3=Hash(x2∥M∥y2)C_3=Hash(x_2∥M∥y_2)C3​=Hash(x2​∥M∥y2​) ;
  8. 输出密文 C=(C1,C2,C3)C=(C_1,C_2,C_3 )C=(C1​,C2​,C3​) 。

其中步骤5 KDF(·)是密钥派生函数,其本质上就是一个伪随机数产生函数,用来产生密钥,取为密码哈希函数 SM3。步骤7的Hash 函数也取为 SM3。

SM2 加密算法流程图如下:

SM2 解密算法

B收到密文后,执行以下解密运算:

  1. 从 CCC 中取出比特串 C1C_1C1​ ,将 C1C_1C1​ 表示为椭圆曲线上的点,验证 C1C_1C1​ 是否满足椭圆曲线方程,若不满足则报错退出;
  2. 计算椭圆曲线点 S=[h]C1S=[h] C_1S=[h]C1​ ,若 SSS 是无穷远点,则报错退出;
  3. 计算 [dB]C1=(x2,y2)[d_B ] C_1=(x_2,y_2 )[dB​]C1​=(x2​,y2​) ,将坐标 (x2,y2)(x_2,y_2)(x2​,y2​) 表示为比特串;
  4. 计算 t=KDF(x2∥y2,klen)t=KDF(x_2∥y_2,klen)t=KDF(x2​∥y2​,klen) ,若 ttt 为全 000 比特串,则报错并退出;
  5. 从 CCC 中取出比特串 C2C_2C2​ ,计算 M’=C2⊕tM’=C_2⊕tM’=C2​⊕t ;
  6. 计算 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​ ,则报错并退出;
  7. 输出明文 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大数运算库)相关推荐

  1. 中国剩余定理(孙子定理)的算法实现(基于miracl大数运算库)

    中国剩余定理(孙子定理)的算法实现: 一.实现目标: 根据中国剩余定理,设正整数两两互素,那么对于任意k个整数,同余方程组: 必有解,模的解数为1.方程组元素的传入是通过文本文件读入的,顺序是,,每个 ...

  2. 国密算法Go语言实现(详解)(九) ——SM2(椭圆曲线公钥密码算法)

    国密算法Go语言实现(详解)(九) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...

  3. 国密算法Go语言实现(详解)(十) ——SM2(椭圆曲线公钥密码算法)

    国密算法Go语言实现(详解)(十) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...

  4. SM2椭圆曲线公钥密码算法(Python实现)

    本文目录 一.实验目的(包括实验环境.实现目标等等) 1. 实验环境 2. 实现目标 3. 实验中需要导入的库 二.方案设计(包括背景.原理.必要的公式.图表.算法步骤等等) 1. 实验背景 2. 实 ...

  5. GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法1

    2021SC@SDUSC 一.相关术语以及定义 二.数字签名算法 1.辅助函数 密码杂凑算法和随机数发生器 杂凑运算:这个输出串称为该消息的杂凑值. 就是一种可将一个 key 对应到一个索引的函数,一 ...

  6. 12、SM2椭圆曲线公钥密码算法

    参考推荐: 国家密码管理局关于发布<SM2椭圆曲线公钥密码算法>公告(国密局公告第21号)_国家密码管理局 https://blog.csdn.net/u013137970/article ...

  7. GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法4

    2021SC@SDUSC 目录 一.ECDSA介绍 二.代码分析 一.ECDSA介绍 ECDSA的全名是Elliptic Curve DSA,即椭圆曲线DSA.它是Digital Signature ...

  8. SM2椭圆曲线公钥密码算法的JAVA实现

    2019独角兽企业重金招聘Python工程师标准>>> package com.zpc.cryptography;import java.io.ByteArrayInputStrea ...

  9. GMSSL :SM2椭圆曲线公钥密码算法-密钥交换协议

    2021SC@SDUSC 目录 一.整体架构 二.具体分析 前一篇文章写了密钥交换协议的基本流程,这一篇文章看一下代码实现 一.整体架构 整体来看这一部分有6个函数,相对重要的是序号3,4代表的函数 ...

最新文章

  1. 部署Chromedriver
  2. config database.php,CodeIgniter配置之database.php用法实例分析
  3. 如何编写更少,更好的代码,或Project Lombok
  4. python计算目录大小_使用Python计算目录的大小?
  5. 如何一边训练一遍验证
  6. 团体程序设计天梯赛-练习集-L1-046. 整除光棍
  7. 心酸血泪前端路,不断成长任我行,零碎知识点笔记(vue踩坑日记)
  8. 单片机实验计数显示器C语言代码,单片机 计数显示器实验报告
  9. C#50个经典小程序代码
  10. 区块链-超级账本Hyperledger-fabric初步认识
  11. 一个网游盗号木马的汇编源码分析
  12. BZOJ 2751: [HAOI2012]容易题(easy)( )
  13. GNSS/INS组合导航(1)-- 姿态矩阵
  14. QQ群78928780记录整理:90514技术话题-部分
  15. 反走崛起之路1:创新之西部——西雅图
  16. ansible dnf模块详解
  17. autocad2014点击保存闪退_cad2014闪退的原因和解决方法
  18. @Autowired的原理简识
  19. MacOS 的任务管理器
  20. 计算机辅助绘图考试题,CAD绘图员(往年考试题)练习题

热门文章

  1. freebsd 安装php,FreeBSD下安装PHP5
  2. Fedora 20 上安装基于dell 1420的无线网卡驱动
  3. java字符串统计英文字符用什么不同_Java-统计字符串中英文单词总数
  4. 赶紧收藏!考博英语听力中常见的俚语分析
  5. 红帽RHCE之软硬链接
  6. python trutle画五星红旗
  7. 一个怂怂的女生的想法
  8. TDA4VM 软件诊断库(SDL)- J721E用户指南
  9. JS 获取 未来时间
  10. osgi Quick Start