C语言
#pragma once //C语言实现的一段式SM3算法 #include <stdio.h> #include <memory> //定义初始值IV,初始值IV是一个常数 unsigned char IV[256 / 8]{ 0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00, 0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e }; //循环左移 unsigned long SL(unsigned long X, int n) { /* * long:32位 * __int64:64位 */ unsigned __int64 x = X; x = x << (n % 32); //把要移动的位数的值移动到左32位中去 unsigned long l{ (unsigned long)(x >> 32) }; //把移动的位数的值移动最右边 return x | l; //右边32位组合后,截断前32位。 } //常量判断 unsigned long Tj(int j) { return j <= 15 ? 0x79cc4519 : 0x7a879d8a; } //布尔函数 unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z) { if (j <= 15) { unsigned long ret = X ^ Y ^ Z; return ret; } else { unsigned long ret = (X & Y) | (X & Z) | (Y & Z); return ret; } } //置换函数 unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z) { if (j <= 15) { unsigned long ret = X ^ Y ^ Z; return ret; } else { unsigned long ret = (X & Y) | (~X & Z); return ret; } } unsigned long P0(unsigned long X) { unsigned long ret = X ^ SL(X, 9) ^ SL(X, 17); return ret; } unsigned long P1(unsigned long X) { unsigned long ret = X ^ SL(X, 15) ^ SL(X, 23); return ret; } //拓展 void EB(unsigned char Bi[512 / 8], unsigned long W[68], unsigned long W1[64]) { //Bi分为W0~W15 for (int i{}; i < 16; ++i) { W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3]; } for (int i = 16; i <= 67; ++i) { W[i] = P1(W[i - 16] ^ W[i - 9] ^ SL(W[i - 3], 15)) ^ SL(W[i - 13], 7) ^ W[i - 6]; } for (int i{}; i <= 63; ++i) { W1[i] = W[i] ^ W[i + 4]; } } //压缩函数 void CF(unsigned char Vi[256 / 8], unsigned char Bi[512 / 8], unsigned char Vi1[256 / 8]) { //Bi拓展为132个字 unsigned long W[68]{}; unsigned long W1[68]{}; EB(Bi, W, W1); //串联 ABCDEFG=Vi unsigned long R[8]{}; for (int i{}; i < 8; ++i) { R[i] = ((unsigned long)Vi[i * 4] << 24) | ((unsigned long)Vi[i * 4 + 1] << 16) | ((unsigned long)Vi[i * 4 + 2] << 8) | ((unsigned long)Vi[i * 4 + 3]); } unsigned long A = R[0]; unsigned long B = R[1]; unsigned long C = R[2]; unsigned long D = R[3]; unsigned long E = R[4]; unsigned long F = R[5]; unsigned long G = R[6]; unsigned long H = R[7]; unsigned long SS1{}; unsigned long SS2{}; unsigned long TT1{}; unsigned long TT2{}; for (int i{}; i <= 63; ++i) { SS1 = SL((SL(A, 12) + E + SL(Tj(i), i)), 7); SS2 = SS1 ^ SL(A, 12); TT1 = FFj(i, A, B, C) + D + SS2 + W1[i]; TT2 = GGj(i, E, F, G) + H + SS1 + W[i]; D = C; C = SL(B, 9); B = A; A = TT1; H = G; G = SL(F, 19); F = E; E = P0(TT2); } //Vi1=ABCDEFGH 串联 R[0] = A; R[1] = B; R[2] = C; R[3] = D; R[4] = E; R[5] = F; R[6] = G; R[7] = H; for (int i{}; i < 8; ++i) { Vi1[i * 4] = (R[i] >> 24) & 0xff; Vi1[i * 4 + 1] = (R[i] >> 16) & 0xff; Vi1[i * 4 + 2] = (R[i] >> 8) & 0xff; Vi1[i * 4 + 3] = R[i] & 0xff; } //Vi1=ABCDEFGH^Vi for (int i{}; i < 256 / 8; ++i) { Vi1[i] ^= Vi[i]; } } //参数 sourceData 是原始数据,sourceData_len 是数据长度,out 是输出参数,存放hash结果 void SM3Hash(unsigned char* sourceData, int sourceData_len, unsigned char out[32]) { int sourceLen = sourceData_len * 8; int zero_amount = 448 - 1 - sourceLen % 512;// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数 if (zero_amount <= 0) { zero_amount += 512; } //固定公式 int n = (sourceLen + zero_amount + 65) / 512; int PopulatingSourceData_len = n * 512 / 8; // 填充后的长度,512位的倍数 unsigned char* tempData = new unsigned char[PopulatingSourceData_len] {}; memset(tempData, 0, PopulatingSourceData_len); memcpy(tempData, sourceData, sourceLen / 8); tempData[sourceLen / 8] = 0x80; // 消息后补1 // 再添加一个64位比特串,该比特串是长度l的二进制表示 unsigned long tempLen = sourceLen; for (int i = 0; i < 64 / 8 && tempLen > 0; ++i) { tempData[PopulatingSourceData_len - 1 - i] = tempLen & 0xFF; tempLen = tempLen >> 8; } //将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(sourceLen + zero_amount+65)/512。 unsigned char** B = new unsigned char* [n] {}; for (int i = 0; i < n; ++i) { B[i] = new unsigned char[512 / 8] {}; memcpy(B[i], tempData + (512 / 8) * i, 512 / 8); } delete[] tempData; unsigned char** V = new unsigned char* [n + 1] {}; for (int i = 0; i <= n; ++i) { V[i] = new unsigned char[256 / 8] {}; memset(V[i], 0, 256 / 8); } // 初始化 V0 = VI memcpy(V[0], IV, 256 / 8); // 压缩函数,V 与扩展的B for (int i = 0; i < n; ++i) { CF(V[i], B[i], V[i + 1]); } for (int i = 0; i < n; ++i) { delete[] B[i]; } delete[] B; // V[n]是结果 memcpy(out, V[n], 32); for (int i = 0; i < n + 1; ++i) { delete[] V[i]; } delete[] V; } void dumpbuf(unsigned char* buf, int len) { int line{ 32 }; printf("len=%d\n", len); for (int i{}; i < len; i++) { printf("%02x ", buf[i]); if (i > 0 && (i + 1) % 16 == 0) { putchar('\n'); } } }View Code
C++
#pragma once #include <iostream> #include <vector> #include <string> #include <algorithm> #include ".vs\..\..\my_func\my_function.h" //定义初始值IV,初始值IV是一个常数 std::vector<unsigned char> IV{ 0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00, 0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e }; //常量判断 unsigned long Tj(int j) { return j <= 15 ? 0x79cc4519 : 0x7a879d8a; } //布尔函数 unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z) { if (j <= 15) { unsigned long ret = X ^ Y ^ Z; return ret; } else { unsigned long ret = (X & Y) | (X & Z) | (Y & Z); return ret; } } //置换函数 unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z) { if (j <= 15) { unsigned long ret = X ^ Y ^ Z; return ret; } else { unsigned long ret = (X & Y) | (~X & Z); return ret; } } unsigned long P0(unsigned long X) { unsigned long ret = X ^ MY_TOOLS::ring_shift_left(X, 9) ^ MY_TOOLS::ring_shift_left(X, 17); return ret; } unsigned long P1(unsigned long X) { unsigned long ret = X ^ MY_TOOLS::ring_shift_left(X, 15) ^ MY_TOOLS::ring_shift_left(X, 23); return ret; } /* 拓展 Bi:长度为64 W:长度为68 W1:长度为64 */ void EB(std::vector<unsigned char> &Bi, std::vector<unsigned long> &W, std::vector<unsigned long> &W1) { //Bi分为W0~W15 for (int i{}; i < 16; ++i) { W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3]; } for (int i = 16; i <= 67; ++i) { W[i] = P1(W[i - 16] ^ W[i - 9] ^ MY_TOOLS::ring_shift_left(W[i - 3], 15)) ^ MY_TOOLS::ring_shift_left(W[i - 13], 7) ^ W[i - 6]; } for (int i{}; i <= 63; ++i) { W1[i] = W[i] ^ W[i + 4]; } } /* * 压缩函数 * Vi:长度32 * Bi:长度64 * Vi_1:长度32 */ void CF(std::vector<unsigned char>& Vi, std::vector<unsigned char>& Bi, std::vector<unsigned char>& Vi_1) { //Bi拓展为132个字 std::vector<unsigned long> W(68, 0); std::vector<unsigned long> W1(68, 0); EB(Bi, W, W1); //串联 ABCDEFG=Vi std::vector<unsigned long> R(8, 0); for (int i{}; i < 8; ++i) { R[i] = (static_cast<unsigned long>(Vi[i * 4]) << 24) | (static_cast<unsigned long>(Vi[i * 4 + 1]) << 16) | (static_cast<unsigned long>(Vi[i * 4 + 2]) << 8) | (static_cast<unsigned long>(Vi[i * 4 + 3])); } unsigned long A = R[0]; unsigned long B = R[1]; unsigned long C = R[2]; unsigned long D = R[3]; unsigned long E = R[4]; unsigned long F = R[5]; unsigned long G = R[6]; unsigned long H = R[7]; unsigned long SS1{}; unsigned long SS2{}; unsigned long TT1{}; unsigned long TT2{}; for (int i{}; i <= 63; ++i) { SS1 = MY_TOOLS::ring_shift_left((MY_TOOLS::ring_shift_left(A, 12) + E + MY_TOOLS::ring_shift_left(Tj(i), i)), 7); SS2 = SS1 ^ MY_TOOLS::ring_shift_left(A, 12); TT1 = FFj(i, A, B, C) + D + SS2 + W1[i]; TT2 = GGj(i, E, F, G) + H + SS1 + W[i]; D = C; C = MY_TOOLS::ring_shift_left(B, 9); B = A; A = TT1; H = G; G = MY_TOOLS::ring_shift_left(F, 19); F = E; E = P0(TT2); } //Vi1=ABCDEFGH 串联 R[0] = A; R[1] = B; R[2] = C; R[3] = D; R[4] = E; R[5] = F; R[6] = G; R[7] = H; for (int i{}; i < 8; ++i) { Vi_1[i * 4] = (R[i] >> 24) & 0xff; Vi_1[i * 4 + 1] = (R[i] >> 16) & 0xff; Vi_1[i * 4 + 2] = (R[i] >> 8) & 0xff; Vi_1[i * 4 + 3] = R[i] & 0xff; } //Vi1=ABCDEFGH^Vi for (int i{}; i < 256 / 8; ++i) { Vi_1[i] ^= Vi[i]; } } /* * hash函数 * 参数 sourceData 是原始数据,sourceData_len 是数据长度,out 是输出参数, 存放hash结果,长度为32 */ void SM3Hash(std::vector<unsigned char>& sourceData, int sourceData_len, std::vector<unsigned char>& out) { int sourceLen = sourceData_len * 8; int zero_amount = 448 - 1 - sourceLen % 512;// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数 if (zero_amount <= 0) { zero_amount += 512; } //固定公式 int n = (sourceLen + zero_amount + 65) / 512; int PopulatingSourceData_len = n * 512 / 8; // 填充后的长度,512位的倍数 /*unsigned char* tempData = new unsigned char[PopulatingSourceData_len] {}; memset(tempData, 0, PopulatingSourceData_len); memcpy(tempData, sourceData, sourceLen / 8);*/ std::vector<unsigned char>tempData{ sourceData }; tempData.resize(PopulatingSourceData_len, 0); tempData[sourceLen / 8] = 0x80; // 消息后补1 // 再添加一个64位比特串,该比特串是长度l的二进制表示 unsigned long tempLen = sourceLen; for (int i = 0; i < 64 / 8 && tempLen > 0; ++i) { tempData[PopulatingSourceData_len - 1 - i] = tempLen & 0xFF; tempLen = tempLen >> 8; } //将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(sourceLen + zero_amount+65)/512。 std::vector<std::vector<unsigned char>>B(n); for (int i = 0; i < n; ++i) { B[i].reserve(64); //提前分配存储空间,不过其实差不多的感觉 //tempData是512的倍数,所以也是64的倍数 B[i].insert(B[i].begin(), tempData.begin() + (64 * i), tempData.begin() + (64 * (i + 1))); } //unsigned char** V = new unsigned char* [n + 1] {}; std::vector<std::vector<unsigned char>>V(n + 1); for (int i = 0; i <= n; ++i) { V[i].reserve(32); //分配空间 } // 初始化 V0 = VI V[0].insert(V[0].begin(), IV.begin(), IV.end()); // 压缩函数,V 与扩展的B for (int i = 0; i < n; ++i) { V[i + 1].resize(32, 0); CF(V[i], B[i], V[i + 1]); } // V[n]是结果 //memcpy(out, V[n], 32); out.insert(out.begin(), V[n].begin(), V[n].end()); } /* * 以2位的16进制数输出hash值 */ void dumpbuf(std::vector<unsigned char>& buf, int len) { int line{ 32 }; std::cout << "len = " << len << '\n'; for (int i{}; i < len; i++) { std::cout << std::hex << static_cast<unsigned>(buf[i]) << ' '; if (i > 0 && (i + 1) % 16 == 0) { std::cout << '\n'; } } }View Code
调用
C版:
void main() { unsigned char data[] = "abc", r[32]; printf("消息:%s\nHash结果:\n", data); SM3Hash(data, 3, r); dumpbuf(r, 32); }
C++版
int main() { std::vector<unsigned char> data; std::vector<unsigned char> result; data.push_back('a'); data.push_back('b'); data.push_back('c'); result.reserve(32); std::cout << "消息:" << MY_TOOLS::vecUChar_to_string(data) << "\nHash结果:\n"; SM3Hash(data, data.size(), result); dumpbuf(result, result.size()); }
输出:
消息:abc
Hash结果:
len = 32
66 c7 f0 f4 62 ee ed d9 d1 f2 d4 6b dc 10 e4 e2
41 67 c4 87 5c f2 f7 a2 29 7d a0 2b 8f 4b a8 e0