SM3密码杂凑算法实现及说明
SM3密碼雜湊算法說明:https://wenku.baidu.com/view/8d67d80178563c1ec5da50e2524de518964bd3b6.html?qq-pf-to=pcqq.c2c
術語與定義
1 比特串bit string
由0和1組成的二進制數字序列。
2 大端big-endian
數據在內存中的一種表示格式,規定左邊為高有效位,右邊為低有效位。數的高階字節放在存儲器的低地址,數的低階字節放在存儲器的高地址。
3 消息message
任意有限長度的比特串。本文本中消息作為雜湊算法的輸入數據。
4 雜湊值hash value
雜湊算法作用于消息后輸出的特定長度的比特串。本文本中的雜湊值長度為256比特。
5 字word
長度為32的比特串
符號
常量與函數
1
2
3
4
算法描述
概述
對長度為l(l < 2^64) 比特的消息m, SM3雜湊算法經過填充和迭代壓縮,生成雜湊值,雜湊值長度
為256比特
填充
假設消息m 的長度為l 比特。首先將比特“ 1”添加到消息的末尾,再添加k 個“ 0”, k是滿
足l + 1 + k ≡ 448mod512 的最小的非負整數。然后再添加一個64位比特串,該比特串是長度l的二進
制表示。填充后的消息m′ 的比特長度為512的倍數。
迭代壓縮
1 迭代過程
2 消息擴展
3 壓縮函數
壓縮函數框圖
其中,字的存儲為大端(big-endian)格式
4 雜湊值
SM3算法C實現
sm3.h
/* * sm3.h * * 為使此算法兼容32位、64位下Linux或Windows系統, * 選擇 int 來表示 32 位整數。 * 消息長度最大限定為 2**32 - 1(單位:比特), * 且為 8 的倍數(消息的最小單元為字節)。 */ #ifndef _SM3_H_ #define _SM3_H_/* * SM3算法產生的哈希值大小(單位:字節) */ #define SM3_HASH_SIZE 32 /* * SM3上下文 */ typedef struct SM3Context {unsigned int intermediateHash[SM3_HASH_SIZE / 4];unsigned char messageBlock[64]; } SM3Context;/* * SM3計算函數 */ unsigned char *SM3Calc(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);#endif // _SM3_H_
/* * sm3.c */ #include <stdio.h> #include <memory.h> #include "sm3.h"/* * 判斷運行環境是否為小端 */ static const int endianTest = 1; #define IsLittleEndian() (*(char *)&endianTest == 1)/* * 向左循環移位 */ #define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) )/* * 反轉四字節整型字節序 */ unsigned int *ReverseWord(unsigned int *word) {unsigned char *byte, temp;byte = (unsigned char *)word;temp = byte[0];byte[0] = byte[3];byte[3] = temp;temp = byte[1];byte[1] = byte[2];byte[2] = temp;return word; }/* * T */ unsigned int T(int i) {if (i >= 0 && i <= 15)return 0x79CC4519;else if (i >= 16 && i <= 63)return 0x7A879D8A;elsereturn 0; }/* * FF */ unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i) {if (i >= 0 && i <= 15)return X ^ Y ^ Z;else if (i >= 16 && i <= 63)return (X & Y) | (X & Z) | (Y & Z);elsereturn 0; }/* * GG */ unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i) {if (i >= 0 && i <= 15)return X ^ Y ^ Z;else if (i >= 16 && i <= 63)return (X & Y) | (~X & Z);elsereturn 0; }/* * P0 */ unsigned int P0(unsigned int X) {return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17); }/* * P1 */ unsigned int P1(unsigned int X) {return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23); }/* * 初始化函數 */ void SM3Init(SM3Context *context) {context->intermediateHash[0] = 0x7380166F;context->intermediateHash[1] = 0x4914B2B9;context->intermediateHash[2] = 0x172442D7;context->intermediateHash[3] = 0xDA8A0600;context->intermediateHash[4] = 0xA96F30BC;context->intermediateHash[5] = 0x163138AA;context->intermediateHash[6] = 0xE38DEE4D;context->intermediateHash[7] = 0xB0FB0E4E; }/* * 處理消息塊 */ void SM3ProcessMessageBlock(SM3Context *context) {int i;unsigned int W[68];unsigned int W_[64];unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2;/* 消息擴展 */for (i = 0; i < 16; i++){W[i] = *(unsigned int *)(context->messageBlock + i * 4);if (IsLittleEndian())ReverseWord(W + i);//printf("%d: %x\n", i, W[i]); }for (i = 16; i < 68; i++){W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15))^ LeftRotate(W[i - 13], 7)^ W[i - 6];//printf("%d: %x\n", i, W[i]); }for (i = 0; i < 64; i++){W_[i] = W[i] ^ W[i + 4];//printf("%d: %x\n", i, W_[i]); }/* 消息壓縮 */A = context->intermediateHash[0];B = context->intermediateHash[1];C = context->intermediateHash[2];D = context->intermediateHash[3];E = context->intermediateHash[4];F = context->intermediateHash[5];G = context->intermediateHash[6];H = context->intermediateHash[7];for (i = 0; i < 64; i++){SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7);SS2 = SS1 ^ LeftRotate(A, 12);TT1 = FF(A, B, C, i) + D + SS2 + W_[i];TT2 = GG(E, F, G, i) + H + SS1 + W[i];D = C;C = LeftRotate(B, 9);B = A;A = TT1;H = G;G = LeftRotate(F, 19);F = E;E = P0(TT2);}context->intermediateHash[0] ^= A;context->intermediateHash[1] ^= B;context->intermediateHash[2] ^= C;context->intermediateHash[3] ^= D;context->intermediateHash[4] ^= E;context->intermediateHash[5] ^= F;context->intermediateHash[6] ^= G;context->intermediateHash[7] ^= H; }/* * SM3算法主函數 */ unsigned char *SM3Calc(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]) {SM3Context context;unsigned int i, remainder, bitLen;/* 初始化上下文 */SM3Init(&context);/* 對前面的消息分組進行處理 */for (i = 0; i < messageLen / 64; i++){memcpy(context.messageBlock, message + i * 64, 64);SM3ProcessMessageBlock(&context);}/* 填充消息分組,并處理 */bitLen = messageLen * 8;if (IsLittleEndian())ReverseWord(&bitLen);remainder = messageLen % 64;memcpy(context.messageBlock, message + i * 64, remainder);context.messageBlock[remainder] = 0x80;if (remainder <= 55){/* 長度按照大端法占8個字節,該程序只考慮長度在 2**32 - 1(單位:比特)以內的情況,* 故將高 4 個字節賦為 0 。*/memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4);memcpy(context.messageBlock + 64 - 4, &bitLen, 4);SM3ProcessMessageBlock(&context);}else{memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1);SM3ProcessMessageBlock(&context);/* 長度按照大端法占8個字節,該程序只考慮長度在 2**32 - 1(單位:比特)以內的情況,* 故將高 4 個字節賦為 0 。*/memset(context.messageBlock, 0, 64 - 4);memcpy(context.messageBlock + 64 - 4, &bitLen, 4);SM3ProcessMessageBlock(&context);}/* 返回結果 */if (IsLittleEndian())for (i = 0; i < 8; i++)ReverseWord(context.intermediateHash + i);memcpy(digest, context.intermediateHash, SM3_HASH_SIZE);return digest; } sm3test.c
#include <string.h> #include <stdio.h> #include "sm3.h" #include <iostream>//#pragma comment(lib,"sm3dll2") //extern "C" void SM3Call(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);int main( int argc, char *argv[] ) {unsigned char input[256] = "abc";int ilen = 3;unsigned char output[32];int i;// ctx;printf("Message:\n");printf("%s\n",input);SM3Calc(input, ilen, output);printf("Hash:\n ");for(i=0; i<32; i++){printf("%02x",output[i]);if (((i+1) % 4 ) == 0) printf(" ");} printf("\n");unsigned char input2[256] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";int ilen2 = 64;unsigned char output2[32];int i2;// ctx;printf("Message:\n");printf("%s\n", input2);SM3Calc(input2, ilen2, output2);printf("Hash:\n ");for (i2 = 0; i2<32; i2++){printf("%02x", output2[i2]);if (((i2 + 1) % 4) == 0) printf(" ");}printf("\n");system("pause"); }
總結
以上是生活随笔為你收集整理的SM3密码杂凑算法实现及说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SM3算法 C语言 (从OpenSSL库
- 下一篇: 手眼标定(eye in hand)-步骤