C++调用openssl实现国标sm2签名算法的使用 您所在的位置:网站首页 数字签名验签报告怎么做 C++调用openssl实现国标sm2签名算法的使用

C++调用openssl实现国标sm2签名算法的使用

2024-07-10 05:43| 来源: 网络整理| 查看: 265

背景

SM2算法基于ECC椭圆曲线算法,广泛用于区块链、HTTPS 等需要非对称加密的场景。是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。

下面链接可以了解一些关于SM2的基础知识。

椭圆曲线加密算法(ECC)信息安全技术 SM2密码算法使用规范深入浅出讲解国密算法

在这里插入图片描述

可以看下知乎上这张图,一眼就可以看出SM1 SM2 SM3等和我们常见的国际加密算法的对应关系。

因为国产化原因,项目中需要使用国标sm2签名算法对文件进行签名和验签。OpenSSL 1.1.1版本提供了对国密SM2算法的支持,在之前的版本openssl不支持。

目前关于使用sm2算法,有两种做法,一种是采用开源库 gmssl。gmssl3已经脱离了openssl的依赖,现在是一个比较好的支持国密算法和ssl协议的三方库。

关于gmssl的使用可以参考它的源码链接,还是比较简单的。

https://gitee.com/mirrors/GmSSL国密SSL实验室

第二种是本文的做法,使用openssl1.1.1版本中的sm2的支持。

核心代码 #pragma once #include class Sm2Helper { public: /** * @brief 生成sm2密钥 * @param [IN] privKeyfilePath 私钥文件的完整存储路径(包含文件名),函数内部会将私钥内容写入文件 * @param [IN] pubKeyfilePath 公钥文件的完整存储路径(包含文件名),函数内部会将公钥内容写入文件 */ static bool sm2genKey(SM2_KEY_PAIR& key_pair, const std::string& privKeyfilePath, const std::string& pubKeyfilePath); /** * @brief 用私钥和公钥对文件进行签名 * @param [IN] user_id 在同一套密钥下,可以对同一个文件用不同的user_id 生成不同的签名文件 * @param [IN] msgDigest 要签名文件的摘要信息,一般可以使用文件的md5或者SM3摘要信息(具体使用哪种规则用户可以自定义,但是注意签名和验签要采用相同的方法计算摘要) * @param [IN] msgDigest_len 摘要信息字符串长度 * @param [IN] privKeyfilePath 私钥文件 * @param [IN] pubKeyfilePath 公钥文件 * @param [OUT] sm2_sig 生成的签名信息(r||s)64字节 * @param [IN] sigfilePath 生成的签名文件,函数内部会将签名信息写入文件 */ static bool sm2signWithFile(const std::string& user_id, const unsigned char* msgDigest, const int msgDigest_len, const std::string& privKeyfilePath, const std::string& pubKeyfilePath, SM2_SIGNATURE_STRUCT& sm2_sig, const std::string& sigfilePath); /** * @brief 用公钥对文件进行签名验证 * @param [IN] user_id 在同一套密钥下,可以对同一个文件用不同的user_id 生成不同的签名文件 * @param [IN] pubKeyfilePath 公钥文件 * @param [IN] msgDigest 待验证文件的摘要信息,一般可以使用文件的md5或者SM3摘要信息(具体使用哪种规则用户可以自定义,但是注意验签和签名要采用相同的方法计算摘要) * @param [IN] msgDigest_len 摘要信息字符串长度 * @param [IN] sigFilePath 签名文件 */ static bool sm2VerifyWithFile(const std::string& user_id, const std::string& pubKeyfilePath, const unsigned char* verifyMsgDigest, const int verifyMsgDigest_len, const std::string& sigFilePath); }; #include #include #include #include #include #include #include #include "sm2_create_key_pair.h" #include "sm2_sign_and_verify.h" #include "sm2helper.h" bool Sm2Helper::sm2genKey(SM2_KEY_PAIR& key_pair, const std::string& privKeyfilePath, const std::string& pubKeyfilePath) { if (0 != sm2_create_key_pair(&key_pair)) { qWarning("Create SM2 key pair failed!\n"); return false; } FILE* fd_key_priv = fopen(privKeyfilePath.data(), "wb+"); if (nullptr == fd_key_priv) { qWarning("create file %s failed.\n", privKeyfilePath.data()); return false; } size_t ret_size = fwrite(key_pair.pri_key, sizeof(unsigned char), PRIVATE_KEY_SIZE, fd_key_priv); fclose(fd_key_priv); if (ret_size != PRIVATE_KEY_SIZE) { qWarning("write private key to file %s error.\n", privKeyfilePath.data()); return false; } FILE* fd_key_pub = fopen(pubKeyfilePath.data(), "wb+"); if (nullptr == fd_key_pub) { qWarning("create file %s failed.\n", pubKeyfilePath.data()); return false; } ret_size = fwrite(key_pair.pub_key, sizeof(unsigned char), PUBLIC_KEY_SIZE, fd_key_pub); fclose(fd_key_pub); if (ret_size != PUBLIC_KEY_SIZE) { qWarning("write public key to file %s error.\n", pubKeyfilePath.data()); return false; } qDebug("writing key to file OK.\n"); return true; } bool Sm2Helper::sm2signWithFile(const std::string& user_id, const unsigned char* msgDigest, const int msgDigest_len, const std::string& privKeyfilePath, const std::string& pubKeyfilePath, SM2_SIGNATURE_STRUCT& sm2_sig, const std::string& sigfilePath) { SM2_KEY_PAIR key_pair; FILE* fd_key_priv = fopen(privKeyfilePath.data(), "rb+"); if (nullptr == fd_key_priv) { qDebug("read file %s failed.\n", privKeyfilePath.data()); return false; } size_t ret_size = fread(key_pair.pri_key, sizeof(unsigned char), PRIVATE_KEY_SIZE, fd_key_priv); fclose(fd_key_priv); if (ret_size != PRIVATE_KEY_SIZE) { qDebug("read private key error.\n"); return false; } FILE* fd_key_pub = fopen(pubKeyfilePath.data(), "rb+"); if (nullptr == fd_key_pub) { qDebug("read file %s failed.\n", pubKeyfilePath.data()); return false; } ret_size = fread(key_pair.pub_key, sizeof(unsigned char), PUBLIC_KEY_SIZE, fd_key_pub); fclose(fd_key_pub); if (ret_size != PUBLIC_KEY_SIZE) { qDebug("read public key error.\n"); return false; } if (0 != sm2_sign_data(msgDigest, msgDigest_len, reinterpret_cast (user_id.data()), user_id.length(), key_pair.pub_key, key_pair.pri_key, &sm2_sig) ) { qWarning("Create SM2 signature failed!\n"); return false; } FILE* fd_sig = fopen(sigfilePath.data(), "wb+"); if (nullptr == fd_sig) { qDebug("read file %s failed.\n", sigfilePath.data()); return false; } ret_size = fwrite(sm2_sig.r_coordinate, sizeof(unsigned char), SIGFILE_HALF_R_SIZE, fd_sig); if (ret_size != SIGFILE_HALF_R_SIZE) { qDebug("create image signature file (%s)--r_coordinate error.\n", sigfilePath.data()); fclose(fd_sig); return false; } ret_size = fwrite(sm2_sig.s_coordinate, sizeof(unsigned char), SIGFILE_HALF_S_SIZE, fd_sig); fclose(fd_sig); if (ret_size != SIGFILE_HALF_S_SIZE) { qDebug("create image signature file (%s)--s_coordinate error.\n", sigfilePath.data()); return false; } return true; } bool Sm2Helper::sm2VerifyWithFile(const std::string& user_id, const std::string& pubKeyfilePath, const unsigned char* verifyMsgDigest, const int verifyMsgDigest_len, const std::string& sigFilePath) { SM2_SIGNATURE_STRUCT sm2_sig2; unsigned char pub[PUBLIC_KEY_SIZE] = {0}; FILE* fd_key_pub = fopen(pubKeyfilePath.data(), "rb+"); if (nullptr == fd_key_pub) { qDebug("read file %s failed.\n", pubKeyfilePath.data()); return false; } size_t ret_size = fread(pub, sizeof(unsigned char), PUBLIC_KEY_SIZE, fd_key_pub); fclose(fd_key_pub); if (ret_size != PUBLIC_KEY_SIZE) { qDebug("read public key error.\n"); return false; } FILE* fd_sig = fopen(sigFilePath.data(), "rb+"); if (nullptr == fd_sig) { qDebug("read file %s failed.\n", sigFilePath.data()); return false; } ret_size = fread(sm2_sig2.r_coordinate, sizeof(unsigned char), SIGFILE_HALF_R_SIZE, fd_sig); if (ret_size != SIGFILE_HALF_R_SIZE) { qDebug("read sig file: %s error.\n", sigFilePath.data()); fclose(fd_sig); return false; } ret_size = fread(sm2_sig2.s_coordinate, sizeof(unsigned char), SIGFILE_HALF_S_SIZE, fd_sig); fclose(fd_sig); if (ret_size != SIGFILE_HALF_S_SIZE) { qDebug("read sig file: %s error.\n", sigFilePath.data()); return false; } int error_code = sm2_verify_sig(verifyMsgDigest, verifyMsgDigest_len, reinterpret_cast (user_id.data()), user_id.length(), pub, &sm2_sig2); if (0 != error_code) { qDebug("Verify SM2 signature failed!\n"); return false; } qDebug("Verify SM2 signature succeeded!\n"); return true; }

详细解释可以看代码注释。

其他代码我打包上传到csdn资源中,关注公号后在后台留言需要下载的资源,我看到后免费发给你,并可以得到我的免费解答。 原创不易,谢谢支持。

下载地址:https://download.csdn.net/download/u012534831/88628411

关注公众号 QTShared,带你探索更多QT相关知识。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有