sm3加密(32位哈希,64位十六进制数据)

这篇具有很好参考价值的文章主要介绍了sm3加密(32位哈希,64位十六进制数据)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

https://blog.csdn.net/nicai_hualuo/article/details/121555000 中介绍了sm3的算法并给出了可用代码,我只是将其拷贝过来,测试、去掉多余的输出,并进行了简单封装,以方便项目中使用。
修正了十六进制转字符串和十进制的方法支持小写的十六进制字符串。
用法见main函数。文章来源地址https://www.toymoban.com/news/detail-673343.html

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

namespace sm3
{
	// 二进制转换为十六进制函数实现
	string BinToHex(string str)
	{
		string hex = ""; // 用来存储最后生成的十六进制数
		int temp = 0;	 // 用来存储每次四位二进制数的十进制值
		while (str.size() % 4 != 0)
		{					 // 因为每四位二进制数就能够成为一个十六进制数,所以将二进制数长度转换为4的倍数
			str = "0" + str; // 最高位添0直到长度为4的倍数即可
		}
		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; // 判断出4位二进制数的十进制大小为多少
			if (temp < 10)
			{ // 当得到的值小于10时,可以直接用0-9来代替
				hex += to_string(temp);
			}
			else
			{ // 当得到的值大于10时,需要进行A-F的转换
				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 if (str[i] >= 'a' && str[i] <= 'f')
			{
				bin += table[str[i] - 'a' + 10];
			}
			else
			{
				bin += table[str[i] - '0'];
			}
		}
		return bin;
	}

	// 二进制转换为十进制的函数实现
	int BinToDec(string str)
	{
		int dec = 0;
		for (int i = 0; i < str.size(); i++)
		{
			dec += (str[i] - '0') * pow(2, str.size() - i - 1);
		}
		return dec;
	}

	// 十进制转换为二进制的函数实现
	string DecToBin(int str)
	{
		string bin = "";
		while (str >= 1)
		{
			bin = to_string(str % 2) + bin;
			str = str / 2;
		}
		return bin;
	}

	// 十六进制转换为十进制的函数实现
	int HexToDec(string str)
	{
		int dec = 0;
		for (int i = 0; i < str.size(); i++)
		{
			if (str[i] >= 'A' && str[i] <= 'F')
			{
				dec += (str[i] - 'A' + 10) * pow(16, str.size() - i - 1);
			}
			else if (str[i] >= 'a' && str[i] <= 'f')
			{
				dec += (str[i] - 'a' + 10) * pow(16, str.size() - i - 1);
			}
			else
			{
				dec += (str[i] - '0') * pow(16, str.size() - i - 1);
			}
		}
		return dec;
	}

	// 十进制转换为十六进制的函数实现
	string DecToHex(int str)
	{
		string hex = "";
		int temp = 0;
		while (str >= 1)
		{
			temp = str % 16;
			if (temp < 10 && temp >= 0)
			{
				hex = to_string(temp) + hex;
			}
			else
			{
				hex += ('A' + (temp - 10));
			}
			str = str / 16;
		}
		return hex;
	}

	string padding(string str)
	{ // 对数据进行填充
		string res = "";
		for (int i = 0; i < str.size(); i++)
		{ // 首先将输入值转换为16进制字符串
			res += DecToHex((int)str[i]);
		}
		// cout << "输入字符串的ASCII码表示为:" << endl;
		/*
		   for (int i = 0; i < res.size(); i++) {
		   cout << res[i];
		   if ((i + 1) % 8 == 0) {
		   cout << "  ";
		   }
		   if ((i + 1) % 64 == 0 || (i + 1) == res.size()) {
		   cout << endl;
		   }
		   }
		   cout << endl;
		   */
		int res_length = res.size() * 4; // 记录的长度为2进制下的长度
		res += "8";						 // 在获得的数据后面添1,在16进制下相当于是添加8
		while (res.size() % 128 != 112)
		{
			res += "0"; // “0”数据填充
		}
		string res_len = DecToHex(res_length); // 用于记录数据长度的字符串
		while (res_len.size() != 16)
		{
			res_len = "0" + res_len;
		}
		res += res_len;
		return res;
	}

	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 AND(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] == '1' && res2[i] == '1')
			{
				res += "1";
			}
			else
			{
				res += "0";
			}
		}
		return BinToHex(res);
	}

	string OR(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] == '0' && res2[i] == '0')
			{
				res += "0";
			}
			else
			{
				res += "1";
			}
		}
		return BinToHex(res);
	}

	string NOT(string str)
	{ // 实现非操作
		string res1 = HexToBin(str);
		string res = "";
		for (int i = 0; i < res1.size(); i++)
		{
			if (res1[i] == '0')
			{
				res += "1";
			}
			else
			{
				res += "0";
			}
		}
		return BinToHex(res);
	}

	char binXor(char str1, char str2)
	{ // 实现单比特的异或操作
		return str1 == str2 ? '0' : '1';
	}

	char binAnd(char str1, char str2)
	{ // 实现单比特的与操作
		return (str1 == '1' && str2 == '1') ? '1' : '0';
	}

	string ModAdd(string str1, string str2)
	{ // mod 2^32运算的函数实现
		string res1 = HexToBin(str1);
		string res2 = HexToBin(str2);
		char temp = '0';
		string res = "";
		for (int i = res1.size() - 1; i >= 0; i--)
		{
			res = binXor(binXor(res1[i], res2[i]), temp) + res;
			if (binAnd(res1[i], res2[i]) == '1')
			{
				temp = '1';
			}
			else
			{
				if (binXor(res1[i], res2[i]) == '1')
				{
					temp = binAnd('1', temp);
				}
				else
				{
					temp = '0';
				}
			}
		}
		return BinToHex(res);
	}

	string P1(string str)
	{ // 实现置换功能P1(X)
		return XOR(XOR(str, LeftShift(str, 15)), LeftShift(str, 23));
	}

	string P0(string str)
	{ // 实现置换功能P0(X)
		return XOR(XOR(str, LeftShift(str, 9)), LeftShift(str, 17));
	}

	string T(int j)
	{ // 返回Tj常量值的函数实现
		if (0 <= j && j <= 15)
		{
			return "79CC4519";
		}
		else
		{
			return "7A879D8A";
		}
	}

	string FF(string str1, string str2, string str3, int j)
	{ // 实现布尔函数FF功能
		if (0 <= j && j <= 15)
		{
			return XOR(XOR(str1, str2), str3);
		}
		else
		{
			return OR(OR(AND(str1, str2), AND(str1, str3)), AND(str2, str3));
		}
	}

	string GG(string str1, string str2, string str3, int j)
	{ // 实现布尔函数GG功能
		if (0 <= j && j <= 15)
		{
			return XOR(XOR(str1, str2), str3);
		}
		else
		{
			return OR(AND(str1, str2), AND(NOT(str1), str3));
		}
	}
	string extension(string str)
	{					  // 消息扩展函数
		string res = str; // 字符串类型存储前68位存储扩展字W值
		for (int i = 16; i < 68; i++)
		{ // 根据公式生成第17位到第68位的W值
			res += XOR(XOR(P1(XOR(XOR(res.substr((i - 16) * 8, 8), res.substr((i - 9) * 8, 8)), LeftShift(res.substr((i - 3) * 8, 8), 15))), LeftShift(res.substr((i - 13) * 8, 8), 7)), res.substr((i - 6) * 8, 8));
		}
		// cout << "扩展后的消息:" << endl;
		// cout << "W0,W1,……,W67的消息:" << endl;
		/*
		   for (int i = 0; i < 8; i++) {
		   for (int j = 0; j < 8; j++) {
		   cout << res.substr(i * 64 + j * 8, 8) << "  ";
		   }
		   cout << endl;
		   }
		   cout << res.substr(512, 8) << "  " << res.substr(520, 8) << "  " << res.substr(528, 8) << "  " << res.substr(536, 8) << endl;
		   cout << endl;
		   */
		for (int i = 0; i < 64; i++)
		{ // 根据公式生成64位W'值
			res += XOR(res.substr(i * 8, 8), res.substr((i + 4) * 8, 8));
		}
		/*
		   cout << "W0',W1',……,W63'的消息:" << endl;
		   for (int i = 0; i < 8; i++) {
		   for (int j = 0; j < 8; j++) {
		   cout << res.substr(544+i * 64 + j * 8, 8) << "  ";
		   }
		   cout << endl;
		   }
		   cout << endl;
		   */
		return res;
	}

	string compress(string str1, string str2)
	{ // 消息压缩函数
		string IV = str2;
		string A = IV.substr(0, 8), B = IV.substr(8, 8), C = IV.substr(16, 8), D = IV.substr(24, 8), E = IV.substr(32, 8), F = IV.substr(40, 8), G = IV.substr(48, 8), H = IV.substr(56, 8);
		string SS1 = "", SS2 = "", TT1 = "", TT2 = "";
		/*
		   cout << "迭代压缩中间值: " << endl;
		   cout << "    A         B         C         D         E         F        G         H " << endl;
		   cout << A << "  " << B << "  " << C << "  " << D << "  " << E << "  " << F << "  " << G << "  " << H << endl;
		   */
		for (int j = 0; j < 64; j++)
		{
			SS1 = LeftShift(ModAdd(ModAdd(LeftShift(A, 12), E), LeftShift(T(j), (j % 32))), 7);
			SS2 = XOR(SS1, LeftShift(A, 12));
			TT1 = ModAdd(ModAdd(ModAdd(FF(A, B, C, j), D), SS2), str1.substr((j + 68) * 8, 8));
			TT2 = ModAdd(ModAdd(ModAdd(GG(E, F, G, j), H), SS1), str1.substr(j * 8, 8));
			D = C;
			C = LeftShift(B, 9);
			B = A;
			A = TT1;
			H = G;
			G = LeftShift(F, 19);
			F = E;
			E = P0(TT2);
			// cout << A << "  " << B << "  " << C << "  " << D << "  " << E << "  " << F << "  " << G << "  " << H << endl;
		}
		string res = (A + B + C + D + E + F + G + H);
		// cout << endl;
		return res;
	}

	string iteration(string str)
	{ // 迭代压缩函数实现
		int num = str.size() / 128;
		// cout << "消息经过填充之后共有 " + to_string(num) + " 个消息分组。" << endl;
		// cout << endl;
		string V = "7380166F4914B2B9172442D7DA8A0600A96F30BC163138AAE38DEE4DB0FB0E4E";
		string B = "", extensionB = "", compressB = "";
		for (int i = 0; i < num; i++)
		{
			// cout << "第 " << to_string(i+1) << " 个消息分组:" << endl;
			// cout << endl;
			B = str.substr(i * 128, 128);
			extensionB = extension(B);
			compressB = compress(extensionB, V);
			V = XOR(V, compressB);
		}
		return V;
	}

	string sm3(const string str)
	{
		string paddingValue = padding(str);
		return iteration(paddingValue);
	}
}

string sm3::sm3(const string str);

int main()
{ // 主函数
	string str = "abc";
	cout << "str:" << str << " sm3: " << sm3::sm3(str) << endl;
}

到了这里,关于sm3加密(32位哈希,64位十六进制数据)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JS十六进制,CRC冗余,小程序发送蓝牙数据,十六进制GBK编码转换等

    小程序问题:https://kf.qq.com/faq/170705YVZFZZ170705eyI7Rr.html 调用: 注意:这里的true和false代表是否大端小端转换 调用: 调用: 调用: 调用: 调用: 此代码写到小程序utils目录下的utuils.js文件中 调用:页面最上边先引入,然后再使用 调用: 这里发送buffer1给小程序公用api就可 调

    2024年02月16日
    浏览(73)
  • JS十六进制转浮点、字符串转为ArrayBuffer、ArrayBuffer转16进制字符串、16进制转10进制、crc校验位、十六进制转中文字符串(小程序、浏览器)、十六进制字符串转ascall字串

    h5实现一键复制文本到剪切板 ArrayBuffer转16进制字符串: 字符串转为ArrayBuffer对象 十六进制转10进制 浮点型转十六进制: 将某段字符串使用某字符补齐 十六进制转带符号(-负号)整型 带符号(负号)整数转十六进制字符串(得到8个字符十六进制字符串) 带符号(负号)整数转

    2024年02月09日
    浏览(54)
  • 十六进制转换到十进制(java)

    一、前言  首先我们要知道十六进制的转换以及十以上的进制的转换与十以下的进制转换是不一样的,它们在一位上会用超过9的数字,这个我们在利用以前的方法就行不通了,我接下来就向大家分享一种方法。(注:在Java中10---15分别用A B C D E F表示,不分大小写) 二、正文

    2024年02月11日
    浏览(58)
  • python实现十六进制转十进制

    先来看下十六进制的定义以及表示方式,以下是百度百科上的解释: 十六进制 (简写为 hex 或下标16)是一种基数为16的计数系统,是一种逢16进1的进位制。通常用数字0、1、2、3、4、5、6、7、8、9和字母A、B、C、D、E、F(a、b、c、d、e、f)表示,其中:A~F表示10~15,这些称作

    2023年04月19日
    浏览(50)
  • 【FPGA仿真】Matlab生成二进制、十六进制的txt数据以及Vivado读取二进制、十六进制数据并将结果以txt格式保存

    在使用Vivado软件进行Verilog程序仿真时可能需要对模块输入仿真的数据,因此我们需要一个产生数据的方法(二进制或者十六进制的数据),Matlab软件是一个很好的工具,当然你也可以使用VS等工具。 以下分别给出了使用Matlab模拟产生二进制和十六进制数据的例子,例子仅供参

    2024年02月01日
    浏览(61)
  • MATLAB十六进制与十进制互相转换

    包含单个数字进行转换和数组进行转换(可用于串口数据解析) 1.十六进制转十进制

    2024年01月16日
    浏览(54)
  • C语言:十进制与十六进制的转化

    要将十进制数转换为十六进制数, 可以使用以下步骤: 1. 将十进制数除以 16,得到商和余数。 2. 用余数作为当前位的十六进制数位,余数可能是 0 到 15 之间的数字,分别对应 0 到 F。 3. 将商作为新的十进制数,并重复步骤 1 和 2,直到商为 0。 4. 将得到的十六进制数位按照

    2024年02月05日
    浏览(78)
  • Python hex()十六进制转换

    Python hex() 函数用于将整数转换为以“0x”为前缀的小写十六进制字符串: 输出: 十六进制 到 十进制 使用 int() 函数 ,第一个参数是字符串 ‘0Xff’ ,第二个参数是说明,这个字符串是几进制的数。 转化的结果是一个十进制数。 二进制 到 十进制 八进制 到 十进制 其实可以看

    2024年02月11日
    浏览(49)
  • PYTHON : 二进制 、 八进制 、十六进制的转换和输出

    十进制转换成其他进制 保存为文本串 二进制 bIn() 八进制 oct() 十六进制 hex() 不输出前缀 使用format函数 如果不想输出进制前面的 前缀符号 , 这时我们就要使用format函数 在这里我们要注意 , 二进制和八进制 的再format里的 符号是‘b’,‘o’ 而十六进制format 里的符

    2023年04月09日
    浏览(78)
  • Java中十六进制与十进制之间互相转换

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 提示:以下是本篇文章正文内容,下面案例可供参考 话不多说,直接上代码 如将十进制数字 108 转换为十六进制 代码示例如下: 运行结果: 这样将一个十

    2024年02月12日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包