【密码算法】SM3密码杂凑算法

admin 2026-03-06 18:06:04 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细解读SM3密码杂凑算法,作为中国国家标准GB/T32905—2016,其输出256比特摘要。文档系统阐述了算法概述、标准体系、核心术语及消息填充、迭代压缩等运算流程,解析了布尔函数与置换函数机制。内容对比了SM3与SHA系列算法特性,强调其高安全性与效率,并附带Python实现代码与运算示例,为掌握该国产密码算法提供了精准的技术指导与实践参考。 综合评分: 88 文章分类: 技术标准,数据安全,安全开发


cover_image

【密码算法】SM3 密码杂凑算法

原创

利刃信安 利刃信安

利刃信安

2026年3月6日 14:03 北京

SM3 密码杂凑算法

1. 概述

SM3密码杂凑算法是中国专门设计的杂凑函数,可用于消息摘要的计算、数字签名和验证、消息鉴别码的生成与验证,以及随机数的生成,具有高安全性和高效率的特点,已被纳入国家标准体系。

1.1 标准信息

  • • 主要标准:GB/T 32905—2016《信息安全技术 SM3密码杂凑算法》

  • • 相关标准:GB/T 18238.3—2024《网络安全技术 杂凑函数 第3部分:专门设计的杂凑函数》

  • • 发布与实施

  • • GB/T 32905—2016:2016-08-29发布,2017-03-01实施

  • • GB/T 18238.3—2024:2024-09-29发布,2025-04-01实施

  • • 起草单位:清华大学、国家密码管理局商用密码检测中心、解放军信息工程大学、中国科学院数据与通信保护研究教育中心等

  • • 标准关系:GB/T 18238.3—2024将SM3纳入专门设计的杂凑函数标准体系,对其算法模型、安全性要求等进行了进一步规范

1.2 算法基本概念

SM3是一种专门设计的杂凑函数,即在设计过程中不依赖其他密码原语(如分组密码等),直接设计形成的杂凑函数。它用于将输入为长度为l( l < 2^{64} )比特的消息 m,经过填充、迭代压缩,生成杂凑值,杂凑值输出长度为256比特,可用于消息摘要的计算、数字签名和验证、消息鉴别码的生成与验证,以及随机数的生成等密码学应用。

1.3 基本参数

  • • 输入:长度为 l ( l < 2^{64} )比特的任意消息
  • • 输出:256比特的固定长度杂凑值(消息摘要)
  • • 分组长度:512比特( L1 = 512 )
  • • 状态长度:256比特( L2 = 256 )
  • • 杂凑值长度:256比特( LH = 256 )

1.4 算法模型

SM3采用基于轮函数的通用模型,主要包括以下组成部分:

  • • 轮函数:输入两个位串(512比特消息分组和256比特当前状态),输出一个256比特新状态
  • • 压缩函数CF:轮函数的具体实现,将当前状态和消息分组变换为新状态
  • • 数据处理:填充后的消息以字节串形式处理,每组8位为一个字节,高位在前
  • • 输出变换:采用恒等变换,直接输出最终状态作为杂凑值 H = V(n)

2. 术语和核心定义

2.1 术语定义

| 术语 | 定义 | | — | — | | 比特串 | 具有0或1值的二进制数字序列 | | 字节 | 由8个连续位构成的位串 | | 大端 | 数据在内存中的表示格式,左边为高有效位,右边为低有效位。数的高阶字节放在存储器的低地址,低阶字节放在高地址 | | 消息 | 任意有限长度的比特串,作为杂凑算法的输入数据 | | 杂凑值 | 杂凑算法作用于消息时输出的固定长度消息摘要 | | 专门设计的杂凑函数 | 在设计过程中不依赖其他密码原语(如分组密码等),直接设计形成的杂凑函数 | | 压缩函数 | 将固定长度的输入(如512比特)压缩为更短的输出(如256比特)的函数 | | 消息分组 | 将填充后的消息按固定长度(512比特)划分得到的块 | | 迭代压缩 | 对每个消息分组依次应用压缩函数,将结果传递给下一轮迭代的过程 | | 轮函数 | 杂凑函数中用于迭代处理的基本函数,对输入的状态和消息块进行变换 |

2.2 核心常量与函数

2.2.1 初始值

IV = 7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e

2.2.2 常量

Tj = 0x79cc4519 &nbsp; &nbsp;(0 ≤ j ≤ 15)
Tj = 0x7a879d8a &nbsp; &nbsp;(16 ≤ j ≤ 63)

2.2.3 布尔函数

FFj(X,Y,Z) = X⊕Y⊕Z &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (0 ≤ j ≤ 15)
FFj(X,Y,Z) = (X∧Y)∨(X∧Z)∨(Y∧Z) &nbsp;(16 ≤ j ≤ 63)

GGj(X,Y,Z) = X⊕Y⊕Z &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (0 ≤ j ≤ 15)
GGj(X,Y,Z) = (X∧Y)∨(¬X∧Z) &nbsp; &nbsp; (16 ≤ j ≤ 63)

2.2.4 置换函数

P0(X) = X⊕(X<<<9)⊕(X<<<17)
P1(X) = X⊕(X<<<15)⊕(X<<<23)

3. 算法运算步骤

3.1 消息填充

SM3的填充方法应采用GB/T 18238.1—2024中A.3规定的方法2,取预留位串长度r=64。具体步骤如下:

  1. 1. 将比特”1″添加到消息末尾
  2. 2. 添加k个”0″,使得 l+1+k ≡ 448 mod 512 (k为最小非负整数)
  3. 3. 添加一个64位比特串,表示消息原始长度l的二进制形式
  4. 4. 填充后消息长度为512的整数倍

填充后的数据串以字节串形式作为输入,每组连续8位为一个字节,每组的第一位为该字节的最高有效位。

3.2 迭代压缩

  1. 1. 将填充后的消息按512比特分组,得到 n 个分组 B(0), B(1), …, B(n-1)
  2. 2. 初始化压缩函数输入为初始值 V(0) = IV
  3. 3. 对每个分组 B(i) ,执行压缩函数 V(i+1) = CF(V(i), B(i)) ,其中 CF 为压缩函数

3.3 压缩函数CF

压缩函数 CF 的执行过程如下:

  1. 1. 消息扩展:将消息分组 B(i) 扩展为132个字:
  • • 第一步:将512位消息分组划分为16个32位字 W_0, W_1, …, W_{15}
  • • 第二步:生成 W[16-67] (52个32位字):
  W_j = P1(W_{j-16} ⊕ W_{j-9} ⊕ (W_{j-3} <<< 15)) ⊕ (W_{j-13} <<< 7) ⊕ W_{j-6}
  其中:j = 16 到 67
  &nbsp; &nbsp; &nbsp; P1(X) = X ⊕ (X <<< 15) ⊕ (X <<< 23)
  • • 第三步:生成 W'[0-63] (64个32位字):
  W'_j = W_j ⊕ W_{j+4}
  其中:j = 0 到 63
  1. 2. 初始化寄存器:将当前状态 V(i) 拆分为8个32位寄存器:
   A, B, C, D, E, F, G, H = V(i)
  1. 3. 64轮迭代:对于 j = 0 到 63 ,执行以下步骤:
  2. 常量
current_Tj = 0x79cc4519 if 0 <= j <= 15 else 0x7a879d8a

布尔函数

FFj_val = A ^ B ^ C if 0 <= j <= 15 else (A & B) | (A & C) | (B & C)
GGj_val = E ^ F ^ G if 0 <= j <= 15 else (E & F) | ((~E) & G)

轮函数核心计算

# 计算 SS1
A_rot12 = A <<< 12 &nbsp;# A循环左移12位
Tj_rot = current_Tj <<< (j % 32) &nbsp;# Tj循环左移j%32位
temp1 = (A_rot12 + E + Tj_rot) & 0xFFFFFFFF
SS1 = temp1 <<< 7 &nbsp;# 循环左移7位

# 计算 SS2
SS2 = SS1 ^ A_rot12

# 计算 TT1 和 TT2
TT1 = (FFj_val + D + SS2 + W'[j]) & 0xFFFFFFFF
TT2 = (GGj_val + H + SS1 + W[j]) & 0xFFFFFFFF

寄存器更新

# 更新工作变量
new_A = TT1
new_B = A
new_C = B <<< 9 &nbsp;# 循环左移9位
new_D = C
new_E = P0(TT2) &nbsp;# 应用置换函数P0
new_F = E
new_G = F <<< 19 &nbsp;# 循环左移19位
new_H = G

# 将新值赋给工作变量
A, B, C, D, E, F, G, H = new_A, new_B, new_C, new_D, new_E, new_F, new_G, new_H
  1. 4. 更新中间值
   V(i+1) = (A,B,C,D,E,F,G,H) ⊕ V(i)

即新状态是当前轮计算结果与输入状态的异或。

3.4 输出杂凑值

SM3的输出变换为恒等变换,即直接输出最终状态 V(n) 作为256比特杂凑值。

4. 应用与特点

4.1 应用场景

  • • 数字签名和验证:用于生成和验证数字签名
  • • 消息认证码(MAC):用于消息完整性验证和认证
  • • 随机数生成:用于生成密码学安全的随机数
  • • 密码存储:用于安全存储密码哈希
  • • 其他密码学应用:如哈希链、承诺方案等

4.2 算法特点

  • • 高安全性

  • • 抗碰撞攻击:设计上考虑了现代密码分析技术,目前尚未发现有效的碰撞攻击方法

  • • 抗原像攻击:给定杂凑值,难以找到对应的原始消息

  • • 抗第二原像攻击:给定消息,难以找到具有相同杂凑值的另一消息

  • • 抗差分攻击和线性攻击:采用了复杂的布尔函数和置换函数

  • • 高效率

  • • 适用于各种计算环境,包括软件和硬件实现

  • • 算法结构简单,基于字节处理,易于优化实现

  • • 轮函数设计平衡了安全性和效率

  • • 国家标准

  • • 由中国国家标准化管理委员会发布,适用于商用密码应用

  • • 是中国商用密码体系的重要组成部分

  • • 具有自主知识产权,不受国外专利限制

  • • 良好的雪崩效应:输入的微小变化会导致输出的显著变化,符合密码学杂凑函数的要求

4.3 与其他杂凑算法的比较

| 算法 | 输出长度 | 设计年份 | 所属标准 | | — | — | — | — | | SM3 | 256比特 | 2010 | GB/T 32905—2016 | | SHA-256 | 256比特 | 2001 | FIPS PUB 180-4 | | SHA-3 | 可配置(224/256/384/512) | 2015 | FIPS PUB 202 |

SM3算法在设计上参考了SHA-256的结构,但进行了改进和优化,具有自主知识产权,是中国商用密码体系的重要组成部分。

4.4 应用前景

随着密码技术的发展和应用需求的增长,SM3算法将在更多领域得到广泛应用,特别是在网络安全、金融安全、物联网安全等领域。作为中国自主设计的密码算法,SM3对于保障国家信息安全具有重要意义。

5. 实现与示例

5.1 运算示例

5.1.1 示例1:短消息

  • • 输入:”abc”(十六进制:616263)
  • • 输出杂凑值:66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0

5.1.2 示例2:512比特消息

  • • 输入:61626364重复16次(共512比特)
  • • 输出杂凑值:debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732

5.2 详细计算过程脚本

工作区中提供了一个详细的SM3计算过程脚本 SM3计算过程详解.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
SM3密码杂凑算法完整实现 - 优化版
基于GB/T 32905-2016标准
支持字符串和十六进制输入,详细展示每一步的计算过程
"""

IV = [
&nbsp; &nbsp;&nbsp;0x7380166f,&nbsp;0x4914b2b9,&nbsp;0x172442d7,&nbsp;0xda8a0600,
&nbsp; &nbsp;&nbsp;0xa96f30bc,&nbsp;0x163138aa,&nbsp;0xe38dee4d,&nbsp;0xb0fb0e4e
]

defleft_rotate(n, b):
&nbsp; &nbsp;&nbsp;"""32位循环左移"""
&nbsp; &nbsp;&nbsp;return&nbsp;((n << b) | (n >> (32&nbsp;- b))) &&nbsp;0xFFFFFFFF

defTj(j):
&nbsp; &nbsp;&nbsp;"""常量Tj"""
&nbsp; &nbsp;&nbsp;return0x79cc4519if&nbsp;j <&nbsp;16else0x7a879d8a

defFFj(X, Y, Z, j):
&nbsp; &nbsp;&nbsp;"""布尔函数FFj"""
&nbsp; &nbsp;&nbsp;if&nbsp;j <&nbsp;16:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;X ^ Y ^ Z
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;(X & Y) | (X & Z) | (Y & Z)

defGGj(X, Y, Z, j):
&nbsp; &nbsp;&nbsp;"""布尔函数GGj"""
&nbsp; &nbsp;&nbsp;if&nbsp;j <&nbsp;16:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;X ^ Y ^ Z
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;(X & Y) | ((~X) & Z)

defP0(X):
&nbsp; &nbsp;&nbsp;"""置换函数P0"""
&nbsp; &nbsp;&nbsp;return&nbsp;X ^ left_rotate(X,&nbsp;9) ^ left_rotate(X,&nbsp;17)

defP1(X):
&nbsp; &nbsp;&nbsp;"""置换函数P1"""
&nbsp; &nbsp;&nbsp;return&nbsp;X ^ left_rotate(X,&nbsp;15) ^ left_rotate(X,&nbsp;23)

defhex_to_binary(hex_str):
&nbsp; &nbsp;&nbsp;"""将十六进制字符串转换为二进制字符串"""
&nbsp; &nbsp; hex_str = hex_str.replace(' ',&nbsp;'')
&nbsp; &nbsp;&nbsp;ifnot&nbsp;hex_str:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return''
&nbsp; &nbsp; binary =&nbsp;bin(int(hex_str,&nbsp;16))[2:]
&nbsp; &nbsp; padding =&nbsp;len(binary) %&nbsp;8
&nbsp; &nbsp;&nbsp;if&nbsp;padding !=&nbsp;0:
&nbsp; &nbsp; &nbsp; &nbsp; binary =&nbsp;'0'&nbsp;* (8&nbsp;- padding) + binary
&nbsp; &nbsp;&nbsp;return&nbsp;binary

defbinary_to_hex(binary_str):
&nbsp; &nbsp;&nbsp;"""将二进制字符串转换为十六进制字符串"""
&nbsp; &nbsp;&nbsp;ifnot&nbsp;binary_str:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return''
&nbsp; &nbsp; padding =&nbsp;len(binary_str) %&nbsp;8
&nbsp; &nbsp;&nbsp;if&nbsp;padding !=&nbsp;0:
&nbsp; &nbsp; &nbsp; &nbsp; binary_str =&nbsp;'0'&nbsp;* (8&nbsp;- padding) + binary_str
&nbsp; &nbsp; hex_str =&nbsp;hex(int(binary_str,&nbsp;2))[2:].upper()
&nbsp; &nbsp;&nbsp;return' '.join([hex_str[i:i +&nbsp;2]&nbsp;for&nbsp;i&nbsp;inrange(0,&nbsp;len(hex_str),&nbsp;2)])

defstring_to_binary(string):
&nbsp; &nbsp;&nbsp;"""将字符串转换为二进制字符串"""
&nbsp; &nbsp; bytes_data = string.encode('utf-8')
&nbsp; &nbsp; binary =&nbsp;''.join(format(byte,&nbsp;'08b')&nbsp;for&nbsp;byte&nbsp;in&nbsp;bytes_data)
&nbsp; &nbsp;&nbsp;return&nbsp;binary

defpad_message(message, length):
&nbsp; &nbsp;&nbsp;"""实现填充逻辑"""
&nbsp; &nbsp; padded = message +&nbsp;"1"

&nbsp; &nbsp; l_plus_1 = length +&nbsp;1
&nbsp; &nbsp; remainder = l_plus_1 %&nbsp;512
&nbsp; &nbsp; k =&nbsp;448&nbsp;- remainder&nbsp;if&nbsp;remainder <=&nbsp;448else512&nbsp;- (remainder -&nbsp;448)

&nbsp; &nbsp; padded +=&nbsp;"0"&nbsp;* k
&nbsp; &nbsp; l_bin =&nbsp;bin(length)[2:].zfill(64)
&nbsp; &nbsp; padded += l_bin

&nbsp; &nbsp;&nbsp;return&nbsp;padded

defmessage_extension_detailed(Bi, group_num=0):
&nbsp; &nbsp;&nbsp;"""消息扩展函数 - 详细版本"""
&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print(f"消息扩展 - 第{group_num}组")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp; W = []

&nbsp; &nbsp;&nbsp;print(f"\n【步骤1】将512位消息分组划分为16个32位字")
&nbsp; &nbsp;&nbsp;print(f"输入:&nbsp;{binary_to_hex(Bi).replace(' ',&nbsp;'')}")
&nbsp; &nbsp;&nbsp;print(f"\n输出 W[0-15]:")

&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(0,&nbsp;512,&nbsp;32):
&nbsp; &nbsp; &nbsp; &nbsp; word =&nbsp;int(Bi[i:i +&nbsp;32],&nbsp;2)
&nbsp; &nbsp; &nbsp; &nbsp; W.append(word)

&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(16):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;W[{i:2d}] =&nbsp;{format(W[i],&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;print(f"\n【步骤2】生成W[16-67]")
&nbsp; &nbsp;&nbsp;print(f"公式: W[j] = P1(W[j-16] ⊕ W[j-9] ⊕ ROTL(W[j-3],15)) ⊕ ROTL(W[j-13],7) ⊕ W[j-6]")
&nbsp; &nbsp;&nbsp;print(f"其中: P1(X) = X ⊕ ROTL(X,15) ⊕ ROTL(X,23)")

&nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;inrange(16,&nbsp;68):
&nbsp; &nbsp; &nbsp; &nbsp; temp1 = W[j -&nbsp;16] ^ W[j -&nbsp;9] ^ left_rotate(W[j -&nbsp;3],&nbsp;15)
&nbsp; &nbsp; &nbsp; &nbsp; temp2 = P1(temp1)
&nbsp; &nbsp; &nbsp; &nbsp; temp3 = temp2 ^ left_rotate(W[j -&nbsp;13],&nbsp;7) ^ W[j -&nbsp;6]
&nbsp; &nbsp; &nbsp; &nbsp; W.append(temp3)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;j <&nbsp;20:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算 W[{j}]:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;16}] =&nbsp;{format(W[j -&nbsp;16],&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;9}] &nbsp;=&nbsp;{format(W[j -&nbsp;9],&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;3}] &nbsp;=&nbsp;{format(W[j -&nbsp;3],&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;13}] =&nbsp;{format(W[j -&nbsp;13],&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;6}] &nbsp;=&nbsp;{format(W[j -&nbsp;6],&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;ROTL(W[{j -&nbsp;3}],15) =&nbsp;{format(left_rotate(W[j -&nbsp;3],&nbsp;15),&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;W[{j -&nbsp;16}] ⊕ W[{j -&nbsp;9}] ⊕ ROTL(W[{j -&nbsp;3}],15) =&nbsp;{format(temp1,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;P1({format(temp1,&nbsp;'08x')}) =&nbsp;{format(temp2,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;ROTL(W[{j -&nbsp;13}],7) =&nbsp;{format(left_rotate(W[j -&nbsp;13],&nbsp;7),&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f" &nbsp; &nbsp;W[{j}] =&nbsp;{format(temp2,&nbsp;'08x')}&nbsp;⊕&nbsp;{format(left_rotate(W[j -&nbsp;13],&nbsp;7),&nbsp;'08x')}&nbsp;⊕&nbsp;{format(W[j -&nbsp;6],&nbsp;'08x')}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp; =&nbsp;{format(W[j],&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;print(f"\n生成的W[16-67] (完整):")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(16,&nbsp;68,&nbsp;4):
&nbsp; &nbsp; &nbsp; &nbsp; line =&nbsp;' &nbsp;'.join([f"W[{j}]={format(W[j],&nbsp;'08x').upper()}"for&nbsp;j&nbsp;inrange(i,&nbsp;min(i +&nbsp;4,&nbsp;68))])
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;{line}")

&nbsp; &nbsp; W_prime = []
&nbsp; &nbsp;&nbsp;print(f"\n【步骤3】生成W'[0-63]")
&nbsp; &nbsp;&nbsp;print(f"公式: W'[j] = W[j] ⊕ W[j+4]")

&nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;inrange(64):
&nbsp; &nbsp; &nbsp; &nbsp; W_prime.append(W[j] ^ W[j +&nbsp;4])

&nbsp; &nbsp;&nbsp;print(f"\n生成的W'[0-63] (完整):")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(0,&nbsp;64,&nbsp;4):
&nbsp; &nbsp; &nbsp; &nbsp; line =&nbsp;' &nbsp;'.join([f"W'[{j}]={format(W_prime[j],&nbsp;'08x').upper()}"for&nbsp;j&nbsp;inrange(i,&nbsp;min(i +&nbsp;4,&nbsp;64))])
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;{line}")

&nbsp; &nbsp;&nbsp;return&nbsp;W, W_prime

defcompression_function_detailed(Vi, W, W_prime, group_num=0, show_all_rounds=False):
&nbsp; &nbsp;&nbsp;"""压缩函数 - 详细版本"""
&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print(f"压缩函数 - 第{group_num}组")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp;&nbsp;print(f"\n【输入】Vi (256位初始值或中间值):")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(8):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;V[{i}] =&nbsp;{format(Vi[i],&nbsp;'08x').upper()}")

&nbsp; &nbsp; A, B, C, D, E, F, G, H = Vi

&nbsp; &nbsp;&nbsp;print(f"\n【初始化工作变量】")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;A =&nbsp;{format(A,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;B =&nbsp;{format(B,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;C =&nbsp;{format(C,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;D =&nbsp;{format(D,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;E =&nbsp;{format(E,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;F =&nbsp;{format(F,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;G =&nbsp;{format(G,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;H =&nbsp;{format(H,&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;print(f"\n【开始64轮迭代压缩】")
&nbsp; &nbsp;&nbsp;print(f"迭代公式:")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;SS1 = ROTL(ROTL(A,12) + E + ROTL(Tj,j), 7)")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;SS2 = SS1 ⊕ ROTL(A,12)")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;TT1 = FFj(A,B,C,j) + D + SS2 + W'[j]")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;TT2 = GGj(E,F,G,j) + H + SS1 + W[j]")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新A = TT1")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新B = A")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新C = ROTL(B,9)")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新D = C")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新E = P0(TT2)")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新F = E")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新G = ROTL(F,19)")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;新H = G")

&nbsp; &nbsp;&nbsp;for&nbsp;j&nbsp;inrange(64):
&nbsp; &nbsp; &nbsp; &nbsp; A_rot12 = left_rotate(A,&nbsp;12)
&nbsp; &nbsp; &nbsp; &nbsp; Tj_rot = left_rotate(Tj(j), j %&nbsp;32)
&nbsp; &nbsp; &nbsp; &nbsp; SS1 = left_rotate((A_rot12 + E + Tj_rot) &&nbsp;0xFFFFFFFF,&nbsp;7)
&nbsp; &nbsp; &nbsp; &nbsp; SS2 = SS1 ^ A_rot12
&nbsp; &nbsp; &nbsp; &nbsp; TT1 = (FFj(A, B, C, j) + D + SS2 + W_prime[j]) &&nbsp;0xFFFFFFFF
&nbsp; &nbsp; &nbsp; &nbsp; TT2 = (GGj(E, F, G, j) + H + SS1 + W[j]) &&nbsp;0xFFFFFFFF

&nbsp; &nbsp; &nbsp; &nbsp; show_this_round = show_all_rounds&nbsp;or&nbsp;j <&nbsp;4or&nbsp;j >=&nbsp;60

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;show_this_round:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n{'─'&nbsp;*&nbsp;80}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"【第{j}轮迭代】")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算SS1:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;Tj =&nbsp;{format(Tj(j),&nbsp;'08x').upper()}&nbsp;{'(j<16)'&nbsp;if&nbsp;j <&nbsp;16&nbsp;else&nbsp;'(j≥16)'}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;ROTL(A,12) = ROTL({format(A,&nbsp;'08x')},12) =&nbsp;{format(A_rot12,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;ROTL(Tj,j mod 32) = ROTL({format(Tj(j),&nbsp;'08x')},{j %&nbsp;32}) =&nbsp;{format(Tj_rot,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;SS1 = ROTL({format(A_rot12,&nbsp;'08x')}&nbsp;+&nbsp;{format(E,&nbsp;'08x')}&nbsp;+&nbsp;{format(Tj_rot,&nbsp;'08x')}, 7)")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp;= ROTL({format((A_rot12 + E + Tj_rot) &&nbsp;0xFFFFFFFF,&nbsp;'08x')}, 7)")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(SS1,&nbsp;'08x').upper()}")

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算SS2:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;SS2 = SS1 ⊕ ROTL(A,12) =&nbsp;{format(SS1,&nbsp;'08x')}&nbsp;⊕&nbsp;{format(A_rot12,&nbsp;'08x')}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(SS2,&nbsp;'08x').upper()}")

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算TT1:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ffj_result = FFj(A, B, C, j)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;FFj(A,B,C,{j}) =&nbsp;{'A⊕B⊕C'&nbsp;if&nbsp;j <&nbsp;16&nbsp;else&nbsp;'(A∧B)∨(A∧C)∨(B∧C)'}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(ffj_result,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;TT1 = FFj + D + SS2 + W'[{j}]")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(ffj_result,&nbsp;'08x')}&nbsp;+&nbsp;{format(D,&nbsp;'08x')}&nbsp;+&nbsp;{format(SS2,&nbsp;'08x')}&nbsp;+&nbsp;{format(W_prime[j],&nbsp;'08x')}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(TT1,&nbsp;'08x').upper()}")

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算TT2:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ggj_result = GGj(E, F, G, j)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;GGj(E,F,G,{j}) =&nbsp;{'E⊕F⊕G'&nbsp;if&nbsp;j <&nbsp;16&nbsp;else&nbsp;'(E∧F)∨(¬E∧G)'}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(ggj_result,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;TT2 = GGj + H + SS1 + W[{j}]")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(ggj_result,&nbsp;'08x')}&nbsp;+&nbsp;{format(H,&nbsp;'08x')}&nbsp;+&nbsp;{format(SS1,&nbsp;'08x')}&nbsp;+&nbsp;{format(W[j],&nbsp;'08x')}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(TT2,&nbsp;'08x').upper()}")

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;计算P0(TT2):")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p0_result = P0(TT2)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;P0(TT2) = TT2 ⊕ ROTL(TT2,9) ⊕ ROTL(TT2,17)")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(TT2,&nbsp;'08x')}&nbsp;⊕&nbsp;{format(left_rotate(TT2,&nbsp;9),&nbsp;'08x')}&nbsp;⊕&nbsp;{format(left_rotate(TT2,&nbsp;17),&nbsp;'08x')}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;{format(p0_result,&nbsp;'08x').upper()}")

&nbsp; &nbsp; &nbsp; &nbsp; temp_A, temp_B, temp_C, temp_D = A, B, C, D
&nbsp; &nbsp; &nbsp; &nbsp; temp_E, temp_F, temp_G, temp_H = E, F, G, H

&nbsp; &nbsp; &nbsp; &nbsp; A = TT1
&nbsp; &nbsp; &nbsp; &nbsp; B = temp_A
&nbsp; &nbsp; &nbsp; &nbsp; C = left_rotate(temp_B,&nbsp;9)
&nbsp; &nbsp; &nbsp; &nbsp; D = temp_C
&nbsp; &nbsp; &nbsp; &nbsp; E = P0(TT2)
&nbsp; &nbsp; &nbsp; &nbsp; F = temp_E
&nbsp; &nbsp; &nbsp; &nbsp; G = left_rotate(temp_F,&nbsp;19)
&nbsp; &nbsp; &nbsp; &nbsp; H = temp_G

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;show_this_round:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n &nbsp;更新工作变量:")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新A = TT1 =&nbsp;{format(A,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新B = 旧A =&nbsp;{format(B,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新C = ROTL(旧B,9) = ROTL({format(temp_B,&nbsp;'08x')},9) =&nbsp;{format(C,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新D = 旧C =&nbsp;{format(D,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新E = P0(TT2) =&nbsp;{format(E,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新F = 旧E =&nbsp;{format(F,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新G = ROTL(旧F,19) = ROTL({format(temp_F,&nbsp;'08x')},19) =&nbsp;{format(G,&nbsp;'08x').upper()}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;新H = 旧G =&nbsp;{format(H,&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print(f"【64轮迭代完成】")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print(f"\n最终工作变量值:")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;A =&nbsp;{format(A,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;B =&nbsp;{format(B,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;C =&nbsp;{format(C,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;D =&nbsp;{format(D,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;E =&nbsp;{format(E,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;F =&nbsp;{format(F,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;G =&nbsp;{format(G,&nbsp;'08x').upper()}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;H =&nbsp;{format(H,&nbsp;'08x').upper()}")

&nbsp; &nbsp; Vi_new = [
&nbsp; &nbsp; &nbsp; &nbsp; A ^ Vi[0], B ^ Vi[1], C ^ Vi[2], D ^ Vi[3],
&nbsp; &nbsp; &nbsp; &nbsp; E ^ Vi[4], F ^ Vi[5], G ^ Vi[6], H ^ Vi[7]
&nbsp; &nbsp; ]

&nbsp; &nbsp;&nbsp;print(f"\n【输出】Vi+1 = Vi ⊕ (A,B,C,D,E,F,G,H):")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(8):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;f" &nbsp;V[{i}] =&nbsp;{format(Vi[i],&nbsp;'08x')}&nbsp;⊕&nbsp;{format([A, B, C, D, E, F, G, H][i],&nbsp;'08x')}&nbsp;=&nbsp;{format(Vi_new[i],&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;return&nbsp;Vi_new

defsm3_hash_detailed(input_data, input_type='hex', show_all_rounds=False):
&nbsp; &nbsp;&nbsp;"""SM3杂凑算法主函数 - 详细版本"""
&nbsp; &nbsp;&nbsp;print("\n"&nbsp;+&nbsp;"="&nbsp;*&nbsp;80)
&nbsp; &nbsp;&nbsp;print("SM3密码杂凑算法完整计算过程")
&nbsp; &nbsp;&nbsp;print("="&nbsp;*&nbsp;80)

&nbsp; &nbsp;&nbsp;if&nbsp;input_type ==&nbsp;'string':
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n【输入类型】字符串")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"【输入内容】{input_data}")
&nbsp; &nbsp; &nbsp; &nbsp; binary_message = string_to_binary(input_data)
&nbsp; &nbsp; &nbsp; &nbsp; hex_message = binary_to_hex(binary_message).replace(' ',&nbsp;'')
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"【十六进制】{hex_message}")
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n【输入类型】十六进制")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"【输入内容】{input_data}")
&nbsp; &nbsp; &nbsp; &nbsp; binary_message = hex_to_binary(input_data)
&nbsp; &nbsp; &nbsp; &nbsp; hex_message = input_data.replace(' ',&nbsp;'')

&nbsp; &nbsp; length =&nbsp;len(binary_message)
&nbsp; &nbsp;&nbsp;print(f"【消息长度】{length}&nbsp;比特 ({length //&nbsp;8}&nbsp;字节)")

&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print("第一步: 消息填充")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp;&nbsp;print(f"\n【填充规则】")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;1. 在消息末尾添加一个比特'1'")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;2. 添加k个'0',使得 (l+1+k) mod 512 = 448")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;3. 添加64位二进制表示的消息长度l")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;4. 填充后消息长度为512的倍数")

&nbsp; &nbsp; l_plus_1 = length +&nbsp;1
&nbsp; &nbsp; remainder = l_plus_1 %&nbsp;512
&nbsp; &nbsp; k =&nbsp;448&nbsp;- remainder&nbsp;if&nbsp;remainder <=&nbsp;448else512&nbsp;- (remainder -&nbsp;448)

&nbsp; &nbsp;&nbsp;print(f"\n【填充参数计算】")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;原始消息长度 l =&nbsp;{length}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;l + 1 =&nbsp;{length}&nbsp;+ 1 =&nbsp;{l_plus_1}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;(l + 1) mod 512 =&nbsp;{l_plus_1}&nbsp;mod 512 =&nbsp;{remainder}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;需要填充的0的个数 k = 448 -&nbsp;{remainder}&nbsp;=&nbsp;{k}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;填充后总长度 =&nbsp;{length}&nbsp;+ 1 +&nbsp;{k}&nbsp;+ 64 =&nbsp;{length +&nbsp;1&nbsp;+ k +&nbsp;64}")

&nbsp; &nbsp; padded_message = pad_message(binary_message, length)

&nbsp; &nbsp;&nbsp;print(f"\n【填充过程】")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;步骤1: 添加'1'")
&nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;输入:&nbsp;{binary_message[:80]}{'...'&nbsp;if&nbsp;len(binary_message) >&nbsp;80&nbsp;else&nbsp;''}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;输出:&nbsp;{binary_message[:80]}{'...'&nbsp;if&nbsp;len(binary_message) >&nbsp;80&nbsp;else&nbsp;''}1")

&nbsp; &nbsp;&nbsp;print(f"\n &nbsp;步骤2: 添加{k}个'0'")
&nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;输出长度:&nbsp;{len(binary_message) +&nbsp;1&nbsp;+ k}&nbsp;比特")

&nbsp; &nbsp;&nbsp;print(f"\n &nbsp;步骤3: 添加64位长度表示")
&nbsp; &nbsp; l_bin =&nbsp;bin(length)[2:].zfill(64)
&nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;长度l的二进制(64位):&nbsp;{l_bin}")
&nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;长度l的十六进制:&nbsp;{format(length,&nbsp;'016x').upper()}")

&nbsp; &nbsp; padded_hex = binary_to_hex(padded_message)
&nbsp; &nbsp;&nbsp;print(f"\n【填充后消息】(十六进制):")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;{padded_hex.replace(' ',&nbsp;'')}")

&nbsp; &nbsp; num_blocks =&nbsp;len(padded_message) //&nbsp;512
&nbsp; &nbsp;&nbsp;print(f"\n【消息分组】{num_blocks}组,每组512比特")

&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print("第二步: 迭代压缩")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp;&nbsp;print(f"\n【初始值IV】")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(8):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;V[{i}] =&nbsp;{format(IV[i],&nbsp;'08x').upper()}")

&nbsp; &nbsp; V = IV[:]

&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(num_blocks):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n{'#'&nbsp;*&nbsp;80}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"# 处理第{i}组消息分组B{i}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"{'#'&nbsp;*&nbsp;80}")

&nbsp; &nbsp; &nbsp; &nbsp; Bi = padded_message[i *&nbsp;512:(i +&nbsp;1) *&nbsp;512]
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n【消息分组B{i}】")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;二进制:&nbsp;{Bi[:80]}{'...'&nbsp;if&nbsp;len(Bi) >&nbsp;80&nbsp;else&nbsp;''}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;十六进制:&nbsp;{binary_to_hex(Bi).replace(' ',&nbsp;'')}")

&nbsp; &nbsp; &nbsp; &nbsp; W, W_prime = message_extension_detailed(Bi, i)
&nbsp; &nbsp; &nbsp; &nbsp; V = compression_function_detailed(V, W, W_prime, i, show_all_rounds)

&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print("第三步: 输出杂凑值")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp; hash_value =&nbsp;''.join([format(v,&nbsp;'08x').upper()&nbsp;for&nbsp;v&nbsp;in&nbsp;V])

&nbsp; &nbsp;&nbsp;print(f"\n【最终杂凑值】(256位):")
&nbsp; &nbsp;&nbsp;print(f" &nbsp;{hash_value}")

&nbsp; &nbsp;&nbsp;print(f"\n【分组显示】:")
&nbsp; &nbsp;&nbsp;for&nbsp;i&nbsp;inrange(8):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp;V[{i}] =&nbsp;{format(V[i],&nbsp;'08x').upper()}")

&nbsp; &nbsp;&nbsp;print(f"\n{'='&nbsp;*&nbsp;80}")
&nbsp; &nbsp;&nbsp;print("计算完成")
&nbsp; &nbsp;&nbsp;print(f"{'='&nbsp;*&nbsp;80}")

&nbsp; &nbsp;&nbsp;return&nbsp;hash_value

defmain():
&nbsp; &nbsp;&nbsp;"""主函数"""
&nbsp; &nbsp;&nbsp;print("="&nbsp;*&nbsp;80)
&nbsp; &nbsp;&nbsp;print("SM3密码杂凑算法实现")
&nbsp; &nbsp;&nbsp;print("基于GB/T 32905-2016标准")
&nbsp; &nbsp;&nbsp;print("="&nbsp;*&nbsp;80)

&nbsp; &nbsp;&nbsp;print("\n请选择输入类型:")
&nbsp; &nbsp;&nbsp;print(" &nbsp;1. 字符串输入")
&nbsp; &nbsp;&nbsp;print(" &nbsp;2. 十六进制输入")

&nbsp; &nbsp;&nbsp;whileTrue:
&nbsp; &nbsp; &nbsp; &nbsp; choice =&nbsp;input("\n请选择(1-2): ").strip()
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;choice&nbsp;in&nbsp;['1',&nbsp;'2']:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("输入错误,请重新选择!")

&nbsp; &nbsp;&nbsp;if&nbsp;choice ==&nbsp;'1':
&nbsp; &nbsp; &nbsp; &nbsp; input_data =&nbsp;input("请输入字符串: ").strip()
&nbsp; &nbsp; &nbsp; &nbsp; input_type =&nbsp;'string'
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp; input_data =&nbsp;input("请输入十六进制(例如: 616263): ").strip()
&nbsp; &nbsp; &nbsp; &nbsp; input_type =&nbsp;'hex'

&nbsp; &nbsp;&nbsp;print("\n是否显示所有64轮迭代的详细过程?")
&nbsp; &nbsp;&nbsp;print(" &nbsp;1. 显示前4轮和后4轮(推荐)")
&nbsp; &nbsp;&nbsp;print(" &nbsp;2. 显示所有64轮(输出较多)")

&nbsp; &nbsp;&nbsp;whileTrue:
&nbsp; &nbsp; &nbsp; &nbsp; detail_choice =&nbsp;input("\n请选择(1-2): ").strip()
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;detail_choice&nbsp;in&nbsp;['1',&nbsp;'2']:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("输入错误,请重新选择!")

&nbsp; &nbsp; show_all_rounds = (detail_choice ==&nbsp;'2')

&nbsp; &nbsp; result = sm3_hash_detailed(input_data, input_type, show_all_rounds)

&nbsp; &nbsp;&nbsp;print(f"\n最终结果:&nbsp;{result}")

if&nbsp;__name__ ==&nbsp;"__main__":
&nbsp; &nbsp; main()

该脚本可以:

  1. 1. 展示完整的计算步骤:包括消息填充、消息扩展、64轮迭代压缩等
  2. 2. 支持多种输入类型:字符串输入和十六进制输入
  3. 3. 可视化迭代过程:默认显示前4轮和后4轮迭代,可选择显示所有64轮
  4. 4. 详细的中间结果:每轮迭代中显示SS1、SS2、TT1、TT2等中间值的计算过程

5.3 脚本使用方法

  1. 1. 运行脚本
   python SM3计算过程详解.py
  1. 2. 选择输入类型
  • • 选项1:字符串输入
  • • 选项2:十六进制输入
  1. 3. 选择详细程度
  • • 选项1:显示前4轮和后4轮(推荐)
  • • 选项2:显示所有64轮

5.4 第三方库实现

实际应用中,建议使用成熟的密码学库,如gmssl,它提供了经过严格测试的SM3实现:

# 使用gmssl库的SM3实现示例
# 安装:pip install gmssl
from&nbsp;gmssl&nbsp;import&nbsp;sm3

message =&nbsp;"abc"
hash_value = sm3.sm3_hash(message.encode())
print(hash_value) &nbsp;# 输出:66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0

6. 对象标识符

SM3密码杂凑算法有以下对象标识符(OID):

6.1 主要OID

  • • id-dhf-sm3:{iso(1) member-body(2) cn(156) scctc(10197) algorithm(1) sm3(401)}
  • • 用于在密码协议和标准中唯一标识SM3算法

6.2 ASN.1定义

DedicatedHashFunctions {
&nbsp; &nbsp; iso(1) standard(0) hash-functions(10118) part3(3)
&nbsp; &nbsp; asn1-module(1) dedicated-hash-functions(0)}
DEFINITIONS EXPLICIT TAGS ::= BEGIN
&nbsp; &nbsp; -- 省略部分定义 --
&nbsp; &nbsp; id-scctc-algorithm OID ::= {iso(1) member-body(2) cn(156) scctc(10197) algorithm(1)}
&nbsp; &nbsp; id-sm3 OID ::= {id-scctc-algorithm sm3(401)}
&nbsp; &nbsp; id-dhf-sm3 OID ::= {id-scctc-algorithm sm3(401)}
&nbsp; &nbsp; -- 省略部分定义 --
END -- DedicatedHashFunctions --

6.3 用途

对象标识符用于在密码协议、数字证书和其他安全应用中明确标识所使用的SM3杂凑算法,确保不同系统之间的互操作性。

7. 总结

SM3密码杂凑算法是中国自主设计的专门密码学杂凑函数,具有高安全性和高效率的特点。作为国家标准,SM3在商用密码应用中发挥着重要作用,为数字签名、消息认证等安全服务提供了基础支持。

7.1 标准演进

  • • 2016年发布GB/T 32905—2016,首次规定SM3算法
  • • 2024年发布GB/T 18238.3—2024,将SM3纳入专门设计的杂凑函数标准体系

7.2 技术特点

  • • 采用基于轮函数的通用模型
  • • 不依赖其他密码原语,独立设计
  • • 具有良好的抗碰撞、抗原像和抗第二原像能力
  • • 适合软件和硬件实现

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:利刃信安 利刃信安 利刃信安《【密码算法】SM3 密码杂凑算法》

评论:0   参与:  0