SM3杂凑算法
文章目錄
- 題目
- 環(huán)境
- 方案設(shè)計
- 背景
- 原理
- 算法步驟
- 方案實現(xiàn)
- 流程圖
- 主要函數(shù)
- C代碼
- 測試
- 數(shù)據(jù)
- 結(jié)果
- 注意問題
- 說明
題目
給出16進(jìn)制消息m,用SM3密碼雜湊算法計算Hash值。
環(huán)境
Windows10,MinGW-W64-builds-4.3.5,miracl 7.0.1
方案設(shè)計
背景
SM3密碼雜湊算法
原理
對長度為 ? (? < ???)比特的消息?,SM3雜湊算法經(jīng)過填充和迭代壓縮,生成雜湊值,雜湊值長度為256比特。
算法步驟
假設(shè)消息?的長度為?比特。首先將比特“1”添加到消息的末尾,再添加?個“0”, ? 是滿足?+?+? ≡ ??? ?????? 的最小的非負(fù)整數(shù)。然后再添加一個64位比特串,該比特串是長度?的二進(jìn)制表示。填充后的消息 ?′的比特長度為512的倍數(shù)。
將填充后的消息 ?′按512比特進(jìn)行分組: ?′= ?? ?? ? ???? 其中 ? = (?+?+??)/???。
將消息分組??按以下方法擴(kuò)展生成132個字??,??,?,???,?’?,?’?, ?,?’??用于壓縮函數(shù)??:
a) 將消息分組??劃分為16個字??,??,?,??5。
b) ??? ? = ?? ?? ??
?? ← ??(?????⊕????⊕(???? ? ??))⊕(?????? ?) ⊕????
??????
c) ??? ? = ? ?? ??
?’j = ?? ⊕ ??+?
??????
對?′按下列方式迭代:
??? ? = ? ?? ???
?(?+?) = ??(?(?);?(?))
??????
其中??是壓縮函數(shù),?(?)為256比特初始值 IV ,?(?)為填充后的 消息分組,迭代壓縮的結(jié)果為?(?)。
壓縮函數(shù):
令A(yù),B,C,D,E,F,G,H為字寄存器,SS1,SS2,TT1,TT2為中間變量,壓縮函數(shù)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)
方案實現(xiàn)
流程圖
主要函數(shù)
- void sftbit(big x, int n, big z); 將一個大數(shù)左移或右移n位,n為正數(shù)時左移,負(fù)數(shù)時右移
- void incr(big x, int n, big z); 將一個大數(shù)加上一個整數(shù), z=x+n
- int numdig(big x); 返回大數(shù)x中數(shù)字的個數(shù)
C代碼
#include <stdio.h> #include "miracl.h" #include <stdlib.h>#define N 3 #define NUM_W 132mr_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] = 0xda8a0600;v[0][4] = 0xa96f30bc; v[0][5] = 0x163138aa; v[0][6] = 0xe38dee4d; v[0][7] = 0xb0fb0e4e;FILE *fp;fp = fopen("data.txt", "r");mip->IOBASE = 16;cinnum(m, fp);fclose(fp);printf("m = ");cotnum(m, stdout);// 填充len = numdig(m)*4; sftbit(m, 1, m);incr(m, 1, m);if (len % 512 < 448){n = len/512 + 1; sftbit(m, 511-(len%512), m); }else {n = len/512 + 2; sftbit(m, 1023-(len%512), m);} incr(m, len, m);printf("m'= ");cotnum(m, stdout); printf("n=%d, len=%d\n",n,len); // 將m按字分割存入數(shù)組bp = m->w;for (i = n-1; i >=0; i--){for (j = 15; j >= 0; j--){b[i][j] = *p++;} }puts("\nB(i)=");for (i = 0; i < n; i++){for (j = 0; j < 16; j++){printf("%08x ", b[i][j]);if ((j+1)%8 == 0) putchar('\n');} }for (i = 0; i < n; i++) {BtoW(i, b, W); // 將消息分組??擴(kuò)展生成132個字CF(i, v, W); // 迭代壓縮}printf("\ny= ");for (j = 0; j < 8; j++) {printf("%08x ", v[n][j]);}mirexit();return 0; }void BtoW(int i, mr_small b[][16], mr_small *W) {int j;for (j = 0; j < 16; j++) {W[j] = b[i][j];}for (j = 16; j < 68; j++) {W[j] = P1(W[j-16]^W[j-9]^move(W[j-3], 15))^move(W[j-13], 7)^W[j-6];}for (j = 0; j < 64; j++) {W[j+68] = W[j]^W[j+4];}printf("\nW(%d)= \n", i+1);for (j = 0; j < NUM_W; j++) {printf("%08x ",W[j]);if ((j+1)%8==0 && j<68 || j==67 || (j-67)%8==0 && j>67 ){putchar('\n');}}} void CF(int i, mr_small V[][8], mr_small *W) {mr_small R[8], ST[4];int j; int t; printf("\n j A B C D E F G H\n ");for (j = 0; j < 8; j++) {R[j] = V[i][j];printf("%08x ",R[j]); }putchar('\n');for (j = 0; j < 64; j++) { ST[0] = move(move(R[0], 12)+R[4]+move(Tj(j), j), 7);ST[1] = ST[0] ^ move(R[0], 12); ST[2] = FF(j, R[0], R[1], R[2]) + R[3] + ST[1] + W[j+68];ST[3] = GG(j, R[4], R[5], R[6]) + R[7] + ST[0] + W[j];R[3] = R[2]; R[2] = move(R[1], 9);R[1] = R[0];R[0] = ST[2];R[7] = R[6];R[6] = move(R[5], 19);R[5] = R[4];R[4] = P0(ST[3]); printf("%2d ",j);for(t=0;t<8;t++) printf("%08x ",R[t]);putchar('\n');}for (j = 0; j < 8; j++) {V[i+1][j] = V[i][j] ^ R[j];}}mr_small FF(int j, mr_small x, mr_small y, mr_small z) {if (j < 16 && j >= 0) {return x^y^z;} if(j >=16 && j < 64) {return (x&y)|(x&z)|(y&z);}return -1; } mr_small GG(int j, mr_small x, mr_small y, mr_small z) {if (j < 16 && j >= 0) {return x^y^z;} if(j >=16 && j < 64) {return (x&y)|(~x&z);}return -1; } mr_small move(mr_small x, int n) {mr_small y , z; y = x << n;z = x >> (sizeof(x)*8-n);z = y | z;return z; } mr_small P0(mr_small x) {return x^move(x, 9)^move(x, 17); } mr_small P1(mr_small x) {return x^move(x, 15)^move(x, 23); } mr_small Tj(int j) {if (j >=0 && j <16){return 0x79cc4519;}if (j >=16 && j <64){return 0x7a879d8a;}return -1; }測試
數(shù)據(jù)
512比特消息
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
填充后的消息
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
80000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
80000000 00000000 00000000 00000000 00000000 00000000 00000000 00000200
雜湊值
debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
結(jié)果
注意問題
因為一個字的長度為32 bits,可以用無符號整型unsigned int表示。所以把大數(shù)分割成無符號整型數(shù)組便于運算,大數(shù)結(jié)構(gòu)體內(nèi)有兩個成員,分別為長度和數(shù)組/指針(小端存儲),通過unsigned int指針可以很方便的訪問該數(shù)組,按字取出并放入用于運算的數(shù)組B。
說明
課程作業(yè),僅作記錄
總結(jié)
- 上一篇: 纸质办公电子化——iWebOffice中
- 下一篇: 好程序员Java教程分享javaweb框