我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
这是将之前写的AES的版本改为SM4,代码变化不大。对应的,也有一个同样的C#版本(国密起步7:BouncyCastle使用SM4自定义格式加解密C#版-CSDN博客)。
这个自定格式是:一字节版本,多个16字节加密块(其中第一个块前8字节是明文长度,后8字节未用)。
一、GmSSL的SM4和AES的区别
sm4只支持128位密钥,其余从编程角度看没什么区别。
CBC、padding这些都是一样的。
因为OpenSSL的CBC有问题,所以我自己写了CBC,也没有使用padding,直接在密文中放了明文长度,因为旧代码已经如此,所以新代码还是这样写的(并非库有什么问题)。
二、源码
//myGmSSL.h 文件编码:UTF-8无签名
#pragma once
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <gmssl/sm4.h>
#include <gmssl/rand.h>
#include <vector>
#include "Buffer.h"
#include "mimetype.h"
using namespace std;
namespace ns_my_std
{
class CMyGmSSL
{
private:
static unsigned char getVer() { return 1; }
static void show_buf(char const* title, unsigned char const* buf, int len)
{
cout << title << " ";
for (int i = 0; i < len; ++i)
{
cout << hex << setw(2) << setfill('0') << (unsigned int)buf[i] << " ";
}
cout << endl;
}
//需要一个从用户密码生成密钥的函数
public:
class IV
{
private:
unsigned char iv[SM4_BLOCK_SIZE];
public:
IV()
{
memset(iv, 0, SM4_BLOCK_SIZE);
}
//执行异或
static void XOR(unsigned char const* iv, unsigned char* data)
{
//show_buf("IV ", iv, SM4_BLOCK_SIZE);
//show_buf("DATA", data, SM4_BLOCK_SIZE);
for (int i = 0; i < SM4_BLOCK_SIZE; ++i)
{
data[i] ^= iv[i];
}
//show_buf("DATA", data, SM4_BLOCK_SIZE);
}
int size()const
{
return SM4_BLOCK_SIZE;
}
//用随机数设置
void Create()
{
time_t t = time(NULL);
srand(t);
for (int i = 0; i < SM4_BLOCK_SIZE; i += sizeof(int))
{
int a = rand();
memcpy(iv + i, &a, sizeof(int));
}
}
void Set(unsigned char const* a)
{
memcpy(iv, a, SM4_BLOCK_SIZE);
}
//注意,会修改内容
unsigned char* Get()
{
//show_buf("IV ", iv, SM4_BLOCK_SIZE);
return iv;
}
};
//所以自行实现CBC
st