SM4算法的C++实现(代码)

一、SM4算法简介

  1. SM4算法是一个分组算法,分组长度为128比特,密钥长度为128比特。
  2. SM4算法的加密算法和密钥扩展算法都采用了32轮非线性迭代结构。
  3. SM4算法的解密算法和加密算法的结构相同,除了轮密钥的使用顺序是加密轮密钥的逆序。
  4. SM4算法的加密流程图大致如下图所示。
    在这里插入图片描述

二、SM4算法的C++实现

1.C++代码

#include <iostream>
#include <string>
#include <cmath>
using namespace std;

string BinToHex(string str) {//二进制转换为十六进制的函数实现
	string hex = "";
	int temp = 0;
	while (str.size() % 4 != 0) {
		str = "0" + str;
	}
	for (int i = 0; i < str.size(); i += 4) {
		temp = (str[i] - '0') * 8 + (str[i + 1] - '0') * 4 + (str[i + 2] - '0') * 2 + (str[i + 3] - '0') * 1;
		if (temp < 10) {
			hex += to_string(temp);
		}
		else {
			hex += 'A' + (temp - 10);
		}
	}
	return hex;
}

string HexToBin(string str) {//十六进制转换为二进制的函数实现
	string bin = "";
	string table[16] = { "0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111" };
	for (int i = 0; i < str.size(); i++) {
		if (str[i] >= 'A'&&str[i] <= 'F') {
			bin += table[str[i] - 'A' + 10];
		}
		else {
			bin += table[str[i] - '0'];
		}
	}
	return bin;
}


int HexToDec(char str) {//十六进制转换为十进制的函数实现
	int dec = 0;
	if (str >= 'A' && str <= 'F') {
		dec += (str - 'A' + 10);
	}
	else {
		dec += (str - '0');
	}
	return dec;
}

string LeftShift(string str, int len) {//循环左移len位函数实现
	string res = HexToBin(str);
	res = res.substr(len) + res.substr(0, len);
	return BinToHex(res);
}

string XOR(string str1, string str2) {//异或函数实现
	string res1 = HexToBin(str1);
	string res2 = HexToBin(str2);
	string res = "";
	for (int i = 0; i < res1.size(); i++) {
		if (res1[i] == res2[i]) {
			res += "0";
		}
		else {
			res += "1";
		}
	}
	return BinToHex(res);
}

string NLTransform(string str) {//非线性变换t函数实现
	string Sbox[16][16] = { {"D6","90","E9","FE","CC","E1","3D","B7","16","B6","14","C2","28","FB","2C","05"},
						 {"2B","67","9A","76","2A","BE","04","C3","AA","44","13","26","49","86","06","99"},
						 {"9C","42","50","F4","91","EF","98","7A","33","54","0B","43","ED","CF","AC","62"},
						 {"E4","B3","1C","A9","C9","08","E8","95","80","DF","94","FA","75","8F","3F","A6"},
						 {"47","07","A7","FC","F3","73","17","BA","83","59","3C","19","E6","85","4F","A8"},
						 {"68","6B","81","B2","71","64","DA","8B","F8","EB","0F","4B","70","56","9D","35"},
						 {"1E","24","0E","5E","63","58","D1","A2","25","22","7C","3B","01","21","78","87"},
						 {"D4","00","46","57","9F","D3","27","52","4C","36","02","E7","A0","C4","C8","9E"},
						 {"EA","BF","8A","D2","40","C7","38","B5","A3","F7","F2","CE","F9","61","15","A1"},
						 {"E0","AE","5D","A4","9B","34","1A","55","AD","93","32","30","F5","8C","B1","E3"},
						 {"1D","F6","E2","2E","82","66","CA","60","C0","29","23","AB","0D","53","4E","6F"},
						 {"D5","DB","37","45","DE","FD","8E","2F","03","FF","6A","72","6D","6C","5B","51"},
						 {"8D","1B","AF","92","BB","DD","BC","7F","11","D9","5C","41","1F","10","5A","D8"},
						 {"0A","C1","31","88","A5","CD","7B","BD","2D","74","D0","12","B8","E5","B4","B0"},
						 {"89","69","97","4A","0C","96","77","7E","65","B9","F1","09","C5","6E","C6","84"},
						 {"18","F0","7D","EC","3A","DC","4D","20","79","EE","5F","3E","D7","CB","39","48"} };
	string res = "";
	for (int i = 0; i < 4; i++) {
		res = res + Sbox[HexToDec(str[2 * i])][HexToDec(str[2 * i + 1])];
	}
	return res;
}

string LTransform(string str) {//线性变换L函数实现
	return XOR(XOR(XOR(XOR(str, LeftShift(str, 2)), LeftShift(str, 10)), LeftShift(str, 18)), LeftShift(str, 24));
}

string L2Transform(string str) {//线性变换L'函数实现
	return XOR(XOR(str, LeftShift(str, 13)), LeftShift(str, 23));
}

string T(string str) {//用于加解密算法中的合成置换T函数实现
	return LTransform(NLTransform(str));
}

string T2(string str) {//用于密钥扩展算法中的合成置换T函数实现
	return L2Transform(NLTransform(str));
}

string KeyExtension(string MK) {//密钥扩展函数实现
	string FK[4] = { "A3B1BAC6", "56AA3350", "677D9197", "B27022DC" };
	string CK[32] = { "00070E15", "1C232A31", "383F464D", "545B6269",
				      "70777E85", "8C939AA1", "A8AFB6BD", "C4CBD2D9",
				      "E0E7EEF5", "FC030A11", "181F262D", "343B4249",
				      "50575E65", "6C737A81", "888F969D", "A4ABB2B9",
				      "C0C7CED5", "DCE3EAF1", "F8FF060D", "141B2229",
				      "30373E45", "4C535A61", "686F767D", "848B9299",
				      "A0A7AEB5", "BCC3CAD1", "D8DFE6ED", "F4FB0209",
				      "10171E25", "2C333A41", "484F565D", "646B7279" };
	string K[36] = { XOR(MK.substr(0,8),FK[0]),XOR(MK.substr(8,8),FK[1]),XOR(MK.substr(16,8),FK[2]),XOR(MK.substr(24),FK[3]) };
	string rks = "";
	for (int i = 0; i < 32; i++) {
		K[i + 4] = XOR(K[i], T2(XOR(XOR(XOR(K[i + 1], K[i + 2]), K[i + 3]), CK[i])));
		rks += K[i + 4];
	}
	return rks;
}

string encode(string plain, string key) {//加密函数实现
	cout << "轮密钥与每轮输出状态:" << endl;
	cout << endl;
	string cipher[36] = { plain.substr(0,8),plain.substr(8,8),plain.substr(16,8),plain.substr(24) };
	string rks = KeyExtension(key);
	for (int i = 0; i < 32; i++) {
		cipher[i + 4] = XOR(cipher[i], T(XOR(XOR(XOR(cipher[i + 1], cipher[i + 2]), cipher[i + 3]), rks.substr(8 * i, 8))));
		cout << "rk[" + to_string(i) + "] = " + rks.substr(8 * i, 8) + "    X[" + to_string(i) + "] = " + cipher[i + 4] << endl;
	}
	cout << endl;
	return cipher[35] + cipher[34] + cipher[33] + cipher[32];
}

string decode(string cipher, string key) {//解密函数实现
	cout << "轮密钥与每轮输出状态:" << endl;
	cout << endl;
	string plain[36] = { cipher.substr(0,8),cipher.substr(8,8), cipher.substr(16,8), cipher.substr(24,8) };
	string rks = KeyExtension(key);
	for (int i = 0; i < 32; i++) {
		plain[i + 4] = XOR(plain[i], T(XOR(XOR(XOR(plain[i + 1], plain[i + 2]), plain[i + 3]), rks.substr(8 * (31 - i), 8))));
		cout << "rk[" + to_string(i) + "] = " + rks.substr(8 * (31 - i), 8) + "    X[" + to_string(i) + "] = " + plain[i + 4] << endl;
	}
	cout << endl;
	return plain[35] + plain[34] + plain[33] + plain[32];
}

int main() {//主函数
	string str = "0123456789ABCDEFFEDCBA9876543210";
	cout << "明    文:" << str.substr(0, 8) << "  " << str.substr(8, 8) << "  " << str.substr(16, 8) << "  " << str.substr(24, 8) << endl;
	cout << endl;
	string key = "0123456789ABCDEFFEDCBA9876543210";
	cout << "加密密钥:" << key.substr(0, 8) << "  " << key.substr(8, 8) << "  " << key.substr(16, 8) << "  " << key.substr(24, 8) << endl;
	cout << endl;
	string cipher = encode(str, key);
	cout << "密    文:" << cipher.substr(0, 8) << "  " << cipher.substr(8, 8) << "  " << cipher.substr(16, 8) << "  " << cipher.substr(24, 8) << endl;
	cout << endl;
	cout << "密    文:" << cipher.substr(0, 8) << "  " << cipher.substr(8, 8) << "  " << cipher.substr(16, 8) << "  " << cipher.substr(24, 8) << endl;
	cout << endl;
	cout << "解密密钥:" << key.substr(0, 8) << "  " << key.substr(8, 8) << "  " << key.substr(16, 8) << "  " << key.substr(24, 8) << endl;
	cout << endl;
	string plain = decode(cipher, key);
	cout << "明    文:" << plain.substr(0, 8) << "  " << plain.substr(8, 8) << "  " << plain.substr(16, 8) << "  " << plain.substr(24, 8) << endl;
}

2.运行结果

  1. 加密运算运行结果图:
    在这里插入图片描述

  2. 解密运算运行结果图:
    在这里插入图片描述

  • 10
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
你可以使用以下代码实现SM2算法C++版本: ```cpp #include <iostream> #include <string> #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/ecdsa.h> #include <openssl/bn.h> std::string sm2_encrypt(const std::string& plaintext, EC_KEY* ec_key) { EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); size_t plaintext_len = plaintext.size(); unsigned char* ciphertext = new unsigned char[plaintext_len + 1]; unsigned char* pt = (unsigned char*)plaintext.c_str(); unsigned char* ct = ciphertext; int ciphertext_len = ECIES_encrypt(ec_group, NULL, pt, plaintext_len, ct, ec_key); std::string result((char*)ciphertext, ciphertext_len); delete[] ciphertext; return result; } std::string sm2_decrypt(const std::string& ciphertext, EC_KEY* ec_key) { EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); size_t ciphertext_len = ciphertext.size(); unsigned char* plaintext = new unsigned char[ciphertext_len + 1]; unsigned char* ct = (unsigned char*)ciphertext.c_str(); unsigned char* pt = plaintext; int plaintext_len = ECIES_decrypt(ec_group, NULL, ct, ciphertext_len, pt, ec_key); std::string result((char*)plaintext, plaintext_len); delete[] plaintext; return result; } int main() { // 初始化 OpenSSL OpenSSL_add_all_algorithms(); // 创建 SM2 密钥对 EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1); if (ec_key == NULL) { std::cerr << "Failed to create SM2 key pair" << std::endl; return 1; } // 生成 SM2 密钥对 if (EC_KEY_generate_key(ec_key) != 1) { std::cerr << "Failed to generate SM2 key pair" << std::endl; EC_KEY_free(ec_key); return 1; } // 明文 std::string plaintext = "Hello, SM2!"; // 加密 std::string ciphertext = sm2_encrypt(plaintext, ec_key); std::cout << "Ciphertext: " << ciphertext << std::endl; // 解密 std::string decryptedtext = sm2_decrypt(ciphertext, ec_key); std::cout << "Decryptedtext: " << decryptedtext << std::endl; // 释放密钥 EC_KEY_free(ec_key); // 清理 OpenSSL EVP_cleanup(); return 0; } ``` 请确保你已经安装了 OpenSSL 库,并在编译时链接该库。这段代码通过调用 OpenSSL 的函数来实现SM2算法的加密和解密操作。你可以使用 `sm2_encrypt` 函数来加密明文,使用 `sm2_decrypt` 函数来解密密文。在示例代码中,我们生成了一个随机的SM2密钥对,并使用该密钥对对明文进行加密和解密。 请注意,这只是一个简单的示例,实际使用中你可能需要更多的代码来处理错误检查、密钥管理等方面的内容。另外,由于SM2算法是国密算法,在使用时需遵守相关法律法规。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值