基于crypto++国产加密软件SM4的实现,顺带加了ase,base64
唔,美国压制得越狠,各种替代产品就越能活。
本文分享SM4的一种快速实现与集成方式。
SM4(原名SMS4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布[1][2],相关标准为“GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”[1]。2016年8月,成为中国国家密码标准(GB/T 32907-2016)[3]。在商用密码体系中,SM4主要用于数据加密,其算法公开,分组长度与密钥长度均为128bit,加密算法与密钥扩展算法都采用32轮非线性迭代结构,S盒为固定的8比特输入8比特输出[4][5]。
是密码界大神wangxiaoyun(让美国安全部颤抖的人)提供的。
主要对标的是对称加密里面的DES与AES。
安全性被大机构验证过,是目前最好的国产对称加密方案。
废话不多话了,既然搜到了本文,肯定是想着怎么实现的。
首先,GMSSL 应该是实现最完整的,啥算法基本都有,但比较大。简单得了解下放弃了。感兴趣的可以自己看http://gmssl.org/。
本人对Crypto++之前有接触,使用过他提供的AES加密方式,搜了下官网,发现从6.0开始便支持SM4了,太好了。
https://www.cryptopp.com/docs/ref/class_s_m4.html#details 这里可以查看详细信息。
本人下载了最新版本8.2的。解压之后打开VS2013,对lib库进行编译,会有个cryptlib.lib的输出。我们只需要这个库即可。

我添加了下测试项目SM4-Cipher进行测试与验证。 验证是通过在线平台看看是否一致。http://aks.jd.com/tools/sec/
直接上代码了。
#include <windows.h>
#include <string>
#include <iostream>
#include "modes.h"
#include "filters.h"
#include "base64.h"
#include "aes.h"
#include "sm4.h"
using namespace std;
using namespace CryptoPP; std::string base64_encrypt(const std::string& src)
{
//byte decoded[] = { 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
std::string encoded; try
{
StringSource ss(src, true,
new Base64Encoder(
new StringSink(encoded), false
) // Base64Encoder
); // StringSource return encoded;
}
catch (...)
{
} return encoded;
} std::string base64_decrypt(const std::string& src)
{
std::string decoded; try
{
StringSource ss(src, true,
new Base64Decoder(
new StringSink(decoded)
) // Base64Decoder
); // StringSource return decoded;
}
catch (...)
{ }
return decoded; }
//typedef unsigned char byte; static CryptoPP::byte AES_KEY[] = "";
static CryptoPP::byte AES_IV[] = ""; //这里封装下sm4 加密算法加解密
bool sm4_encrypt(void* data, size_t size, std::string& out)
{
out.clear();
try
{
ECB_Mode<SM4>::Encryption cbcEncryption(AES_KEY, );
StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(out));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(data), size);
stfEncryptor.MessageEnd();
}
catch (...)
{
return false;
}
return true;
} bool sm4_decrypt(void* data, int size, std::string& out)
{
out.clear();
try
{
ECB_Mode<SM4>::Decryption cbcDecryption(AES_KEY, );
StreamTransformationFilter stfEncryptor(cbcDecryption, new CryptoPP::StringSink(out));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(data), size);
stfEncryptor.MessageEnd();
}
catch (...)
{
return false;
}
return true;
} std::string aes_encrypt(const char* src, const int &length,std::string& out)
{
//
try
{
AES::Encryption aesEncryption(AES_KEY, );
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, AES_IV);
StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(out));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(src), length);
stfEncryptor.MessageEnd(); return out;
}
catch (...)
{
}
return out;
} std::string aes_decrypt(const char* src, const int &length, std::string& out)
{
try
{
AES::Decryption aesDecryption(AES_KEY, );
CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, AES_IV);
StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(out));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(src), length);
stfDecryptor.MessageEnd(); return out;
}
catch (...)
{
}
return out;
}
以上简单得实现了 base64、aes、sm4。并测试可行。
大文件加密需要分块,注意无论是aes还是sm4,都有16字节对齐的概念。而且若块大小不是16字节倍数,补齐为16字节倍数。如果块大小是16字节倍数,则再添加16字节。
切记。
void testfile()
{
const DWORD Two_G = << ;
string path;
int type = ;
int encrypt = ;
char name[] = { };
name[] = '';
name[] = '.';
name[] = 't';
name[] = 'm';
name[] = 'p';
cout << "----------本程序基于crypto++库开发------------\n";
while (true)
{
cout << "请输入您要加解密的文件\n";
cin >> path;
if (GetFileAttributesA(path.c_str()) == INVALID_FILE_ATTRIBUTES)
{
cout << "文件输入错误\n";
continue;
} cout << "请输入您要加解密文件的种类\n 1:SM4 2:AES-256 \n";
cin >> type;
if (type < || type>)
{
cout << "暂不支持的类型\n";
continue;
} cout << "您要加密还是解密?\n 1:加密 0:解密 \n";
cin >> encrypt;
if (encrypt != && encrypt != )
{
cout << "输入有误\n";
continue;
} string path2 = "D:\\";
path2.append(name); cout << "加解密文件会输出到" << path2 << endl;
cout << "开始加解密操作了,从打开文件开始到生成全部临时文件结束,请耐心等待\n";
DWORD begin = GetTickCount(); HANDLE hFile = CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "打开文件出错\n";
continue;
}
DWORD dwBytesToRead = GetFileSize(hFile, NULL);
if (dwBytesToRead > Two_G)
{
cout << "文件太大啦\n";
CloseHandle(hFile);
continue;
}
if (GetFileAttributesA(path2.c_str()) != INVALID_FILE_ATTRIBUTES)
{
DeleteFileA(path2.c_str());
}
HANDLE hFile2 = CreateFileA(path2.c_str(), GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile2 == INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
cout << "打开文件出错\n";
continue;
}
//一次加密1M吧 1M = 16B * 65536
//一次解密需要多16字节。
DWORD size_once = * ;
if (encrypt == )
{
size_once += ;
}
char * pbuff = (char*)malloc(size_once);
//string 的大小已经在堆里了
DWORD readbyte;
do{ //循环读文件,确保读出完整的文件
ReadFile(hFile, pbuff, size_once, &readbyte, NULL);
if (readbyte==)
break;
dwBytesToRead -= readbyte; //注意,本次只有readbyte可以用
std::string out;
if (encrypt == )
{
if (type == )
{
sm4_encrypt(pbuff, readbyte, out);
}
else
{
aes_encode(pbuff, readbyte, out);
} }
else
{
if (type == ){
sm4_decrypt(pbuff, readbyte, out);
}
else
{
aes_decode(pbuff, readbyte, out);
} } //out写入文件
DWORD dwBytesToWrite = out.size();
DWORD dwBytesWrite = ;
const char * tmpBuf = out.c_str();
do{ //循环写文件,确保完整的文件被写入
WriteFile(hFile2, tmpBuf, dwBytesToWrite, &dwBytesWrite, NULL);
dwBytesToWrite -= dwBytesWrite;
tmpBuf += dwBytesWrite; } while (dwBytesToWrite > ); } while (dwBytesToRead > );
free(pbuff);
CloseHandle(hFile);
CloseHandle(hFile2);
DWORD end = GetTickCount();
cout << "本次加密结束,使用的时间为" << end - begin << "毫秒\n"; name[]++;
}
}
基于crypto++国产加密软件SM4的实现,顺带加了ase,base64的更多相关文章
- GitHub 上最热的10款国产开源软件
衡量一个开源产品好不好,看看产品在 GitHub 的 Star 数量就知道了.由此可见,GitHub 已经沦落为开源产品的“大众点评”了.一个开源产品希望快速的被开发者知道.快速的获取反馈,放到 Gi ...
- 基于web的IM软件通信原理分析
关于IM(InstantMessaging)即时通信类软件(如微信,QQ),大多数都是桌面应用程序或者native应用较为流行,而网上关于原生IM或桌面IM软件类的通信原理介绍也较多,此处不再赘述.而 ...
- 【转】基于RSA算法实现软件注册码原理初讨
1 前言 目前,商用软件和共享软件绝大部份都是采用注册码授权的方式来保证软件本身不被盗用,以保证自身的利益.尽管很多常用的许多软件系统的某些版本已经被别人破解,但对于软件特殊行业而言,注册码授权的方式 ...
- CDIF: 基于JSON的SOA软件框架
通用设备互联框架(CDIF)是一个具备中美知识产权保护的,基于web的连接框架,目前有部分开源实现存放在: GitHub - out4b/cdif: Common device interconnec ...
- CDIF:基于JSON的SOA软件框架
通用设备互联框架(CDIF)是一个具备中美知识产权保护的,基于web的连接框架,目前有部分开源实现存放在: GitHub - out4b/cdif: Common device interconnec ...
- C#基于RSA加密算法实现软件注册实战演练
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...
- C++ Crypto++ RSA加密资料收集
C++利用Crypto++,vs2005环境下的RSA应用 基于Crypto++/Cryptopp的rsa密钥生成,rsa加密.解密,rsa签名.验签 Keys and Formats 使用Crypt ...
- 使用基于 PHP 的开源软件 YOURLS 搭建短链接地址服务
使用基于 PHP 的开源软件 YOURLS搭建 系统配置 php7.1+mysql5.7+nginx 下载源代码 git clone https://github.com/YOURLS/YOURLS. ...
- 密信(Mesince)首创全自动邮件加密,颠覆传统邮件加密软件
电子邮件泄密已经成为一个全球性的日益严峻的安全问题,解决这个问题的唯一有效办法就是电子邮件内容先加密后发送.然而,使用基于S/MIME标准的传统邮件加密软件进行邮件加密,需要用户具备一定的技术基础.用 ...
随机推荐
- The usage of Markdown---文字强调:加粗/斜体/文本高亮/删除线/下划线/按键效果
更新时间:2019.09.14 1. 序言 有时候,我们需要对某些文字进行强调,例如粗体和斜体.而Markdown通常可以使用星号*或者下划线_进行文字强调. 2. 加粗 如果想要达到加粗的效果,可以 ...
- 小白学 Python(13):基础数据结构(字典)(下)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...
- 使用IDEA开发Spark程序
一.分布式估算圆周率 1.计算原理 假设正方形的面积S等于x²,而正方形的内切圆的面积C等于Pi×(x/2)²,因此圆面积与正方形面积之比C/S就为Pi/4,于是就有Pi=4×C/S. 可以利用计算机 ...
- linux小白的入门和目标。
大家好! 我是一名Linux小白,有幸来到马哥教育这个大家庭与各位同学在未来的五个月里一起学习Linux技术!尽管Linux对于刚接触到的新手会很难,但是我知道痛苦只是暂时的,满路荆棘的后面必是明亮宽 ...
- phpstudy 升级mysql到mysql5.7
前言 今天在工作发现一个错误,在往本地导数据表的时候老是报错: ? 1 [Err] 1294 - Invalid ON UPDATE clause for '字段名' column 报错的数据表字段: ...
- MySQL:数据库基本认识
1.什么是数据库 通俗来讲,数据库就是用于存储数据的仓库.很多人可能会问,存储数据用文件不就行了吗?为什么还要弄数据库? 文件存储数据具有以下几个缺点: 文件的安全性问题 文件不利于查询和数据库管理 ...
- 使用asp.net core 3.0 搭建智能小车1
跟随.net core 3.0 一起发布的System.Device.Gpio 1.0已经可以让我们用熟悉的C#原汁原味的开发莓派上面的GPIO了.并且在 Iot.Device.Bindings这个包 ...
- 微信小程序的canvas和遮盖布颜色设置问题
canvas绘画出并显示小程序的逻辑首先是将网络图片转化为本地图片,其次再将进行绘画.将本地图片和二维码显示在画布上,最后将整个画布截图用api显示在屏幕上.真正的画图让他飞去屏幕外. 有时候会需要用 ...
- 上下文管理器及with的相关总结
什么是上下文管理器 基本语法 with EXPR as VAR: BLOCK 概念 上下文表达式:with open('test.txt') as f: 上下文管理器:open('test.txt') ...
- [考试反思]1030csp-s模拟测试94:未知
排名也未知.第1或第5. 分数也未知,300或260. 人生真是大起大落... 啊啊啊啊啊我好感动啊竟然重测了一次----- 评测机怎么测怎么RE,本机怎么测怎么AC(任意编译指令,任意评测平台) 结 ...