base_sm4.h

#pragma once
#include <vector>
#include <iostream>
/*32位以内的循环左移*/
#define SM4_Rotl32(buf,n) (((buf)<<(n))|((buf)>>(32-(n))))
class base_sm4
{
public:
base_sm4() {};
/*
* 函数SM4_SelfCheck是SM4自检函数,它用标准数据作为输入,那么输出也是一个标准结果,
如果输出和标准结果不同,就说明发生错误了。
若函数返回0,则表示自检成功,否则失败。
*/
int SM4_SelfCheck();
protected:
std::vector<unsigned int>SM4_CK{
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
};
std::vector<unsigned int>SM4_FK{
0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC,
};
std::vector<unsigned char>SM4_Sbox{
0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48,
};
/*
* 函数SM4_KeySchedule用来生成轮密钥,
参数MK是输入参数,存放主密钥(也就是加密密钥);
rk是输出参数,存放生成的轮密钥。rk为32长度
*/
void SM4_KeySchedule(std::vector<unsigned char>::iterator MK, std::vector<unsigned int>::iterator rK);
/*
* 函数SM4_Encrypt是SM4加密函数,输入参数MK存放主密钥;
输入参数PlainText存放要加密的明文;
输出参数CipherText存放加密的结果,即密文。
*/
void SM4_Encrypt(std::vector<unsigned char>::iterator MK, std::vector<unsigned char>::iterator PlainText, std::vector<unsigned char>::iterator CipherText);
/*
* 函数SM4_Decrypt是SM4解密函数,输入参数MK存放主密钥,这个密钥和加密时的主密钥必须一样;
输入参数CipherText存放要解密的密文;
输出参数PlainText存放解密的结果,即明文。
*/
void SM4_Decrypt(std::vector<unsigned char>::iterator MK, std::vector<unsigned char>::iterator CipherText, std::vector<unsigned char>::iterator PlainText);
};
View Code
base_sm4.cpp

#include "base_sm4.h"
void base_sm4::SM4_KeySchedule(std::vector<unsigned char>::iterator MK, std::vector<unsigned int>::iterator rK) {
unsigned int temp{}, buf{};
std::vector<unsigned int>K(36, 0);
for (int i{}; i < 4; ++i) {
K[i] = this->SM4_FK[i] ^ ((MK[4 * i] << 24) | (MK[4 * i + 1] << 16) | (MK[4 * i + 2] << 8) | (MK[i * 4 + 3]));
}
for (int i{}; i < 32; ++i) {
temp = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ this->SM4_CK[i];
buf = ((this->SM4_Sbox[(temp >> 24 & 0xff)]) << 24) | ((this->SM4_Sbox[(temp >> 16 & 0xff)]) << 16) | ((this->SM4_Sbox[(temp >> 8 & 0xff)]) << 8) | (this->SM4_Sbox[(temp & 0xff)]);
K[i + 4] = K[i] ^ (buf ^ (SM4_Rotl32((buf), 13)) ^ (SM4_Rotl32((buf), 23)));
rK[i] = K[i + 4];
}
}
void base_sm4::SM4_Encrypt(std::vector<unsigned char>::iterator MK, std::vector<unsigned char>::iterator PlainText, std::vector<unsigned char>::iterator CipherText) {
unsigned int temp{}, buf{};
std::vector<unsigned int> rk(36, 0);
std::vector<unsigned int> X(36, 0);
this->SM4_KeySchedule(MK, rk.begin());
for (int i{}; i < 4; ++i) {
X[i] = (PlainText[i * 4] << 24) | (PlainText[i * 4 + 1] << 16) | (PlainText[i * 4 + 2] << 8) | (PlainText[i * 4 + 3]);
}
for (int i{}; i < 32; i++) {
temp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i];
buf = ((this->SM4_Sbox[(temp >> 24 & 0xff)]) << 24) | ((this->SM4_Sbox[(temp >> 16 & 0xff)]) << 16) | ((this->SM4_Sbox[(temp >> 8 & 0xff)]) << 8) | (this->SM4_Sbox[(temp & 0xff)]);
X[i + 4] = X[i] ^ (buf ^ SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10) ^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
}
for (int i{}; i < 4; ++i) {
CipherText[4 * i] = (X[35 - i] >> 24) & 0xff;
CipherText[4 * i + 1] = (X[35 - i] >> 16) & 0xff;
CipherText[4 * i + 2] = (X[35 - i] >> 8) & 0xff;
CipherText[4 * i + 3] = (X[35 - i]) & 0xff;
}
}
void base_sm4::SM4_Decrypt(std::vector<unsigned char>::iterator MK, std::vector<unsigned char>::iterator CipherText, std::vector<unsigned char>::iterator PlainText) {
unsigned int temp, buf;
std::vector<unsigned int> rk(36, 0);
std::vector<unsigned int> X(36, 0);
this->SM4_KeySchedule(MK, rk.begin());
for (int i{}; i < 4; ++i) {
X[i] = (CipherText[i * 4] << 24) | (CipherText[i * 4 + 1] << 16) | (CipherText[i * 4 + 2] << 8) | (CipherText[i * 4 + 3]);
}
for (int i{}; i < 32; ++i) {
temp = X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[31 - i];
buf = ((this->SM4_Sbox[(temp >> 24 & 0xff)]) << 24) | ((this->SM4_Sbox[(temp >> 16 & 0xff)]) << 16) | ((this->SM4_Sbox[(temp >> 8 & 0xff)]) << 8) | (this->SM4_Sbox[(temp & 0xff)]);
X[i + 4] = X[i] ^ (buf ^ SM4_Rotl32((buf), 2) ^ SM4_Rotl32((buf), 10) ^ SM4_Rotl32((buf), 18) ^ SM4_Rotl32((buf), 24));
}
for (int i{}; i < 4; ++i) {
PlainText[4 * i] = (X[35 - i] >> 24) & 0xff;
PlainText[4 * i + 1] = (X[35 - i] >> 16) & 0xff;
PlainText[4 * i + 2] = (X[35 - i] >> 8) & 0xff;
PlainText[4 * i + 3] = (X[35 - i]) & 0xff;
}
}
int base_sm4::SM4_SelfCheck() {
//Standard data 标准数据
std::vector<unsigned char> key { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
std::vector<unsigned char> plain { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 };
std::vector<unsigned char>cipher { 0x68,0x1e,0xdf,0x34,0xd2,0x06,0x96,0x5e,0x86,0xb3,0xe9,0x4f,0x53,0x6e,0x42,0x46 };
std::vector<unsigned char> En_output(16,0);
std::vector<unsigned char>De_output(16, 0);
SM4_Encrypt(key.begin(), plain.begin(), En_output.begin());
SM4_Decrypt(key.begin(), cipher.begin(), De_output.begin());
//判断
for (int i = 0; i < 16; i++)
{
//第一个判断是判断加密结果是否和标准密文数据相同
//第二个判断解密结果是否和明文相同
if ((En_output[i] != cipher[i]) || (De_output[i] != plain[i]))
{
std::cout << "Self-check error/nEn_output:";
for (int j = 0; j < 16; j++) {
std::cout << std::hex << static_cast<int>(En_output[j]) << ",";
}
std::cout << "/nDe_output:";
for (int j = 0; j < 16; j++) {
std::cout << std::hex << static_cast<int>(De_output[j]) << ",";
}
std::cout << "/n";
return 1;
}
}
std::cout << "sm4(16字节)自检成功!/n/n";
return 0;
}
View Code
实现SM4算法(16字节版).cpp

// 实现SM4算法(16字节版).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 为什么叫16字节版呢?这是因为本例只能对16字节数据进行加解密。
// 为什么不直接给出能对任意长度数据进行加解密的版本呢?
// 这是因为任意长度加解密的版本也是以16字节版为基础的。
// 别忘记了,SM4的分组长度是16字节,SM4是分组加解密的,任何长度的明文都会划分为16字节一组,
// 然后一组一组地进行加解密。
//
#include <iostream>
#include "C版/sm4.h"
#include "base_sm4.h"
int main()
{
//SM4_SelfCheck();
base_sm4 sm4;
sm4.SM4_SelfCheck();
std::cout << "Hello World!/n";
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
View Code
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/289367.html