/// sm3.h 头文件 #pragma once #include <cstdint> namespace sm3 { /// interface funcName of SM3 extern void SM3Hash(const unsigned char* m, const int ml, unsigned char r[32]); } /// sm3.cpp实现文件
#include "sm3.h" #include <memory> #include <cstring> namespace sm3 { static 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 }; /// 循环左移 static uint32_t SL(uint32_t X, int n) { uint64_t x = X; x <<= (n % 32); uint32_t l = (uint32_t)(x >> 32); return x | l; } static uint32_t Tj(int j) { return (j <= 15) ? 0x79cc4519 : 0x7a879d8a; } static uint32_t FFj(int j, uint32_t X, uint32_t Y, uint32_t Z) { return (j <= 15)? (X ^ Y ^ Z) : ((X & Y) | (X & Z) | (Y & Z)); } static uint32_t GGj(int j, uint32_t X, uint32_t Y, uint32_t Z) { return (j <= 15) ? (X ^ Y ^ Z) : ((X & Y) | (~X & Z)); } static uint32_t P0(uint32_t X) { return X ^ SL(X, 9) ^ SL(X, 17); } static uint32_t P1(uint32_t X) { return X ^ SL(X, 15) ^ SL(X, 23); } /// 扩展 static void EB(const unsigned char Bi[512 / 8], uint32_t W[68], uint32_t W1[64]) { /// Bi 分为W0~W15 for (size_t i = 0; i < 16; ++i) { W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3]; } size_t j; for (j = 16; j < 68; ++j) { W[j] = P1(W[j - 16] ^ W[j - 9] ^ SL(W[j - 3], 15)) ^ SL(W[j - 13], 7) ^ W[j - 6]; } for (j = 0; j < 64; ++j) { W1[j] = W[j] ^ W[j + 4]; } } // 压缩函数 static void CF(const unsigned char Vi[256 / 8], const unsigned char Bi[512 / 8], unsigned char Vi1[256 / 8]) { /// Bi 扩展为132个字 uint32_t W[68] = { 0 }; uint32_t W1[64] = { 0 }; EB(Bi, W, W1); /// 串联 ABCDEFGH = Vi uint32_t R[8] = { 0 }; for (size_t i = 0; i < 8; ++i) { R[i] = ((uint32_t)Vi[i * 4]) << 24 | ((uint32_t)Vi[i * 4 + 1]) << 16 | ((uint32_t)Vi[i * 4 + 2]) << 8 | ((uint32_t)Vi[i * 4 + 3]); } uint32_t A = R[0], B = R[1], C = R[2], D = R[3], E = R[4], F = R[5], G = R[6], H = R[7]; uint32_t SS1, SS2, TT1, TT2; for (int j = 0; j < 64; ++j) { SS1 = SL(SL(A, 12) + E + SL(Tj(j), j), 7); SS2 = SS1 ^ SL(A, 12); TT1 = FFj(j, A, B, C) + D + SS2 + W1[j]; TT2 = GGj(j, E, F, G) + H + SS1 + W[j]; 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 (size_t i = 0; 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 (size_t i = 0; i < 256 / 8; ++i) { Vi1[i] ^= Vi[i]; } } void SM3Hash(const unsigned char* m, const int ml, unsigned char r[32]) { const int l = ml * 8; int k = (448 - 1) - (l % 512);/// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数 if (k <= 0) { k += 512; } const int n = (l + k + 65) / 512; /// 多少个64Bytes的块 // const int m1l = n * (512 / 8); /// 填充后的字节长度,512位的倍数 /// calculate the final 64Bytes data for later usage unsigned char finalBlk[512 / 8] = {0}; const int leftOver = ml % 64; const int startPos = ml - leftOver; memcpy(finalBlk, m + startPos, leftOver); finalBlk[leftOver] = 0x80; /// 消息后补1 /// 再添加一个64位比特串,该比特串是长度l的二进制表示 uint32_t l1 = l; for (int i = 0; i < (64 / 8) && l1 > 0; ++i) { finalBlk[64 - 1 - i] = l1 & 0xFF; l1 >>= 8; } /// 将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n-1),其中n=(l+k+65)/512 unsigned char V0_[256 / 8]; unsigned char V1_[256 / 8] = {0}; /// 初始化 V0 <=== IV memcpy(V0_, IV, 256/8); /// 压缩函数,V 与扩展的B unsigned char* pi_ = V0_; unsigned char* pj_ = V1_; const unsigned char* BPtr = m; /// 初始指向数组首地址 /// 最前面的n-1个块的update处理逻辑 for (int i = 0; i < n - 1; ++i) { CF(pi_, BPtr, pj_); BPtr += 64; /// adjust ptr advancing one block(64bytes) for the next loop /// swap two pointers for the next loop unsigned char* tmp = pi_; pi_ = pj_; pj_ = tmp; } /// 上面循环执行完毕后, pi_将保存最终的结果值, pi_是结果 /// 最后一个填充块的final处理逻辑 CF(pi_, finalBlk, pj_); /// 得到最终结果 memcpy(r, pj_, 32); } }