1.SM2算法

openssl 1.1.1以后版本提供了对国密SM2算法的支持。源码的cryto/include/internall目录下有sm2,sm3,sm4的设计实现,但是无法直接调用,因此通过openssl的evp接口实现国密SM2算法的加解密。

SM2公钥格式:公钥:04|X|Y,共65字节;私钥格式:整数,共32字节。密文格式结构体为,typedef struct SM2Cipher_st {
    ASN1_INTEGER *xCoordinate;                                // x分量(随机,非公钥),32字节
    ASN1_INTEGER *yCoordinate;                                // y分量(随机,非公钥),32字节
    ASN1_OCTET_STRING *hash;                                  // 杂凑值,32字节
    ASN1_OCTET_STRING *cipherText;                            // 真密文,等于明文长度
} SM2Cipher;
密文结构体x、y分量为C1,杂凑值为C3,密文数据为C2,新标准密文结构为C1C3C2。根据密文机构以及各个成员变量长度可以知道,明文长度等于密文结构体长度-96。

2.例子

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <string>
#include <unistd.h>
std::string sm2PriKeyStr="MIICSwIBADCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/v8AAAAA//8wRAQg/v8AAAAA//wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP7///9yA99rIcYFK1O79Ak51UEjAgEBBIIBVTCCAVECAQEEINXHVaHjZdZjM3Ja9CyYR/VT4ZXqX2JCG1w59I+G2DoToIHjMIHgAgEBMCwGByqGSM49AQECIQD+/wAAAAD//zBEBCD+/wAAAAD//AQgKOn6np2fXjRNWp5Lz2UJp/OXifUVq4+S3by9QU2UDpMEQQQyxK4sHxmBGV+ZBEZqOcmUj+MLv/JmC+FxWkWJM0x0x7w3NqL09necWb3O42tpIVPQqYd8xipHQALfMuUhOfCgAiEA/v///3ID32shxgUrU7v0CTnVQSMCAQGhRANCAAQ8nhkap78DwzgwGnIBNfgXNIyoqPzfT+rnmXvRJ7NY8fjONiql9wQYxliyuAil6lNu2ax2MULoG43kdKE8a2JU";
std::string sm2PubKeyStr="MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/v8AAAAA//8wRAQg/v8AAAAA//wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP7///9yA99rIcYFK1O79Ak51UEjAgEBA0IABDyeGRqnvwPDODAacgE1+Bc0jKio/N9P6ueZe9Ens1jx+M42KqX3BBjGWLK4CKXqU27ZrHYxQugbjeR0oTxrYlQ=";int my_sm2encrpt(std::string keystr, unsigned char *sourStr, int cStrlen ,unsigned char *enStr)
{BIO* bp = NULL;EVP_PKEY *pkey = NULL;EVP_PKEY_CTX *ectx = NULL;size_t cEnStrlen;char *cEnStr = NULL;char *chPublicKey = const_cast<char *>(keystr.c_str());if ((bp = BIO_new_mem_buf(chPublicKey, -1)) == NULL){printf("BIO_new_mem_buf failed!\n");return NULL;}pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);BIO_free_all(bp);if ( (EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) != 1 ){goto clean_up;}if ( !(ectx = EVP_PKEY_CTX_new(pkey, NULL)) ){goto clean_up;}if ( (EVP_PKEY_encrypt_init(ectx)) != 1 ){goto clean_up;}if ( (EVP_PKEY_encrypt(ectx, NULL, &cEnStrlen,reinterpret_cast<unsigned char *>(sourStr), (size_t)(cStrlen))) != 1 ){goto clean_up;}if ( !(cEnStr = ( char *)malloc(cEnStrlen)) ){goto clean_up;}if ( (EVP_PKEY_encrypt(ectx,reinterpret_cast<unsigned char *>(cEnStr), &cEnStrlen,reinterpret_cast<unsigned char *>(sourStr), cStrlen)) != 1 ){goto clean_up;}printf("enStrLen2:\n %d\n",cEnStrlen);memcpy(enStr,cEnStr,cEnStrlen);return (int)(cEnStrlen);clean_up:if (pkey){EVP_PKEY_free(pkey);}if (ectx){EVP_PKEY_CTX_free(ectx);}if (sourStr){free(sourStr);}if (cEnStr){free(cEnStr);}
}int dencryptStr(std::string keystr,unsigned char * cEnStr,int cEnstrlen,unsigned char* deStr){BIO* priBp = NULL;EVP_PKEY * mSm2PriKey;EVP_PKEY_CTX *ectx = NULL;size_t cDeStrlen=0;char *cDeStr = NULL;//create pri keychar *chPrilicKey = const_cast<char *>(keystr.c_str());if ((priBp = BIO_new_mem_buf(chPrilicKey, -1)) == NULL){printf("BIO_new_mem_buf failed!\n");}mSm2PriKey = PEM_read_bio_PrivateKey(priBp, NULL, NULL, NULL);BIO_free_all(priBp);if (NULL == mSm2PriKey){ERR_load_crypto_strings();char errBuf[512];ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));printf("load sm2 private key failed[%s]\n", errBuf);}//解密if ((EVP_PKEY_set_alias_type(mSm2PriKey, EVP_PKEY_SM2)) != 1 ){printf("EVP_PKEY_set_alias_type failed!\n");}if ( !(ectx = EVP_PKEY_CTX_new(mSm2PriKey, NULL)) ){printf("EVP_PKEY_CTX_new failed!\n");}if ( (EVP_PKEY_decrypt_init(ectx)) != 1 ){printf("EVP_PKEY_decrypt_init failed!\n");}if ( (EVP_PKEY_decrypt(ectx, NULL, &cDeStrlen,  reinterpret_cast<unsigned char *>(cEnStr), cEnstrlen)) != 1 ){printf("EVP_PKEY_decrypt failed!\n");ERR_load_crypto_strings();char errBuf[512];ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));printf("EVP_PKEY_decrypt[%s]\n", errBuf);}if ( !(cDeStr = (char*)malloc(cDeStrlen)) ){printf(" (unsigned char *)malloc(cDeStrlen)) failed!\n");}if ( (EVP_PKEY_decrypt(ectx,  reinterpret_cast<unsigned char *>(cDeStr), &cDeStrlen, reinterpret_cast<unsigned char *>(cEnStr), cEnstrlen)) != 1 ){printf(" EVP_PKEY_decrypt failed!\n");}printf("cDeStrlen:%d\n",cDeStrlen);memcpy(deStr,cDeStr,cDeStrlen);EVP_PKEY_CTX_free(ectx);free(cDeStr);return cDeStrlen;
}
int main(int argc, char *argv[])
{unsigned char sm2_en[512],sm2_de[512];int sm2enStrLen,sm2deStrLen;for(int i = 64; i < sm2PriKeyStr.size(); i+=64){if(privatekey[i] != '\n'){sm2PriKeyStr.insert(i, "\n");}++i;}sm2PriKeyStr.insert(0, "-----BEGIN EC PARAMETERS-----\nBggqgRzPVQGCLQ==\n-----END EC PARAMETERS-----\n-----BEGIN EC PRIVATE KEY-----\n");sm2PriKeyStr.append("\n-----END EC PRIVATE KEY-----\n");for(int i = 64; i < sm2PubKeyStr.size(); i+=64){if(publickey[i] != '\n'){sm2PubKeyStr.insert(i, "\n");}++i;}sm2PubKeyStr.insert(0, "-----BEGIN PUBLIC KEY-----\n");sm2PubKeyStr.append("\n-----END PUBLIC KEY-----\n");unsigned char source[20]={0x41,0x12,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20};sm2enStrLen=my_sm2encrpt(sm2PubKeyStr,source,20,sm2_en);printf("sm2enStrLen :%d \n",sm2enStrLen);printf("sm2_en: \n");for(int i=0;i<sm2enStrLen;i++){printf("0x%02x ",sm2_en[i]);}printf("\n");sm2deStrLen=dencryptStr(sm2PriKeyStr,sm2_en,sm2enStrLen,sm2_de);printf("sm2deStrLen :%d \n",sm2deStrLen);printf("sm2_de: ");for(int i=0;i<sm2deStrLen;i++){printf("0x%x ",sm2_de[i]);}printf("\n");*/
}

openssl sm2 加解密相关推荐

  1. openssl SM2 加解密的坑

    1.密文结构,有些算法实现输出的密文结构为 C1C2C3 ,有些为 C1C3C2 , 需要先转换密文格式,再做解密操作. 2.有些算法实现,公钥前加 04 ,私钥前加 00,密文前加 04 ,在处理时 ...

  2. 使用 Python 脚本执行国密 sm2 加解密

    一.场景 工作中的一个场景:Go 需要对信息加解密,但是研究了 GmSSL Go API 文档之后,发现是依赖于 CGO 的,同事配了半天环境没配成功.于是换了一个方法,选择 Go 调 Python ...

  3. SM2 加解密 一文理清

    1. 给一个私钥的der文件. 通过命令查看公私钥数据. F:\project\simkey\now\>gmssl ec -inform der -in anca_ec_keypri.der - ...

  4. SM2 加解密注意事项

    SM2 加解密联调时走过的坑 1.密文数据,有些加密硬件出来密文结构为 C1|C2|C3 ,有些为 C1|C3|C2 , 需要对应密文结构做解密操作 2.有些加密硬件,公钥前加04 ,私钥前加00,密 ...

  5. python openssl 证书加解密过程感觉是这样

    python openssl 证书加解密过程感觉是这样 第一步 生成2048 bit的PEM格式的RSA Key:Key.pem openssl genrsa -out Key.pem -f4 204 ...

  6. Openssl Aes加解密使用示例

    Openssl Aes加解密使用示例 Aes简介 设置Aes密钥 Aes算法CBC加解密 Aes简介 Aes是分组加密算法,主要基于块加密,选取固定长度的密钥去加密明文中固定长度的块,生成的密文块与明 ...

  7. SM2加解密代码及算法解析

    一.前言 关于国密算法SM2加解密的标准可参考国标文件: http://c.gb688.cn/bzgk/gb/showGb?type=online&hcno=370AF152CB5CA4A37 ...

  8. 国密算法SM2加解密,签名和验签java语言

    SM2加解密java语言 maven项目 引入bcprov-jdk15on <dependency><groupId>org.bouncycastle</groupId& ...

  9. linux证书存放路径,利用Tar和OpenSSL轻松加/解密文件和目录

    众所周知要想保护数据的安全比较简单快捷的方法无疑是给文件和目录进行加密的操作.相比于Windows给文件和目录进行加/解密的操作,在Linux上进行加/解密文件和目录要复杂一点.那么我们到底有没有什么 ...

最新文章

  1. SLAM技术大解析:它是如何帮助机器人实现智能行走的?
  2. 字符串常量池StringTable 你真的了解么
  3. 浅谈Java网络编程之Socket (1)
  4. ajax17,17个使用AJAX技术的数据表格控件
  5. SDUT-2121_数据结构实验之链表六:有序链表的建立
  6. SpringBoot整合Redis 主从复制_01
  7. vue 刷新echarts_在vue.js中使用echarts,数据动态刷新
  8. 人均34万,腾讯为3300名员工发11亿红包;B站回应大会员补偿会自动续费;​小米销量超苹果跻身全球第二|极客头条...
  9. AI “闯入”北极圈
  10. 将php分页类YII绑定框架,就需要改变风格的基础
  11. ajax传图片的方法
  12. 解读灰度直方图的信息
  13. 微信小程序中自定义模板
  14. ASUS C302C Chromebook Windows声卡驱动
  15. linux ikev1切换到ikev2,IKEv2与IKEv1的差异.doc
  16. Java Swing 开发总结汇总贴
  17. 基于HTML5的个人网页的网站设计与实现 毕业设计-附源码031623
  18. File xxx specified for property 'resourceFile' does not exist.解决方法
  19. 线性代数 05.07 用合同变换法化二次型为标准形
  20. python多光谱遥感数据处理、图像分类、定量评估及机器学习方法

热门文章

  1. cxf拦截器,实现对接收到的报文和发送出去的报文格式自定义
  2. 拓扑排序 病毒virus
  3. 途志:想要提高直播间销量 ,产品出场顺序很重要
  4. 提醒陕西省高级职称评审进入到答辩者一些技巧
  5. 《Windows网络编程案例教程》-董相志 学习记录 阻塞/非阻塞套接字编程
  6. 刷脸支付技术对接可以代理可以贴牌
  7. cv曲线面积的意义_「初中数学」与反比例函数有关的面积专题
  8. 电信增值服务许可证申请流程条件?
  9. 男朋友想自学python_我在学习鼓励男朋友初篇-百度经验
  10. Android Studio 基础 之 获取系统Calendar 日历日程(可获得当天以后可设定天数范围内的日历日程) (涉及指定日期时间判断是星期几的方法使用)的方法整理