基于 gmssl实现的sm2加密(C++)

您所在的位置:网站首页 bio数据 基于 gmssl实现的sm2加密(C++)

基于 gmssl实现的sm2加密(C++)

#基于 gmssl实现的sm2加密(C++)| 来源: 网络整理| 查看: 265

项目中需要用到sm2加密,在网上搜索了一下相关的库,发现只有openssl和gmssl这两个库可以用,于是基于gmssl库做了封装,gmssl的版本是:GmSSL 2.5.4 - OpenSSL 1.1.0d  19 Jun 2019

搞这个库的确要费不少功夫,现在分享出来给需要的人。目前我是用在linux环境中,因此编译成linux动态库,并且屏蔽相关库的头文件和符号,只暴露sm2加解密相关的接口符号,gmssl库通过静态库的方式引用。

关于sm2加密有几个比较重要的参数,第一个是椭圆曲线参数,第二个是密文编码方式,第三个是哈希算法,目前我们用的都是固定的参数,所以封装的时候没有提供参数选择这些功能,需要的可以自行扩展。下面的sm2加密相关参数为:使用默认的椭圆曲线参数(sm2p256v1),ASN.1/DER编码方式(C1|C3|C2编码方式) ,哈希(杂凑)算法使用sm3

一些初学者可能还不大懂怎么引用外部库,我把我自己的工程上传到github上了,可以作为参考,gmssl库我已经编译好,生成的是静态库,但是gmssl库的编译其实还是应该用自己的机器去编译的,因为自己拿我编译好的静态库去用的话,不同的linux版本有可能不兼容。gmssl库文件我也放在该工程下了,可以不用去官网找,文件为:GmSSL-master.zip。 github地址:qingfeng1992/gmutil: 基于gmssl加密库封装sm2加解密方法 (github.com)

可以直接使用git clone [email protected]:qingfeng1992/gmutil.git 拉取代码

下载下来后请先看README.txt后再操作

gmutil.h头文件:

#ifndef __GM_UTIL_H__ #define __GM_UTIL_H__ #include using namespace std; #ifdef _WIN32 #define UNIX_EXPORT #else #define UNIX_EXPORT __attribute__((visibility("default"))) #endif // namespace GM //{ // 错误码 enum EGMErrorCode { GM_UTIL_CODE_OK = 0, GM_UTIL_CODE_CREATE_EV_KEY_FAILED, // 密钥解析失败 GM_UTIL_CODE_SM2_ENCRYPT_FAILED, // SM2加密失败 GM_UTIL_CODE_SM2_DECRYPT_FAILED, // SM2解密失败 GM_UTIL_CODE_NOT_SM2P256V1, // 不是默认的sm2p256v1椭圆曲线参数 GM_UTIL_CODE_INIT_BIO_FAILED, // 初始化BIO失败 GM_UTIL_CODE_CIPHER_TEXT_TO_BIO_FAILED, // 加密数据存储到BIO失败 GM_UTIL_CODE_BIO_DATA_TO_MEM_FAILED, // BIO数据转存到缓冲区失败 GM_UTIL_CODE_BIO_DATA_TO_CIPHER_TEXT_FAILED, // BIO数据转成Ciphertext结构失败 }; extern "C" { // 从文件中读入公钥/私钥数据到string中,失败返回空字符串 UNIX_EXPORT string GmReadKeyFromFile(string strFileName); /** * @brief sm2加密,使用默认的椭圆曲线参数(NID_sm2p256v1),ASN.1/DER编码方式(C1|C3|C2编码方式) ,哈希(杂凑)算法使用sm3 * @param strPubKey 公钥数据 * @param strIn 需要加密的数据 * @param strCiphertext 密文,加密后的密文不是可见字符 * @return 返回GM_UTIL_ERR_OK表示加密成功,否则失败,具体见EGMErrorCode定义 */ UNIX_EXPORT int GmSm2Encrypt(string strPubKey, const string &strIn, string &strCiphertext); /** * @brief sm2解密,使用默认的椭圆曲线参数(NID_sm2p256v1),ASN.1/DER编码方式(C1|C3|C2编码方式),哈希(杂凑)算法使用sm3 * @param strPubKeyFile 私钥数据 * @param strCiphertext 需要解密的数据(不是可见字符) * @param strOut 解密后的明文 * @return 返回GM_UTIL_ERR_OK表示解密成功,否则失败,具体见EGMErrorCode定义 */ UNIX_EXPORT int GmSm2Decrypt(string strPriKey, const string &strCiphertext, string &strOut); // 将二进制数据转换成十六进制字符串 UNIX_EXPORT string GmByte2HexStr(const string &data, bool bLowerCase = true); // 将十六进制字符串转换成二进制 UNIX_EXPORT string GmHexStr2Byte(const string& hex, bool bLowerCase = true); } // } // namespace GM #endif // end __GM_UTIL_H__

gmutil.cpp文件:

#include "gmutil.h" #include #include #include #include #include #include #include #include //using namespace GM; /** * @brief 使用公钥/私钥数据获取EV_KEY对象 * @param key 公钥/私钥数据 * @param is_public 是否公钥 * @return 失败返回NULL */ static EC_KEY *CreateEC(unsigned char *key, int is_public) { EC_KEY *ec_key = NULL; BIO *keybio = NULL; keybio = BIO_new_mem_buf(key, -1); if (keybio == NULL) { printf("%s", "[BIO_new_mem_buf]->key len=%d,Failed to Get Key", strlen((char *) key)); return NULL; } if (is_public) { ec_key = PEM_read_bio_EC_PUBKEY(keybio, NULL, NULL, NULL); } else { ec_key = PEM_read_bio_ECPrivateKey(keybio, NULL, NULL, NULL); } if (ec_key == NULL) { printf("Failed to Get Key"); BIO_free_all(keybio); return NULL; } BIO_free_all(keybio); // 此处是不是要free? return ec_key; } int GmSm2Encrypt(string strPubKey, const string &strIn, string &strCiphertext) { EC_KEY *evKey = CreateEC((unsigned char *)strPubKey.c_str(), 1); if (NULL == evKey) { return GM_UTIL_CODE_CREATE_EV_KEY_FAILED; } // 目前只支持默认的sm2p256v1椭圆曲线参数 if (!EC_KEY_is_sm2p256v1(evKey)) { EC_KEY_free(evKey); return GM_UTIL_CODE_NOT_SM2P256V1; } // 加密后的密文会比明文长97字节 unsigned char *buff = NULL; size_t outLen = 0; SM2CiphertextValue *cval = NULL; size_t mlen, clen; unsigned char *p; if (NULL == (cval = SM2_do_encrypt(EVP_sm3(), (const unsigned char *)strIn.c_str(), strIn.size(), evKey))) { EC_KEY_free(evKey); return GM_UTIL_CODE_SM2_ENCRYPT_FAILED; } BIO *bOut = BIO_new(BIO_s_mem()); if (NULL == bOut) { EC_KEY_free(evKey); SM2CiphertextValue_free(cval); return GM_UTIL_CODE_INIT_BIO_FAILED; } if (i2d_SM2CiphertextValue_bio(bOut, cval) sgetn(buffer, count); stream.rdstate(); stream.peek(); return reads; } string GmReadKeyFromFile(string strFileName) { fstream myfile; myfile.open(strFileName, ifstream::in | ifstream::binary); if (!myfile.is_open()) { return ""; } char buff[1024]; std::ostringstream oss; int len; while (!myfile.eof()) { size_t read = Read(myfile, buff, sizeof(buff)); oss > 4) & 0x0F]; strHex += sDigit[cTemp & 0x0F]; } return strHex; } string GmHexStr2Byte(const string& hex, bool bLowerCase) { if (hex.size() % 2 != 0) { // 十六进制字符串必须是偶数长度 return ""; } char chA = 'a'; if (!bLowerCase) { chA = 'A'; } std::ostringstream oss; for (int i = 0; i < hex.size(); i += 2) { unsigned int highBit; if (hex[i] >= '0' && hex[i] = '0' && hex[i + 1]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3