赞
踩
SM2算法基于ECC椭圆曲线算法,广泛用于区块链、HTTPS 等需要非对称加密的场景。是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。
下面链接可以了解一些关于SM2的基础知识。
可以看下知乎上这张图,一眼就可以看出SM1 SM2 SM3等和我们常见的国际加密算法的对应关系。
因为国产化原因,项目中需要使用国标sm2签名算法对文件进行签名和验签。OpenSSL 1.1.1版本提供了对国密SM2算法的支持,在之前的版本openssl不支持。
目前关于使用sm2算法,有两种做法,一种是采用开源库 gmssl。gmssl3已经脱离了openssl的依赖,现在是一个比较好的支持国密算法和ssl协议的三方库。
关于gmssl的使用可以参考它的源码链接,还是比较简单的。
第二种是本文的做法,使用openssl1.1.1版本中的sm2的支持。
#pragma once #include <string> 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 <QDebug> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #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<const unsigned char* > (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<const unsigned char*> (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 © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。