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