https://github.com/Tyrone-Zhao/Algorithm/tree/master/sm3
1.python中的非为补码非,需要自己编写按位非
2.算法为大端运算,用python编写算法时需要在把输入数据转换成bytes后,从bytes读取大端数据,使用int.from_bytes(data, “big”)方法
3.因为是采用寄存器机制,所以在python中需要使用list类型来实现, 并且设定最大值为2 ** 32,在做加法运算时需要取余
import binascii
import sys
import pysnooper
class SM3:
MAX = 2 ** 32
IV = "7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e"
def __init__(self, string):
self.input = string
self.b_input = bytes(self.input, "utf-8")
self.hex_input = hex(int.from_bytes(self.b_input, "big"))[2:] # 按照大端计算
@property
def hash(self):
"""
获取结果Hash值
:return: 256位16进制hash值
"""
return self.iterationCourse(self.fill(self.hexToBin(self.hex_input)))[-1]
def getT(self, j):
"""
常量
:param j:
:return: 79cc4519 (0 <= j <= 15), 7a879d8a (16 <= j <= 63)
"""
if 0 <= j <= 15:
return int("79cc4519", 16)
elif 16 <= j <= 63:
return int("7a879d8a", 16)
def FF(self, X, Y, Z, j):
"""
布尔函数
:param X: 16进制string
:param Y: 16进制string
:param Z: 16进制string
:return: X ^ Y ^ Z (0 <= j <= 15), (X & Y) | (X & Z) | (Y & Z) (16 <= j <= 63)
"""
if 0 <= j <= 15:
return X ^ Y ^ Z
elif 16 <= j <= 63:
return (X & Y) | (X & Z) | (Y & Z)
else:
return 0
def GG(self, X, Y, Z, j):
"""
布尔函数
:param X: 16进制string
:param Y: 16进制string
:param Z: 16进制string
:return: X ^ Y ^ Z (0 <= j <= 15), (X & Y) | (~X & Z) (16 <= j <= 63)
"""
if 0 <= j <= 15:
return X ^ Y ^ Z
elif 16 <= j <= 63:
return (X & Y) | (self.non(X) & Z)
else:
return 0
def P0(self, X):
"""
置换函数
:param X: 整数值
:return: X ^ (X <<< 9) ^ (X <<< 17)
"""
return X ^ self.leftRotate(X, 9) ^ self.leftRotate(X, 17)
def P1(self, X):
"""
置换函数
:param X: 整数值
:return: X ^ (X <<< 15) ^ (X <<< 23)
"""
return X ^ self.leftRotate(X, 15) ^ self.leftRotate(X, 23)
def leftRotate(self, X, k):
"""
循环左移
:param X: 整数值
:param k: 位移的位数
:param bit: 整数对应二进制的位数
:return: 二进制左移k位的整数值
"""
res = list(self.intToBin(X))
for i in range(k):
temp = res.pop(0)
res.append(temp)
return int("".join(res), 2)
def fill(self, bin_string):
"""
填充二进制消息string
:param bin_string: 对任意消息使用self.msgToBin()得到的结果
:return: 填充后的二进制消息m',其比特长度为512的倍数
"""
tail = "{:064b}".format(len(bin_string))
bin_string += "1"
div, mod = divmod(len(bin_string), 512)
if mod >= 448:
bin_string += "0" * (512 - mod + 448)
else:
bin_string += "0" * (448 - mod)
return bin_string + tail
def iterationCourse(self, msg):
"""
迭代压缩消息
:param msg: 填充后的二进制消息m', self.fill(msg)
:return: Hash值(杂凑值)
"""
# 将填充消息m'按512比特进行分组
n = len(msg) // 512
m = [msg[i * 512:(i + 1) * 512] for i in range(n)]
# 对m[i]进行压缩迭代, msg = self.bigLittleEndianConvert(Vi, "big") # 小端数据转换为大端
V = [self.IV]
for i in range(n):
V.append(hex(int(self.intToBin(self.CF(V[-1], m[i]), 256), 2))[2:])
return V
def CF(self, Vi, mi):
"""
压缩函数
:param Vi: 512比特16进制数据
:param mi: 512比特二进制数据
:return: 512比特16进制数据
"""
# 将Vi存储到字寄存器
msg = Vi
A = [int(msg[i * 8: (i + 1) * 8], 16) for i in range(len(msg) // 8)]
# 消息扩展,得到W和W'
W1, W2 = self.informationExtend(mi)
# 压缩消息
for j in range(64):
factor1 = self.leftRotate(A[0], 12)
factor2 = self.leftRotate(self.getT(j), j % 32)
SS1 = self.leftRotate((factor1 + A[4] + factor2) % self.MAX, 7)
factor3 = self.leftRotate(A[0], 12)
SS2 = SS1 ^ factor3
TT1 = (self.FF(A[0], A[1], A[2], j) + A[3] + SS2 + W2[j]) % self.MAX
TT2 = (self.GG(A[4], A[5], A[6], j) + A[7] + SS1 + W1[j]) % self.MAX
A[3] = A[2]
A[2] = self.leftRotate(A[1], 9)
A[1] = A[0]
A[0] = TT1
A[7] = A[6]
A[6] = self.leftRotate(A[5], 19)
A[5] = A[4]
A[4] = self.P0(TT2)
temp = self.intToBin(A[0], 32) + self.intToBin(A[1], 32) + self.intToBin(A[2], 32) + \
self.intToBin(A[3], 32) + self.intToBin(A[4], 32) + self.intToBin(A[5], 32) + \
self.intToBin(A[6], 32) + self.intToBin(A[7], 32)
temp = int(temp, 2)
return temp ^ int(Vi, 16)
def informationExtend(self, mi):
"""
消息扩展, 将512比特二进制消息扩展为132个字
:param mi: Bi,512比特二进制数据
:return: W -> 68个16进制消息字, W' -> 64个16进制消息字
"""
# 第一步,将消息Bi划分为16个字W0~W15
mi = self.binToHex(mi)
W1 = [int(mi[i * 8: (i + 1) * 8], 16) for i in range(len(mi) // 8)]
# 第二步
for j in range(16, 68):
p = self.P1(W1[j - 16] ^ W1[j - 9] ^ self.leftRotate(W1[j - 3], 15))
W1.append(p ^ self.leftRotate(W1[j - 13], 7) ^ W1[j - 6])
# 第三步
W2 = [W1[j] ^ W1[j + 4] for j in range(64)]
return W1, W2
def bigLittleEndianConvert(self, data, need="big"):
"""
大小端16进制数据转换
:param data: 16进制小端string
:param need: 转换为大端还是小端
:return: 转换后16进制string
"""
if sys.byteorder != need:
return binascii.hexlify(binascii.unhexlify(data)[::-1])
return data
def hexToBin(self, hex_string):
"""
十六进制string转换为二进制string
:param hex: 十六进制string
:return: 二进制string
"""
res = ""
for h in hex_string:
res += '{:04b}'.format(int(h, 16))
return res
def binToHex(self, bin_string):
"""
二进制string转换为十六进制string
:param bin_string: 二进制string
:return: 十六进制string
"""
res = ""
for i in range(len(bin_string) // 4):
s = bin_string[i * 4: (i + 1) * 4]
res += '{:x}'.format(int(s, 2))
return res
def msgToHex(self, msg):
"""
字符串转换为16进制字符串
:param msg: string
:return: msg.encode("utf-8").hex()
"""
return msg.encode("utf-8").hex()
def msgToBin(self, msg):
"""
字符串转换为二进制字符串
:param msg: string
:return: self.hexToBin(self.msgToHex(msg))
"""
return self.hexToBin(self.msgToHex(msg))
def intToBin(self, X, bits=32):
"""
整数值转二进制
:param X: 整数值
:return: 32位二进制字符串
"""
return ('{:0%db}' % bits).format(X)
def non(self, X):
"""
按位非
:param X: 整数值
:return: 按位非后的整数值
"""
X = self.intToBin(X)
Y = ""
for i in X:
if i == "0":
Y += "1"
else:
Y += "0"
return int(Y, 2)
if __name__ == "__main__":
print(SM3("abc").hash)
print(SM3("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd").hash)
1.要注意大小端转换问题,实际上就是byte位的倒序。
2.strconv.ParseInt(x, 16, 33),这里ParseInt的比特位要设置为33,因为要转换为uint32类型,而int有一个符号位。
3.W1和W2在迭代压缩消息的for循环中重置。
4.每次调用Hash()函数时,都要默认重置struct中的内容
package main
import (
"bytes"
"fmt"
"strconv"
"unsafe"
)
type SM3 struct {
Input string
IV string
V []string
B []string
W1 []uint32
W2 []uint32
A []uint32
MAX uint32
}
// 初始化IV值
func (s *SM3) Init() {
s.IV = "7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e"
s.V = append(s.V, s.IV)
s.MAX = 0xffffffff
}
// 输入字符补齐32位
func (s *SM3) CharToBin(char uint32) string {
r := strconv.FormatUint(uint64(char), 2) // byte转为无符号整型
// 补充到32位
if len(r) < 32 {
r = fmt.Sprintf("%032s", r)
}
return r
}
// byte转8位二进制
func (s *SM3) ByteToBin(char byte) string {
r := strconv.FormatUint(uint64(char), 2) // byte转为无符号整型
// 补充到32位
if len(r) < 8 {
r = fmt.Sprintf("%08s", r)
}
return r
}
// int转二进制32位
func (s *SM3) DecimalToBin(n int) string {
return s.CharToBin(uint32(n))
}
// uint32转16进制
func (s *SM3) Uint32ToHex(i uint32) string {
return fmt.Sprintf("%02x", i)
}
// 十六进制转二进制32位
func (s *SM3) HexToBin(x string) string {
base, _ := strconv.ParseInt(x, 16, 33)
return s.CharToBin(uint32(base))
}
// 十六进制转int
func (s *SM3) HexToInt(x string) int {
var num int
l := len(x)
for i := l - 1; i >= 0; i-- {
num += (int(x[l-i-1]) & 0xf) << uint8(i)
}
return num
}
// 8位十六进制转uint32
func (s *SM3) HexToUint32(x string) uint32 {
base, _ := strconv.ParseInt(x, 16, 33)
return uint32(base)
}
// 二进制转uint32
func (s *SM3) BinToUint32(b string) uint32 {
base, _ := strconv.ParseInt(b, 2, 33)
return uint32(base)
}
// 获取T值
func (s *SM3) GetT(j uint8) uint32 {
var r uint32
if j < 16 {
base, _ := strconv.ParseInt("79cc4519", 16, 32)
r = uint32(base)
} else if j <= 63 {
base, _ := strconv.ParseInt("7a879d8a", 16, 32)
r = uint32(base)
}
return r
}
// 布尔函数FFj
func (s *SM3) FF(X uint32, Y uint32, Z uint32, j uint8) uint32 {
var r uint32
if j < 16 {
r = X ^ Y ^ Z
} else if j <= 63 {
r = (X & Y) | (X & Z) | (Y & Z)
}
return r
}
// 布尔函数GGj
func (s *SM3) GG(X uint32, Y uint32, Z uint32, j uint8) uint32 {
var r uint32
if j < 16 {
r = X ^ Y ^ Z
} else if j <= 63 {
r = (X & Y) | ((^X) & Z)
}
return r
}
// 循环左移, k代表左移的位数
func (s *SM3) LeftRotate(X uint32, k uint8) uint32 {
X = (X << k) | (X >> (32 - k))
return X
}
// 置换函数P0
func (s *SM3) P0(X uint32) uint32 {
return X ^ s.LeftRotate(X, 9) ^ s.LeftRotate(X, 17)
}
// 置换函数P1
func (s *SM3) P1(X uint32) uint32 {
return X ^ s.LeftRotate(X, 15) ^ s.LeftRotate(X, 23)
}
// 填充函数
func (s *SM3) FillInput() string {
s.Init()
var res string
res += s.BigLittleEndianConvert()
res += "1" // 将1添加到消息末尾
temp := len(res) % 512
if temp < 448 {
res += s.SameString("0", 448 - temp) // (l + 1 + k) mod 512余448
} else {
res += s.SameString("0", 512 - temp + 448)
}
tail := fmt.Sprintf("%064s", s.DecimalToBin(len(s.Input)*8))
res += tail
return res
}
// 大小端数据转换, 实际上就是字节序反转
func (s *SM3) BigLittleEndianConvert() string {
var temp string
if s.IsLittleEndian() {
for i := 0; i < len(s.Input); i++ { // 小端转大端
temp += s.ByteToBin(s.Input[i])
}
} else {
for i := len(s.Input) - 1; i >= 0; i-- {
temp += s.ByteToBin(s.Input[i]) // 大端保持原状
}
}
return temp
}
// 判断当前系统环境是否是小端
func (s *SM3) IsLittleEndian() bool {
var i int32 = 0x01020304
u := unsafe.Pointer(&i)
pb := (*byte)(u)
b := *pb
return (b == 0x04)
}
// 返回固定长度相同字符的字符串
func (s *SM3) SameString(str string, n int) string {
var buffer bytes.Buffer
for i := 0; i < n; i++ {
buffer.WriteString(str)
}
return buffer.String()
}
// 迭代压缩消息函数,返回64位16进制hash值
func (s *SM3) IterationCourse() string {
str := s.FillInput()
n := len(str) / 512
for i := 0; i < n; i++ {
s.B = append(s.B, str[i*512:(i+1)*512])
}
for i := 0; i < n; i++ {
s.V = append(s.V, s.CF(s.V[i], s.B[i]))
// 重置s.W1和s.W2
s.W1 = []uint32{}
s.W2 = []uint32{}
}
return s.V[len(s.V)-1:][0]
}
// 压缩函数
func (s *SM3) CF(Vi string, Bi string) string {
// Vi按字存到A
for i := 0; i < len(Vi)/8; i++ {
s.A = append(s.A, s.HexToUint32(Vi[i*8:(i+1)*8]))
}
// 消息扩展,得到W1和W2
s.informationExtend(Bi)
for j := 0; j < 64; j++ {
factor1 := s.LeftRotate(s.A[0], 12)
factor2 := s.LeftRotate(s.GetT(uint8(j)), uint8(j%32))
SS1 := s.LeftRotate((factor1 + s.A[4] + factor2), 7)
factor3 := s.LeftRotate(s.A[0], 12)
SS2 := SS1 ^ factor3
TT1 := (s.FF(s.A[0], s.A[1], s.A[2], uint8(j)) + s.A[3] + SS2 + s.W2[j])
TT2 := (s.GG(s.A[4], s.A[5], s.A[6], uint8(j)) + s.A[7] + SS1 + s.W1[j])
s.A[3] = s.A[2]
s.A[2] = s.LeftRotate(s.A[1], 9)
s.A[1] = s.A[0]
s.A[0] = TT1
s.A[7] = s.A[6]
s.A[6] = s.LeftRotate(s.A[5], 19)
s.A[5] = s.A[4]
s.A[4] = s.P0(TT2)
}
var res string
for i := 0; i < len(Vi)/8; i++ {
s.A[i] ^= s.HexToUint32(Vi[i*8 : (i+1)*8])
res += s.Uint32ToHex(s.A[i])
}
return res
}
// 消息扩展函数
func (s *SM3) informationExtend(Bi string) {
for i := 0; i < 16; i++ {
s.W1 = append(s.W1, s.BinToUint32(Bi[i*32:(i+1)*32]))
}
for j := 16; j < 68; j++ {
p := s.P1(s.W1[j-16] ^ s.W1[j-9] ^ s.LeftRotate(s.W1[j-3], 15))
s.W1 = append(s.W1, p^s.LeftRotate(s.W1[j-13], 7)^s.W1[j-6])
}
for j := 0; j < 64; j++ {
s.W2 = append(s.W2, s.W1[j]^s.W1[j+4])
}
}
// 生成hash值
func (s *SM3) Hash(str string) string {
s.Input = str
s.Reset()
return s.IterationCourse()
}
// 重置struct为零值
func (s *SM3) Reset() {
s.V = []string{}
s.B = []string{}
s.A = []uint32{}
}
func main() {
// 获取输入字符串
var s SM3
// "abc"测试
fmt.Println(s.Hash("abc"))
// 512bit测试
fmt.Println(s.Hash("abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"))
}
/*
* sm3.h
* 为使此算法兼容32位、64位下Linux或Windows系统,
* 选择 int 来表示 32 位整数。
* 消息长度最大限定为 2**32 - 1(单位:比特),
* 且为 8 的倍数(消息的最小单元为字节)。
*/
#ifndef C_SM3_H
#define C_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 //C_SM3_H
sm3.cpp
/*
* sm3.c
*/
#include
#include
#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;
else
return 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);
else
return 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);
else
return 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++)
{
// printf("%d: %x\n", i, A);
// printf("%d: %x\n", i, B);
// printf("%d: %x\n", i, C);
// printf("%d: %x\n", i, D);
// printf("%d: %x\n", i, E);
// printf("%d: %x\n", i, F);
// printf("%d: %x\n", i, G);
// printf("%d: %x\n", i, H);
unsigned int SS3;
// SS3 = LeftRotate(A, 12);
// printf("SS3: %d: %x\n", i, SS1);
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];
// printf("SS1: %d: %x\n", i, SS1);
// printf("SS2: %d: %x\n", i, SS2);
// printf("TT1: %d: %x\n", i, TT1);
// printf("TT2: %d: %x\n", i, TT2);
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.cpp
#include
#include
#include "sm3.h"
#include
//#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");
}
论文:http://www.doc88.com/p-9025639971932.html 需要注意这里面的压缩函数部分伪代码是错误的
过程测试数据:https://wenku.baidu.com/view/8d67d80178563c1ec5da50e2524de518964bd3b6.html?qq-pf-to=pcqq.c2c
https://blog.csdn.net/qq_37726361/article/details/84196058
https://blog.csdn.net/a344288106/article/details/80094878
https://github.com/ZZMarquis/gm/blob/e92bc99ad9a0305b01cf00d53fd64f356ce37026/sm3/sm3.go#L137