C++国密SM2算法加解密的使用

news/2024/9/20 7:25:30/ 标签: c++, 算法, 开发语言

目录

效果

在线校验

代码实现参考

项目

下载


效果

加密字符串:lxw 123abcD 2024-09-01:12:00加密后信息:042E82EE8ACE2BD56FA71DC6A0C34190627AA365F8EEE6261903BEE327A85EB5E1D6E78F2D79AD6F6DC9E45C0829625DC3165BB78BD897F99044A640F930653747939CF9D5A10C8216F945A55949D8B759FAC93638AD24321017C83331F213C7599802EA216083D6E6C1372C838B9F1AA756B11E8D3BFF6A294C7FCA61解密后信息:lxw 123abcD 2024-09-01:12:00

在线校验

地址:https://the-x.cn/cryptography/Sm2.aspx

代码实现参考

https://github.com/yaqiangxue/Test_SM2_encrypt_and_decrypt/tree/master

项目

代码

#include "StdAfx.h"
#include <iostream>
#include <string>
#include <cstring>
#include <memory>
#include <openssl/bio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "sm2_cipher_error_codes.h"
#include "sm2_create_key_pair.h"
#include "sm2_encrypt_and_decrypt.h"

using namespace std;


// 将16进制的string字符串,转成16进制的arr
int hexCharStr2unsignedCharStr(char *src, unsigned long lsrc, int flag, unsigned char * out, unsigned long * lout)
{
    if((0 == flag && 0 !=lsrc%2) || (0 != flag && 0 !=lsrc%3) ||NULL == src || NULL == out )
    {
        return 1;//param err
    }

    int j = 0;//index of out buff
    if(0 == flag)
    {    //int i;
        for (int i=0; i<lsrc; i += 2)
        {
            int tmp = 0;
            int HIGH_HALF_BYTE = 0;
            int LOW_HALF_BYTE = 0;
            if (src[i]>= 0x30 && src[i]<=0x39)
            {
                HIGH_HALF_BYTE = src[i] - 0x30;
            }
            else if (src[i]>= 0x41 && src[i]<=0x46)
            {
                HIGH_HALF_BYTE = src[i] - 0x37;
            }
            else if( src[i]>= 0x61 && src[i]<=0x66)
            {
                HIGH_HALF_BYTE = src[i] - 0x57;
            }
            else if( src[i] == 0x20)
            {
                HIGH_HALF_BYTE = 0x00;
            }
            else
            {
                return -1;
            }

            if (src[i+1]>= 0x30 && src[i+1]<=0x39)
            {
                LOW_HALF_BYTE = src[i+1] - 0x30;
            }
            else if (src[i+1]>= 0x41 && src[i+1]<=0x46)
            {
                LOW_HALF_BYTE = src[i+1] - 0x37;
            }
            else if( src[i+1]>= 0x61 && src[i+1]<=0x66)
            {
                LOW_HALF_BYTE = src[i+1] - 0x57;
            }
            else if( src[i+1] == 0x20)
            {
                LOW_HALF_BYTE = 0x00;
            }
            else
            {
                return -1;
            }

            tmp = (HIGH_HALF_BYTE<<4) + LOW_HALF_BYTE;
            out [j] = tmp;
            j++;
        }
    }
    else
    {    //int i;
        for (int i=0; i<lsrc; i += 3)
        {
            int tmp = 0;
            int HIGH_HALF_BYTE = 0;
            int LOW_HALF_BYTE = 0;
            if ((i+2<= lsrc) && (src[i+2] != flag))
            {
                return 1;
            }

            if (src[i]>= 0x30 && src[i]<=0x39 )
            {
                HIGH_HALF_BYTE = src[i] - 0x30;
            }
            else if (src[i]>= 0x41 && src[i]<=0x46)
            {
                HIGH_HALF_BYTE = src[i] - 0x37;
            }
            else if( src[i]>= 0x61 && src[i]<=0x66)
            {
                HIGH_HALF_BYTE = src[i] - 0x57;
            }
            else
            {
                return -1;
            }

            if (src[i+1]>= 0x30 && src[i+1]<=0x39)
            {
                LOW_HALF_BYTE = src[i+1] - 0x30;
            }
            else if (src[i+1]>= 0x41 && src[i+1]<=0x46)
            {
                LOW_HALF_BYTE = src[i+1] - 0x37;
            }
            else if( src[i+1]>= 0x61 && src[i+1]<=0x66)
            {
                LOW_HALF_BYTE = src[i+1] - 0x57;
            }
            else
            {
                return -1;
            }

            tmp = (HIGH_HALF_BYTE<<4) + LOW_HALF_BYTE;
            out [j] = tmp;
            j++;
        }
    }

    * lout = j;
    return 0;

}

// 将hexarr 转成16进制的字符串  如 0x11 0x22  转了之后是 “1122”
string array2hex(const unsigned char *arr, size_t len)
{
    size_t i;
    string res;
    char tmp[3];
    const char *tab = "0123456789ABCDEF";
    res.reserve(len * 2 + 1);
    for(i = 0; i < len; ++i) {
        tmp[0] = tab[arr[i] >> 4];
        tmp[1] = tab[arr[i] & 0xf];
        tmp[2] = '\0';
        res.append(tmp);
    }
    return res;
}

int main() {

    int error_code;
    //生成密钥对
    /*SM2_KEY_PAIR key_pair;
    if ( error_code = sm2_create_key_pair(&key_pair) )
    {
    printf("Create SM2 key pair failed!\n");
    return (-1);
    }
    std::string pubKeyStr2=array2hex(key_pair.pri_key,32);
    std::string priKeyStr2=array2hex(key_pair.pub_key,65);
    std::cout<<"pubKeyStr:"<<pubKeyStr2<<std::endl;
    std::cout<<"priKeyStr:"<<priKeyStr2<<std::endl;*/

    //公钥是加04的。
    std::string pubKeyStr = "04FDFB7C93565AB39E1D8178429632EEC914F6A347AE9A0CE9B201FFAEA81A80CC4D81036191209B21CDBAD8A4BCD5C9A776FEDB771D6D2D8DAC0F1E5941C0F63C";
    std::string priKeyStr = "832B9C649C63B376DBD1D858C4D1B804CCFF6F7B6B588A9F30A54AF821F80E86";

    std::string msg = "lxw 123abcD 2024-09-01:12:00";
    std::cout<<"加密字符串:"<<msg<<std::endl<<std::endl;
    int msg_len = msg.length();

    //私钥
    unsigned char pri_key[32] = {0};
    unsigned long pri_key_len = 32;

    //公钥
    unsigned char pub_key[65] = {0}; 
    unsigned long pub_key_len = 65;

    unsigned char c1[65], c3[32];
    unsigned long c1Len = 65;
    unsigned long c3Len = 32;
    unsigned char *c2, *plaintext;

    int b = hexCharStr2unsignedCharStr((char*)priKeyStr.c_str(), priKeyStr.length(), 0, pri_key, &pri_key_len);
    if(b != 0)
    {
        printf("转换priKeyStr失败\n");
    }

    b = hexCharStr2unsignedCharStr((char*)pubKeyStr.c_str(), pubKeyStr.length(), 0, pub_key, &pub_key_len);
    if(b != 0)
    {
        printf("转换pubKeyStr失败\n");
    }

    if ( !(c2 = (unsigned char *)malloc(msg_len)) )
    {
        printf("Memory allocation failed!\n");
        return ALLOCATION_MEMORY_FAIL;
    }

    //加密
    if ( error_code = sm2_encrypt((unsigned char *)msg.c_str(),
        msg_len,
        pub_key,
        c1,
        c3,
        c2) )
    {
        printf("Create SM2 ciphertext by using input defined in standard failed!\n");
        free(c2);
        return error_code;
    }
    std::string c1str=array2hex(c1,c1Len);
    std::string c2str=array2hex(c2,msg_len);
    std::string c3str=array2hex(c3,c3Len);

    std::string result=c1str+c2str+c3str;
    std::cout<<"加密后信息:"<<result<<std::endl<<std::endl;

    //解密
    if ( !(plaintext = (unsigned char *)malloc(c2str.length())) )
    {
        printf("Memory allocation failed!\n");
        return ALLOCATION_MEMORY_FAIL;
    }
    if ( error_code = sm2_decrypt(c1,
        c3,
        c2,
        msg_len,
        pri_key,
        plaintext) )
    {
        printf("Decrypt SM2 ciphertext by using private key defined in standard failed!\n");
    }

    std::string plainTextStr((char*)plaintext);
    plainTextStr = plainTextStr.substr(0, msg_len);
    std::cout<<"解密后信息:"<<plainTextStr<<std::endl;

    free(plaintext);
    free(c2);

    getchar();
    return 0;
}

#include "StdAfx.h"
#include <iostream>
#include <string>
#include <cstring>
#include <memory>
#include <openssl/bio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "sm2_cipher_error_codes.h"
#include "sm2_create_key_pair.h"
#include "sm2_encrypt_and_decrypt.h"using namespace std;// 将16进制的string字符串,转成16进制的arr
int hexCharStr2unsignedCharStr(char *src, unsigned long lsrc, int flag, unsigned char * out, unsigned long * lout)
{if((0 == flag && 0 !=lsrc%2) || (0 != flag && 0 !=lsrc%3) ||NULL == src || NULL == out ){return 1;//param err}int j = 0;//index of out buffif(0 == flag){	//int i;for (int i=0; i<lsrc; i += 2){int tmp = 0;int HIGH_HALF_BYTE = 0;int LOW_HALF_BYTE = 0;if (src[i]>= 0x30 && src[i]<=0x39){HIGH_HALF_BYTE = src[i] - 0x30;}else if (src[i]>= 0x41 && src[i]<=0x46){HIGH_HALF_BYTE = src[i] - 0x37;}else if( src[i]>= 0x61 && src[i]<=0x66){HIGH_HALF_BYTE = src[i] - 0x57;}else if( src[i] == 0x20){HIGH_HALF_BYTE = 0x00;}else{return -1;}if (src[i+1]>= 0x30 && src[i+1]<=0x39){LOW_HALF_BYTE = src[i+1] - 0x30;}else if (src[i+1]>= 0x41 && src[i+1]<=0x46){LOW_HALF_BYTE = src[i+1] - 0x37;}else if( src[i+1]>= 0x61 && src[i+1]<=0x66){LOW_HALF_BYTE = src[i+1] - 0x57;}else if( src[i+1] == 0x20){LOW_HALF_BYTE = 0x00;}else{return -1;}tmp = (HIGH_HALF_BYTE<<4) + LOW_HALF_BYTE;out [j] = tmp;j++;}}else{	//int i;for (int i=0; i<lsrc; i += 3){int tmp = 0;int HIGH_HALF_BYTE = 0;int LOW_HALF_BYTE = 0;if ((i+2<= lsrc) && (src[i+2] != flag)){return 1;}if (src[i]>= 0x30 && src[i]<=0x39 ){HIGH_HALF_BYTE = src[i] - 0x30;}else if (src[i]>= 0x41 && src[i]<=0x46){HIGH_HALF_BYTE = src[i] - 0x37;}else if( src[i]>= 0x61 && src[i]<=0x66){HIGH_HALF_BYTE = src[i] - 0x57;}else{return -1;}if (src[i+1]>= 0x30 && src[i+1]<=0x39){LOW_HALF_BYTE = src[i+1] - 0x30;}else if (src[i+1]>= 0x41 && src[i+1]<=0x46){LOW_HALF_BYTE = src[i+1] - 0x37;}else if( src[i+1]>= 0x61 && src[i+1]<=0x66){LOW_HALF_BYTE = src[i+1] - 0x57;}else{return -1;}tmp = (HIGH_HALF_BYTE<<4) + LOW_HALF_BYTE;out [j] = tmp;j++;}}* lout = j;return 0;}// 将hexarr 转成16进制的字符串  如 0x11 0x22  转了之后是 “1122”
string array2hex(const unsigned char *arr, size_t len)
{size_t i;string res;char tmp[3];const char *tab = "0123456789ABCDEF";res.reserve(len * 2 + 1);for(i = 0; i < len; ++i) {tmp[0] = tab[arr[i] >> 4];tmp[1] = tab[arr[i] & 0xf];tmp[2] = '\0';res.append(tmp);}return res;
}int main() {int error_code;//生成密钥对/*SM2_KEY_PAIR key_pair;if ( error_code = sm2_create_key_pair(&key_pair) ){printf("Create SM2 key pair failed!\n");return (-1);}std::string pubKeyStr2=array2hex(key_pair.pri_key,32);std::string priKeyStr2=array2hex(key_pair.pub_key,65);std::cout<<"pubKeyStr:"<<pubKeyStr2<<std::endl;std::cout<<"priKeyStr:"<<priKeyStr2<<std::endl;*///公钥是加04的。std::string pubKeyStr = "04FDFB7C93565AB39E1D8178429632EEC914F6A347AE9A0CE9B201FFAEA81A80CC4D81036191209B21CDBAD8A4BCD5C9A776FEDB771D6D2D8DAC0F1E5941C0F63C";std::string priKeyStr = "832B9C649C63B376DBD1D858C4D1B804CCFF6F7B6B588A9F30A54AF821F80E86";std::string msg = "lxw 123abcD 2024-09-01:12:00";std::cout<<"加密字符串:"<<msg<<std::endl<<std::endl;int msg_len = msg.length();//私钥unsigned char pri_key[32] = {0};unsigned long pri_key_len = 32;//公钥unsigned char pub_key[65] = {0}; unsigned long pub_key_len = 65;unsigned char c1[65], c3[32];unsigned long c1Len = 65;unsigned long c3Len = 32;unsigned char *c2, *plaintext;int b = hexCharStr2unsignedCharStr((char*)priKeyStr.c_str(), priKeyStr.length(), 0, pri_key, &pri_key_len);if(b != 0){printf("转换priKeyStr失败\n");}b = hexCharStr2unsignedCharStr((char*)pubKeyStr.c_str(), pubKeyStr.length(), 0, pub_key, &pub_key_len);if(b != 0){printf("转换pubKeyStr失败\n");}if ( !(c2 = (unsigned char *)malloc(msg_len)) ){printf("Memory allocation failed!\n");return ALLOCATION_MEMORY_FAIL;}//加密if ( error_code = sm2_encrypt((unsigned char *)msg.c_str(),msg_len,pub_key,c1,c3,c2) ){printf("Create SM2 ciphertext by using input defined in standard failed!\n");free(c2);return error_code;}std::string c1str=array2hex(c1,c1Len);std::string c2str=array2hex(c2,msg_len);std::string c3str=array2hex(c3,c3Len);std::string result=c1str+c2str+c3str;std::cout<<"加密后信息:"<<result<<std::endl<<std::endl;//解密if ( !(plaintext = (unsigned char *)malloc(c2str.length())) ){printf("Memory allocation failed!\n");return ALLOCATION_MEMORY_FAIL;}if ( error_code = sm2_decrypt(c1,c3,c2,msg_len,pri_key,plaintext) ){printf("Decrypt SM2 ciphertext by using private key defined in standard failed!\n");}std::string plainTextStr((char*)plaintext);plainTextStr = plainTextStr.substr(0, msg_len);std::cout<<"解密后信息:"<<plainTextStr<<std::endl;free(plaintext);free(c2);getchar();return 0;
}

下载

源码下载


http://www.ppmy.cn/news/1519102.html

相关文章

【Leetcode 2357 】 使数组中所有元素都等于零 —— 哈希表

给你一个非负整数数组 nums 。在一步操作中&#xff0c;你必须&#xff1a; 选出一个正整数 x &#xff0c;x 需要小于或等于 nums 中 最小 的 非零 元素。nums 中的每个正整数都减去 x。 返回使 nums 中所有元素都等于 0 需要的 最少 操作数。 示例 1&#xff1a; 输入&am…

【手撕数据结构】二叉树oj题

目录 单值二叉树题目描述题目思路及代码 相同的树题目描述题目思路及代码 对称二叉树题目描述题目思路及代码 另一棵树的子树题目描述题目思路及代码 二叉树的前序遍历题目描述题目思路及代码 二叉树的构建与遍历题目描述题目思路及代码 单值二叉树 题目描述 题目思路及代码 …

10、Flink 动态表之表到流的转换详解

表到流的转换 动态表可以像普通数据库表一样通过 INSERT、UPDATE 和 DELETE 来不断修改,它可能是一个只有一行、不断更新的表,也可能是一个 insert-only 的表,没有 UPDATE 和 DELETE 修改,或者介于两者之间的其他表。 在将动态表转换为流或将其写入外部系统时,需要对这些…

JVM GC 调优

文章目录 引言I 调整JVM的默认堆内存配置1.1 java命令启动jar包时配置JVM 的内存参数1.2 基于Tomcat服务器部署的java应用,配置JVM 的内存参数II JVM GC 调优基本概念: 应用程序的响应时间(RT)和吞吐量(QPS)JVM调优原理调优思路调优方法JVM调优技巧建议引言 内存参数:ht…

为Ubuntu换颗“心”

对于现在的Linux发行版操作系统,都默认配置好相应的Kernel,但其版本远比最新的要旧,而最新的Kernel除了会修复已发现的BUG,有时还会更新部分框架以及新增功能模块代码,为了确保系统的稳定,还有体验下新功能,我们只好对操作系统的进行换“心”手术,这手术可不简单,首先…

Go 语言版本管理——Goenv

Go 语言版本管理——Goenv 命令安装 goenv安装和切换 Go 版本 goenv 是一个专门管理 Go 语言版本的工具。 命令 安装 goenv github-goenv git clone https://github.com/go-nv/goenv.git ~/.goenv echo export GOENV_ROOT"$HOME/.goenv" >> ~/.bash_profile…

字符编码简介

目录 1. ASCLL 2. GB2312 3. GBK/gbk 4. GB18030 5. Unicode 6. 总结 1. ASCLL 在计算机刚开始被美国人发明的时候&#xff0c;需要将字符存储到计算机进行运算或打印&#xff0c;于是选取了95 个可见字符&#xff08;数字0-9&#xff0c;英文字母&#xff0c;标点符号&…

超详细Git基本命令使用(二)

&#x1f600;前言 本篇博文是关于 Git基本命令的使用&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力&#x1f6…

SprinBoot+Vue实验室考勤管理小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

【0-1背包变种】力扣2787. 将一个数字表示成幂的和的方案数

给你两个 正 整数 n 和 x 。 请你返回将 n 表示成一些 互不相同 正整数的 x 次幂之和的方案数。换句话说&#xff0c;你需要返回互不相同整数 [n1, n2, …, nk] 的集合数目&#xff0c;满足 n n1x n2x … nkx 。 由于答案可能非常大&#xff0c;请你将它对 109 7 取余后…

深度学习100问35:如何避免梯度爆炸发生

嘿&#xff0c;想避免梯度爆炸这个麻烦家伙&#xff0c;有好多招儿呢。 首先说说权重初始化&#xff0c;这就好比给游戏里的角色分配初始能力值。得合理安排神经网络的权重初始化哦&#xff0c;不然一开始就可能出问题。可以用像 Xavier 初始化或者 He 初始化这些方法&#x…

Http的get请求中的URL中的占位符参数和查询参数有什么区别

Http的GET请求中的URL中的占位符参数和查询参数在功能、位置和用途上存在明显的区别。 占位符参数&#xff08;Path Variables&#xff09; 定义与位置&#xff1a;占位符参数是通过URL模板中的{}定义的&#xff0c;它们位于URL的路径&#xff08;path&#xff09;部分。例如…

Python实时聊天室架构与API实战应用

尊敬的各位读者&#xff0c;欢迎参与本次共享研讨项目——利用Python构建实时聊天室。在本项目中&#xff0c;我们将引进一款前沿工具——发布订阅频道API&#xff0c;以实现聊天室内的实时交互功能。 在当今信息泛滥的社会环境下&#xff0c;实时交流已成为人们日常生活中不可…

算法训练营|图论第7天 prim算法 kruskal算法

题目&#xff1a;prim算法 题目链接&#xff1a; 53. 寻宝&#xff08;第七期模拟笔试&#xff09; (kamacoder.com) 代码&#xff1a; #include<bits/stdc.h> #include<unordered_map> #include<unordered_set> using namespace std; int main() {int v…

人工智能 | 实现定制化 AutoGPT 实战

简介 在前面的学习过程中&#xff0c;已经了解到了 AutoGPT 基本的环境安装操作。接下来就可以基于 AutoGPT 完成一些有趣的任务。通过 AutoGPT 实现我们的需求 环境准备 在正式使用 AutoGPT 之前&#xff0c;确认以下环境没有任何问题&#xff1a; 稳定的科学上网环境。配…

国产芯片+国产操作系统打造办公系统

在《使用国产操作系统作为开发系统》一文中&#xff0c;我介绍了将开发系统从 Ubuntu 替换为 Deepin 系统的过程。经过一个多月的使用&#xff0c;Deepin 系统已然成为我的主力开发平台&#xff0c;其顺手程度让我对国产操作系统的信心大增。于是&#xff0c;我开始将目光瞄向公…

面试(九)

目录 一. 僵尸进程/孤儿进程/守护进程 二 线程的同步和异步 三. 线程间通信 3.1 共享内存 3.2 互斥锁 3.3 条件变量 3.4 信号量 3.5 读写锁 3.6 事件 3.7 线程局部存储 四. 进程间通信 3.1 管道 3.2 消息队列 3.3. 共享内存 3.4 信号量 3.5 套接字 3.6 内存映…

数据结构之十字链表

一、基本概念 十字链表是为了便于求得图中顶点的度&#xff08;出度和入度&#xff09;而提出来的。在十字链表存储结构中&#xff0c;有向图中的每一个顶点都有一个对应的节点&#xff0c;用于存储顶点的信息&#xff08;如顶点编号、数据等&#xff09;以及指向以该顶点为弧…

Java源码学习之高并发编程基础——AQS源码剖析之阻塞队列(下)

1.前言&目录 前言&#xff1a; 在上一篇文章AQS源码剖析之阻塞队列&#xff08;上&#xff09;中介绍了以独占锁模式下AQS的基本原理&#xff0c;AQS仅仅起到了一个“维持线程等待秩序”的作用&#xff0c;那么本篇文章继续讲解共享锁模式下的特点。 AQS不操纵锁的获取或者…

Java对象的访问定位技术

Java虚拟机规范中规定reference类型是一个指向对象的引用&#xff0c;但规定并没有定义这个引用应该通过什么方式去定位、访问堆中的对象的具体位置&#xff0c;所以对象访问方式取决于具体的虚拟机实现。 目前主流的访问方式有两种&#xff1a;使用句柄和直接指针。 使用句柄…