题目
给出16进制消息m,用SM3密码杂凑算法计算Hash值。
环境
Windows10,MinGW-W64-builds-4.3.5,miracl 7.0.1
方案设计
背景
SM3密码杂凑算法
原理
对长度为 ? (? < ???)比特的消息?,SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度为256比特。
算法步骤
- 填充
假设消息?的长度为?比特。首先将比特“1”添加到消息的末尾,再添加?个“0”, ? 是满足?+?+? ≡ ??? ?????? 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度?的二进制表示。填充后的消息 ?′的比特长度为512的倍数。 - 扩展
将填充后的消息 ?′按512比特进行分组: ?′= ?? ?? ⋯ ??−? 其中 ? = (?+?+??)/???。
将消息分组??按以下方法扩展生成132个字??,??,⋯,???,?’?,?’?, ⋯,?’??用于压缩函数??:
a) 将消息分组??划分为16个字??,??,⋯,??5。
b) ??? ? = ?? ?? ??
?? ← ??(??−??⊕??−?⊕(??−? ⋘ ??))⊕(??−??⋘ ?) ⊕??−?
??????
c) ??? ? = ? ?? ??
?’j = ?? ⊕ ??+?
?????? - 迭代压缩
对?′按下列方式迭代:
??? ? = ? ?? ?−?
?(?+?) = ??(?(?);?(?))
??????
其中??是压缩函数,?(?)为256比特初始值 IV ,?(?)为填充后的 消息分组,迭代压缩的结果为?(?)。
压缩函数:
令A,B,C,D,E,F,G,H为字寄存器,SS1,SS2,TT1,TT2为中间变量,压缩函数V i+1 = CF(V (i),B(i)), 0 ≤ i ≤ n−1。计算过程描述如下:
ABCDEFGH ← V (i)
FOR j=0 TO 63
SS1 ← ((A ≪ 12) + E + (Tj ≪ j)) ≪ 7
SS2 ← SS1⊕(A ≪ 12)
TT1 ← FFj(A,B,C) + D + SS2 + W’j
TT2 ← GGj(E,F,G) + H + SS1 + Wj
D ← C
C ← B ≪ 9
B ← A
A ← TT1
H ← G
G ← F ≪ 19
F ← E
E ← P0(TT2)
ENDFOR
V (i+1) ← ABCDEFGH⊕V (i)
方案实现
流程图
主要函数
- void sftbit(big x, int n, big z); 将一个大数左移或右移n位,n为正数时左移,负数时右移
- void incr(big x, int n, big z); 将一个大数加上一个整数, z=x+n
- int numdig(big x); 返回大数x中数字的个数
C代码
#include <stdio.h>
#include "miracl.h"
#include <stdlib.h>
#define N 3
#define NUM_W 132
mr_small GG(int j, mr_small x, mr_small y, mr_small z);
mr_small FF(int j, mr_small x, mr_small y, mr_small z);
void BtoW(int i, mr_small b[][16], mr_small *W);
void CF(int i, mr_small V[][8], mr_small *W);
mr_small move(mr_small x, int n);
mr_small P0(mr_small x);
mr_small P1(mr_small x);
mr_small Tj(int j);
void str2hex(char *str, char *hex)
{
char *p = hex;
int i;
for(i=0;str[i];i++){
sprintf(p, "%02x",str[i]);
p+=2;
}
*p='\0';
// puts(hex);
}
int main(void)
{
miracl *mip = mirsys(5000,16);
int i, j, n; unsigned long long len;
mr_small W[NUM_W]={
0}, b[N][16]={
0}, v[N+1][8], *p;
big m;
m = mirvar(0);
v[0][0] = 0x7380166f; v[0][1] = 0x4914b2b9; v[0][2] = 0x172442d7; v[0][3