基于SM3的HMAC算法的实现


一、SM3算法描述

算法的输入长度为L比特,1<=L<=2^64-1,输出哈希值长度为256比特。(具体参考现代密码学第四版)

二、HMAC算法描述

在这里插入图片描述

算法输出表达式如下:
HMACk=H [ ( k2⊕opad ) || H [ (k2⊕ipad) || M ] ]
HMAC函数中的代码主要是按照这个表达式来写,具体可看注释。
这里的k2是原密钥经过扩展以后得到的,代码中用的长度为512比特。
初始密钥k的长度随机,如果长度大于b(b为一个分组的比特数)则先进行哈希,再补0;如果长度小于b,直接在左边补0。

算法的C++实现

SM3实现部分代码如下(示例):

string SM3(string M) {
	//cout << "输入消息为字符串: " + M << endl;
	//cout << endl;
	string paddingValue = padding(M);
	string result = iteration(paddingValue);
	cout << "杂凑值:" << endl;
	for (int i = 0; i < 8; i++) {
		cout << result.substr(i * 8, 8) << "  ";
	}
	cout << endl;
	cout << endl;
	return result;
}

HMAC算法的代码实现

string HMAC(string k, string M) {//暂且当密钥长度小于b,不需要哈希和填充
	
	string k2 = paddingk(k);
	cout << "填充后的k是:" << endl;
	
	for (int i = 0; i <8; i++) {
		cout << k2.substr(i * 8, 8) << "  ";
	}
	cout << endl;
	for (int j = 8; j < 16; j++) {
		cout << k2.substr(j * 8, 8) << "  ";
	}
	cout << endl;
	int b = 512;
	//padding(M);//对消息进行填充
	string ipad = "00110110";
	string opad = "01011010";
	for (int i = 0; i < b / 8; i++) {
		ipad += "00110110";
		opad += "01011010";
	}
	string si = XOR(k2, BinToHex(ipad));//此时为16进制
	string M1 = si + M;
	string s0 = XOR(k2, opad);
	cout << "这里是对(k2异或ipad)与M链接进行哈希" << endl;
	cout << endl;
	string M2 = SM3(M1);//16进制
	cout << "这是最后一步哈希,产生最终结果" << endl;
	cout << endl;
	string HMACM = SM3(s0+M2);
	return HMACM;
}

主函数

int main() {
	string k;
	string M;
	cout << "请输入密钥k(以16进制)";
	cin >> k;
	cout << "请输入消息";
	cin >> M;
	string HMACk = HMAC(k, M);
	cout << "最终的输出为:" << endl;
	for (int i = 0; i < 8; i++) {
		cout << HMACk.substr(i * 8, 8) << "  ";
	}
	cout << endl;

	return 0;
}

各种辅助的小函数

//二进制转换为十六进制函数实现
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 {
			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 {
			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';
}

//mod 2^32运算的函数实现
string ModAdd(string str1, string str2) {
	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);
}

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

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

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

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

//实现布尔函数GG功能
string GG(string str1, string str2, string str3, int j) {
	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 IV = "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, IV);
		IV = XOR(IV, compressB);
	}
	return IV;
}

总结

这是密码学实验的实验题,代码里的print函数没有用可以不写,感谢CSDN里的大佬写的SM3的代码,救了我一条狗命。
放个链接https://blog.csdn.net/nicai_hualuo/article/details/121555000

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: C语言中的hmacHMAC-SM3)是基于SM3哈希算法的一种消息认证码算法HMAC(Hash-based Message Authentication Code)是一种密钥相关的哈希算法,常用于对消息进行完整性验证和身份认证。 在C语言中使用HMAC-SM3算法实现过程如下: 1. 导入相关的头文件和库:需要包含SM3算法HMAC算法的头文件,并引用相关的库文件。 2. 定义HMAC-SM3算法的输入参数:HMAC-SM3算法的输入参数包括消息m、密钥k以及其他相关的参数。 3. 执行HMAC-SM3算法的核心步骤: a. 首先根据密钥k生成两个不同的密钥分别称为ipad和opad,其中ipad是使用0x36填充的密钥,opad是使用0x5C填充的密钥。 b. 对ipad和opad分别与消息m进行异或运算。 c. 将异或运算结果进行SM3哈希运算得到两个中间结果。 d. 将两个中间结果通过拼接等操作得到最终的HMAC-SM3结果。 4. 返回HMAC-SM3结果。 需要注意的是,由于SM3HMAC都是通过调用底层的哈希算法实现的,因此在实现HMAC-SM3时需要确保SM3算法已经正确地实现并可用。 以上就是C语言中基于SM3HMAC算法实现过程,通过HMAC-SM3可以有效地对消息进行认证和完整性验证,以确保消息的安全性和可靠性。 ### 回答2: C语言中的HMAC算法基于SM3是一种应用于消息认证的方法。HMAC(Hash-based Message Authentication Code)是一种在消息传输中对数据完整性和真实性进行验证的技术。SM3是国家密码管理局(SCCA)发布的一种密码杂凑算法。 在C语言中实现基于SM3HMAC算法,需要先实现SM3算法的相关函数。SM3算法是一种基于SHA-256的密码杂凑算法,可以通过调用已有的SHA-256函数库来实现。在C语言中,可以使用OpenSSL库中的函数,例如EVP_sha256_init()、EVP_sha256_update()和EVP_sha256_final()等来计算SM3算法的哈希值。 接下来,可以使用C语言中的函数来实现HMAC算法HMAC算法需要用到SM3算法来计算哈希值,并将其与密钥进行异或运算。具体步骤如下: 1. 导入所需的函数库,包括SHA-256和HMAC实现。 2. 定义输入数据的消息和密钥。 3. 调用SM3哈希函数计算消息的哈希值。 4. 将密钥填充到与哈希算法的块大小相等的长度,如果密钥长度超过块大小,则需要先将密钥进行哈希化,然后填充到块大小。 5. 在填充后的密钥中执行异或运算,结果作为内部密钥。 6. 将内部密钥与外部密钥做异或运算。 7. 使用SM3哈希算法对异或结果进行迭代哈希计算,得到最终的HMAC结果。 通过以上步骤,可以在C语言中实现基于SM3HMAC算法。注意,为了确保安全性和正确性,建议使用经过验证的算法和库函数,并遵循密码学安全的最佳实践,以防止潜在的安全漏洞。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值