SM9算法C++实现系列目录:

  • 基于JPBC的SM9算法的java实现与测试

  • 国密SM9算法C++实现之0:源码下载地址

  • 国密SM9算法C++实现之一:算法简介

  • 国密SM9算法C++实现之二:测试工具

  • 国密SM9算法C++实现之三:椭圆曲线接口、参数初始化

  • 国密SM9算法C++实现之四:基本功能函数与KGC接口的实现

  • 国密SM9算法C++实现之五:签名验签算法

  • 国密SM9算法C++实现之六:密钥封装解封算法

  • 国密SM9算法C++实现之七:加密解密算法

  • 国密SM9算法C++实现之八:密钥交换算法

  • 国密SM9算法C++实现之九:算法功能与测试例子

国密SM9算法C++实现之五:签名验签算法

文章目录

  • 国密SM9算法C++实现之五:签名验签算法
    • @[toc]
    • 签名算法流程
      • 签名值
        • Signature.h
      • 签名算法实现
    • 验签算法流程
      • 验签算法实现

实现完KGC部分后,可以开始实现SM9算法部分。本篇描述签名验签算法的实现。

签名算法流程

SM9标准文档中描述的签名算法流程如下所示:

其流程图为:

根据算法描述,定义接口函数:

 /** * 签名* * @param masterPublicKey 签名主公钥* @param prikey 用户签名私钥* @param data 待签数据* @return 签名值* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE*/static Signature sign(const string& masterPublicKey, const string& prikey, const string& data);

签名值

SM9签名结果包括h和S两个部分,对此,也简单将其封装为一个类。

Signature.h


#ifndef YY_SM9_SIGNATURE_INCLUDE_H__
#define YY_SM9_SIGNATURE_INCLUDE_H__#pragma once#include <string>using namespace std;/**
* 签名值.
* @author YaoYuan
*/
class Signature {
public:Signature() {}Signature(const string& h, const string& s) {mH = h;mS = s;}~Signature() {}public:string getH() const { return mH; }string getS() const { return mS; }private:string mH;string mS;
};#endif

签名算法实现

按照签名流程,实现签名算法:


Signature SM9::sign(const string& masterPublicKey, const string& prikey, const string& data)
{Signature signature;bool hasException = true;string h, s, sw;ecn2 Ppubs;epoint* dsa = NULL;epoint* S = NULL;ZZN12 g;ZZN12 w;big h2 = NULL;big r = NULL;big l = NULL;big tmp = NULL;big zero = NULL;#ifdef SELF_CHECKstring gHex, rHex, wHex, h2Hex;
#endifif( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}Parameters::init_ecn2(Ppubs);Parameters::init_big(h2);Parameters::init_big(r);Parameters::init_big(l);Parameters::init_big(tmp);Parameters::init_big(zero);Parameters::init_epoint(dsa);Parameters::init_epoint(S);// Step1 : g = e(P1, Ppub-s)Parameters::cin_ecn2_byte128(Ppubs, masterPublicKey.c_str());if( !ZZN12::calcRatePairing(g, Ppubs, Parameters::param_P1, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());
#endifwhile( true ) {
#ifdef SELF_CHECKrHex = YY::YHex::hex2bin("033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE");Parameters::cin_big(r, rHex.c_str(), rHex.length());
#else// Step2: generate rbigrand(Parameters::param_N, r);
#endif// Step3 : calculate w=g^rw = g.pow(r);sw = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sw);
#endif// Step4 : calculate h=H2(M||w,N)h = KGC::H2(data, sw);Parameters::cin_big(h2, h.c_str(), h.length());#ifdef SELF_CHECKh2Hex = YY::YHex::bin2Hex(h);
#endif// Step5 : l=(r-h)mod Nsubtract(r, h2, l);divide(l, Parameters::param_N, tmp);while( mr_compare(l, zero) < 0 )add(l, Parameters::param_N, l);if( mr_compare(l, zero) != 0 )break;}// Step6 : S=[l]dSA=(xS,yS)Parameters::cin_epoint(dsa, prikey.c_str());ecurve_mult(l, dsa, S);s = Parameters::cout_epoint(S);// Step7 : signature=(h,s)signature = Signature(h, s);hasException = false;END:Parameters::release_epoint(dsa);Parameters::release_epoint(S);Parameters::release_ecn2(Ppubs);Parameters::release_big(h2);Parameters::release_big(r);Parameters::release_big(l);Parameters::release_big(tmp);Parameters::release_big(zero);if( hasException ) {throw exception(getErrorMsg().c_str());}return signature;
}

验签算法流程

SM9标准文档中描述的验签算法流程如下所示:

其流程为:

根据算法描述,定义接口函数:

 /*** 验签** @param masterPublicKey 签名主公钥* @param prikey 用户ID* @param signature 签名值* @param data 待签数据* @return true-验签成功;false-验签失败* @throw std::exception SM9_ERROR_NOT_INIT | SM9_ERROR_CALC_RATE | * SM9_ERROR_VERIFY_H_OUTRANGE | SM9_ERROR_VERIFY_S_NOT_ON_G1 | SM9_ERROR_VERIFY_H_VERIFY_FAILED*/static bool verify(const string& masterPublicKey, const string& id, const Signature& signature, const string& data);

接口中没有必要提供hid,对于验签算法来说,这是确定的。

验签算法实现


bool SM9::verify(const string& masterPublicKey, const string& id, const Signature& signature, const string& data)
{bool result = false;bool hasException = true;big NSub1 = NULL;big one = NULL;big h = NULL;epoint* S = NULL;ecn2 Ppubs;ecn2 P;ZZN12 g;ZZN12 t;ZZN12 u;ZZN12 w;big h1 = NULL;string sH1, sH2, sw, sH, sS;if( !mIsInit ) {mErrorNum = SM9_ERROR_NOT_INIT;throw exception(getErrorMsg().c_str());}sH = signature.getH();sS = signature.getS();#ifdef SELF_CHECKstring gHex, rHex, h1Hex, tHex, pHex, uHex, wHex;
#endifParameters::init_big(NSub1);Parameters::init_big(one);Parameters::init_big(h);Parameters::init_epoint(S);Parameters::init_ecn2(Ppubs);Parameters::init_ecn2(P);Parameters::init_big(h1);// Step1 : check if h in the range [1, N-1]decr(Parameters::param_N, 1, NSub1);convert(1, one);Parameters::cin_big(h, sH.c_str(), sH.length());if( (mr_compare(h, one) < 0) | (mr_compare(h, NSub1) > 0) ) {mErrorNum = SM9_ERROR_VERIFY_H_OUTRANGE;goto END;}// Step2 : check if S is on G1Parameters::cin_epoint(S, sS.c_str());if( !Parameters::isPointOnG1(S) ) {mErrorNum = SM9_ERROR_VERIFY_S_NOT_ON_G1;goto END;}// Step3 : g = e(P1, Ppub-s)Parameters::cin_ecn2_byte128(Ppubs, masterPublicKey.c_str());if( !ZZN12::calcRatePairing(g, Ppubs, Parameters::param_P1, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKgHex = YY::YHex::bin2Hex(g.toByteArray());
#endif// Step4 : calculate t=g^ht = g.pow(h);#ifdef SELF_CHECKtHex = YY::YHex::bin2Hex(t.toByteArray());
#endif// Step5 : calculate h1=H1(IDA||hid,N)sH1 = KGC::H1(id, HID_SIGN);Parameters::cin_big(h1, sH1.c_str(), sH1.length());#ifdef SELF_CHECKh1Hex = YY::YHex::bin2Hex(sH1);
#endif// Step6 : P=[h1]P2+Ppubsecn2_copy(&Parameters::param_P2, &P);ecn2_mul(h1, &P);ecn2_add(&Ppubs, &P);ecn2_norm(&P);#ifdef SELF_CHECKpHex = YY::YHex::bin2Hex(Parameters::cout_ecn2(P));
#endif// Step7 : u=e(S,P)if( !ZZN12::calcRatePairing(u, P, S, Parameters::param_t, Parameters::norm_X) ) {mErrorNum = SM9_ERROR_CALC_RATE;goto END;}#ifdef SELF_CHECKuHex = YY::YHex::bin2Hex(u.toByteArray());
#endif// Step8 : w=u*tw = u.mul(t);sw = w.toByteArray();#ifdef SELF_CHECKwHex = YY::YHex::bin2Hex(sw);
#endif// Step9 : h2=H2(M||w,N)sH2 = KGC::H2(data, sw);if( sH2.compare(sH) == 0 ) {result = true;}  else {mErrorNum = SM9_ERROR_VERIFY_H_VERIFY_FAILED;}hasException = false;
END:Parameters::release_big(NSub1);Parameters::release_big(one);Parameters::release_big(h);Parameters::release_epoint(S);Parameters::release_ecn2(Ppubs);Parameters::release_ecn2(P);Parameters::release_big(h1);if( hasException ) {throw exception(getErrorMsg().c_str());}return result;
}

由于验签函数返回类型是bool,因此验签失败后,可以通过getErrorMsg获取错误信息。

国密SM9算法C++实现之五:签名验签算法相关推荐

  1. php pkcs7签名验签算法,OpenSSL 签名验签接口调用及测试

    OpenSSL 签名验签接口调用及测试 概述 项目中我们经常会遇到开发签名.验签功能.签名.验签是可信赖网络的一个重要功能.因此,我记录了OpenSSL 签名验签接口调用及测试. 相关测试代码 bas ...

  2. C语言——基于OpenSSL 的RSA 签名验签算法

    OpenSSL开源工程中,实现RSA签名方法有多种.该方法基于OpenSSL 3.0版本,调用OpenSSL EVP层的EVP_DigestSign*()与EVP_DigestVerify*()实现p ...

  3. gmssl国密sm2(生成密钥对-私钥签字-证书验签)

    生成密钥对: #include <stdio.h> #include <string.h> #include <stdlib.h> #include "e ...

  4. 国密SM9算法C++实现之一:算法简介

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  5. 国密SM9算法C++实现之八:密钥交换算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  6. 国密SM9算法C++实现之七:加密解密算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  7. 国密SM9算法C++实现之九:算法功能与测试例子

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  8. 国密SM9算法C++实现之六:密钥封装解封算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

  9. 国密SM9算法C++实现之三:椭圆曲线接口、参数初始化

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

最新文章

  1. Nginx+Tomcat出现session丢失问题
  2. SAP APO 介绍
  3. 软件测试工作常用linux命令,软件测试工程师工作中常用的Linux命令
  4. oracle 修索引改空间_Oracle如何更改表空间的数据文件位置详解
  5. spring 动态代理_分析动态代理给 Spring 事务埋下的坑
  6. PaddlePaddle中数据的基本操作
  7. 让我们了解下什么是智能客服(问答)
  8. 谈谈主策划需要的能力
  9. Unity粒子系统——简易特效制作(一)
  10. 计数器代码php,php的计数器程序_php
  11. G480改装固态硬盘、光驱变机械硬盘以及装系统(下)
  12. 特征选择:python lime
  13. AtCoder Beginner Contest 164 E Two Currencies Bellman-Ford优化思想+01背包+动归dp状态转移
  14. 计算机模拟电子云密度,小知识:分子动力学基本原理及应用
  15. RTC实时时钟(学习笔记)
  16. 全球人造丝卫生棉条行业调研及趋势分析报告
  17. [转载]删除微软拼音输入法
  18. Hidden Message
  19. wps word文档生成目录的时候显示断裂会生成大纲怎么办_自从学会了Word自动排版,我的秀发浓密多了...
  20. 获取沪深300成分股单日收盘价

热门文章

  1. ubuntu 搭建mysql环境_docker 搭建ubuntu+mysql环境教程
  2. [开心IT面试题] 封闭的房间中,如何判断三盏灯是由哪个开关控制?
  3. 老毛桃WinPE以ISO镜像模式安装CentOS7
  4. 1w存银行一年多少利息_如果你有1000万存入银行,一年能有多少利息?刺激!
  5. AndroidUI图片图标素材大全
  6. 如何克服解决Git冲突的恐惧症?(Git基础篇--上)
  7. 用计算器实现主机字节序与网络字节序之间转换
  8. vs2013 连接 海马玩模拟器
  9. 元宇宙能成为下一个互联网吗?
  10. 剑指offer笔记(七)从尾到头打印链表