【应用密码学】实验七 Hash函数——SM3

一、实验要求与目的

  1. 理解哈希函数的基本原理及在密码学中的应用;
  2. 掌握国密哈希标准 SM3 的算法结构;
  3. 编程实现 SM3 摘要算法,包括消息填充、消息扩展、压缩函数及摘要输出;
  4. 对中间变量 W、W′ 和 A~H 的迭代过程进行可视化,深入理解其内部机制。

二、实验内容与步骤记录(只记录关键步骤与结果,可截图,但注意排版与图片大小)

SM3 是一种基于 Merkle-Damgård结构 的杂凑算法,其流程可分为以下五大步骤:

消息预处理(填充 + 分组),消息扩展(生成 W 和 W′),压缩函数(A~H 迭代更新),状态反馈(初始向量 XOR 当前结果),输出摘要(256-bit)。所以我们分别对这些步骤进行设计

1.消息填充与分组处理

首先将输入字符串转换为二进制串,每个字符使用8位ASCII编码表示。

按照 SM3 填充规则:在消息后添加一个 1;添加 k 个 0,使得 l + 1 + k ≡ 448 mod 512;在末尾添加原始长度 l 的 64-bit 表示;

最终使得填充结果为 512 的整数倍(本实验为1组512位)。

2.消息扩展模块实现

W0–W15:初始划分

对每个 512bit 块 Bi,按 32bit 为单位划分为 16 个整数 W0​,W1​,...,W15​。

W16–W67:扩展计算

通过如下公式递推生成:

Wj=P1(Wj−16⊕Wj−9⊕(Wj−3⋘15))⊕(Wj−13⋘7)⊕Wj−6(16 ≤j < 68)

其中 P1(x)=x⊕(x⋘15)⊕(x⋘23)

W′0–W′63 计算

Wj′=Wj⊕Wj+4(0≤j<64)

可视化输出

实验中通过 print_expansion() 函数输出 W 与 W′ 的值(十六进制格式),验证扩展逻辑正确性。

3.压缩函数(64轮迭代)实现与输出

根据国密标准设定初始寄存器 A~H:

A = 0x7380166F

B = 0x4914B2B9

C = 0x172442D7

...

H = 0xB0EB0E4E

每一轮(共64轮)执行如下操作:

SS1 = ROTL((ROTL(A, 12) + E + ROTL(Tj, j)) & 0xFFFFFFFF, 7)

SS2 = SS1 ^ ROTL(A, 12)

TT1 = (FF(A,B,C,j) + D + SS2 + W′[j]) & 0xFFFFFFFF

TT2 = (GG(E,F,G,j) + H + SS1 + W[j]) & 0xFFFFFFFF

然后更新:

mathematica

D = C, C = ROTL(B,9), B = A, A = TT1

H = G, G = ROTL(F,19), F = E, E = P0(TT2)

每轮后输出一次 A~H 的状态:

j=00 → A=8742F2C2 B=7380166F ...

j=01 → A=4C71DB3E B=8742F2C2 ...

这样可跟踪 A~H 的变化趋势,验证压缩操作的动态过程。

4. 向量反馈与摘要输出

64轮结束后,将当前 A~H 与前一状态向量 V 进行逐位异或,形成新的向量:

V_next[i] = V[i] ^ current[i]  for i in 0..7

如果还有后续分组,则继续迭代。

当所有分组处理完成后,V 就是最终的 SM3 杂凑值。拼接 A~H,输出为 256bit 十六进制字符串:

66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0

该值与 SM3 标准样例一致,验证算法正确性。

三、源代码记录(关键代码需备注)

# -------------- 基础函数 ----------------#
def str_to_bin(msg: str) -> str:return ''.join(f'{ord(c):08b}' for c in msg)def padding_sm3(msg: str) -> str:m_bin = str_to_bin(msg)l = len(m_bin)m_bin += '1'k = (448 - (l + 1)) % 512m_bin += '0' * kl_bin = f'{l:064b}'m_bin += l_binreturn m_bindef left_rotate(x, n):n = n % 32return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFFdef split_blocks(m_bin: str, block_size=512):return [m_bin[i:i + block_size] for i in range(0, len(m_bin), block_size)]def binstr_to_int_list(block_512bit: str):return [int(block_512bit[i:i + 32], 2) for i in range(0, 512, 32)]# -------------- 扩展函数 ----------------#
def P1(X):return X ^ left_rotate(X, 15) ^ left_rotate(X, 23)def P0(X):return X ^ left_rotate(X, 9) ^ left_rotate(X, 17)def message_expand(block_512bit: str):W = binstr_to_int_list(block_512bit)for j in range(16, 68):term = P1(W[j - 16] ^ W[j - 9] ^ left_rotate(W[j - 3], 15))term = term ^ left_rotate(W[j - 13], 7) ^ W[j - 6]W.append(term & 0xFFFFFFFF)W_ = [(W[j] ^ W[j + 4]) & 0xFFFFFFFF for j in range(64)]return W, W_def print_expansion(W, W_):print("=== W[0..67] ===")for i in range(68):print(f"W[{i:02}] = {W[i]:08X}")print("\n=== W′[0..63] ===")for i in range(64):print(f"W′[{i:02}] = {W_[i]:08X}")# -------------- 压缩函数 ----------------#
def FF(X, Y, Z, j):return (X ^ Y ^ Z) if j < 16 else ((X & Y) | (X & Z) | (Y & Z))def GG(X, Y, Z, j):return (X ^ Y ^ Z) if j < 16 else ((X & Y) | (~X & Z))def CF(V, B):A, B_, C, D, E, F_, G, H = VW, W_ = message_expand(B)print("\n>>> [压缩函数初始化] <<<")print(f"A={A:08X} B={B_:08X} C={C:08X} D={D:08X} E={E:08X} F={F_:08X} G={G:08X} H={H:08X}")for j in range(64):Tj = 0x79CC4519 if j < 16 else 0x7A879D8ASS1 = left_rotate((left_rotate(A, 12) + E + left_rotate(Tj, j)) & 0xFFFFFFFF, 7)SS2 = SS1 ^ left_rotate(A, 12)TT1 = (FF(A, B_, C, j) + D + SS2 + W_[j]) & 0xFFFFFFFFTT2 = (GG(E, F_, G, j) + H + SS1 + W[j]) & 0xFFFFFFFFD = CC = left_rotate(B_, 9)B_ = AA = TT1H = GG = left_rotate(F_, 19)F_ = EE = P0(TT2)print(f"j={j:02} → A={A:08X} B={B_:08X} C={C:08X} D={D:08X} E={E:08X} F={F_:08X} G={G:08X} H={H:08X}")print(">>> [压缩函数结束] <<<")return [(v ^ n) & 0xFFFFFFFF for v, n in zip(V, [A, B_, C, D, E, F_, G, H])]# -------------- 哈希函数主控 ----------------#
def sm3_hash(msg: str, visual=True):IV = [0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0EB0E4E]padded = padding_sm3(msg)blocks = split_blocks(padded)print("原始长度:", len(str_to_bin(msg)), "bits")print("填充后总长度:", len(padded), "bits")print("填充后分组数量:", len(blocks))print("填充结果前64位:", padded[:64])print("填充结果末64位:", padded[-64:])V = IV[:]for i, block in enumerate(blocks):print(f"\n>>> 第 {i} 块 <<<")W, W_ = message_expand(block)if visual:print_expansion(W, W_)V = CF(V, block)digest = ''.join(f'{x:08x}' for x in V)print("\n最终 SM3 摘要为:")print(digest)return digest# -------------- 测试入口 ----------------#
if __name__ == "__main__":msg = "abc"  # 可以改为 input("请输入消息: ")sm3_hash(msg)

四、实验思考

1. SM3 摘要为什么不是最后一轮 A–H 值拼接?

SM3 采用 Merkle-Damgård 构架,每轮压缩结束后必须将前一状态 V 与当前 A–H 异或(XOR)。若直接使用 A~H 拼接会破坏反馈结构,易受长度扩展攻击。因此摘要为:

digest=Vn=Vn−1[A,B,...,H]\text{digest} = V_n = V_{n-1} \oplus [A,B,...,H]digest=Vn​=Vn−1​[A,B,...,H]

2. SM3 SHA-256 的主要区别有哪些?

项目

SM3

SHA-256

分组长度

512 bit

512 bit

输出长度

256 bit

256 bit

常量结构

轮常量分段不同

固定64个常量

置换函数

P0, P1

无(直接计算)

安全标准

国密标准 GM/T 0004-2012

国际标准 FIPS PUB 180-4

3. SM3 安全性基于什么?

SM3 作为哈希函数,其安全性包括抗碰撞性、抗第二原像性等,核心基于消息扩展、压缩函数的非线性变换和 Merkle-Damgård 结构的累积性。目前无有效攻击能在 2^128 复杂度下破坏 SM3 的抗碰撞性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进行性核上性麻痹护理之道:助力患者舒适生活

进行性核上性麻痹是一种缓慢进展的神经退行性疾病&#xff0c;主要影响患者的运动、语言和吞咽功能&#xff0c;给日常生活带来诸多不便。除了遵医嘱接受药物或物理治疗&#xff0c;科学的健康护理对延缓病情发展、提升生活质量尤为重要。 运动康复是护理的关键环节。由于患者常…

5G 核心网中 NRF 网元的功能、接口及参数详解

引言 在 5G 核心网的架构体系里,网络存储功能(Network Repository Function,NRF)占据着关键地位,承担着核心网网络功能(Network Function,NF)的注册、发现以及服务管理等重要任务,为整个 5G 网络的高效稳定运行提供了坚实支撑。接下来,让我们深入剖析 NRF 网元在注册…

HUAWEI交换机配置镜像口验证(eNSP)

技术术语&#xff1a; 流量观察口&#xff1a;就是我们常说的镜像口&#xff0c;被观察的流量的引流目的端口 流量源端口&#xff1a;企业生产端口&#xff0c;作为观察口观察对象。 命令介绍&#xff1a; [核心交换机]observe-port [观察端口ID或编号&#xff08;数字&am…

Spring AI Alibaba 发布企业级 MCP 分布式部署方案

作者&#xff1a; 影子&#xff0c;刘宏宇&#xff0c;刘军 Spring AI 通过集成 MCP 官方的 java sdk&#xff0c;让 Spring Boot 开发者可以非常方便的开发自己的 MCP 服务&#xff0c;把自己企业内部的业务系统通过标准 MCP 形式发布为 AI Agent 能够接入的工具&#xff1b;…

Redis实战-缓存篇(万字总结)

前言&#xff1a; 今天结合黑马点评这个项目&#xff0c;讲下有关Redis缓存的一些内容&#xff0c;例如缓存更新策略&#xff0c;缓存穿透&#xff0c;雪崩和击穿等。 今日所学&#xff1a; 什么是缓存缓存更新策略缓存穿透缓存雪崩缓存击穿缓存工具封存 目录 1.什么是缓存…

openFuyao开源发布,建设多样化算力集群开源软件生态

openFuyao 开源发布 随着 AI 技术的高速发展&#xff0c;算力需求呈爆发式增长&#xff0c;集群已成为主流生产方式。然而&#xff0c;当前集群软件生态发展滞后于硬件系统&#xff0c;面临多样化算力调度困难、超大规模集群软件支撑不足等挑战。这些问题的根源在于集群生产的…

深入理解 Redis 哨兵模式

Redis 哨兵模式深度解析&#xff1a;从原理到实践的全流程指南 在分布式系统架构中&#xff0c;Redis 作为高性能的内存数据库&#xff0c;其哨兵模式&#xff08;Sentinel&#xff09;是保障服务高可用性的核心方案。本文将从基础概念、运行机制出发&#xff0c;结合具体配置…

HackMyVM-Find

信息搜集 主机发现 ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:39:60:4c, IPv4: 192.168.43.126 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.43.1 c6:45:66:05:91:88 …

2025年渗透测试面试题总结-匿名[校招]安全服务工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 匿名[校招]安全服务工程师 一面问题与完整回答 1. 学校、专业、成绩与排名 2. 学习安全时长 3. 当前学习…

TopCode之手撕快排

题目链接 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 题目解析 算法原理 使用数组分三块的思想 i用来遍历整个数组 left用来标记<key的边界 right用来标记>key的边界 然后i进行遍历,数组就分成了四块 [l,left]<key [left1,i-1]key [i,right-1]未…

bi软件是什么?bi软件是做什么用的?

目录 一、BI 软件是什么 1. 基本概念 2. 工作原理 二、BI 软件是做什么用的&#xff1f; 1. 精准洞察市场趋势 2. 优化企业战略规划 3. 辅助投资决策 三、如何选择合适的 BI 软件 1.功能匹配度 2.易用性和可扩展性 3.数据安全和稳定性 4.技术支持和服务 总结 生产…

11.14 LangGraph检查点系统实战:AI Agent会话恢复率提升287%的企业级方案

使用 LangGraph 构建生产级 AI Agent:LangGraph 持久化与记忆的"检查点系统的实现" 关键词:LangGraph 检查点系统,多回合记忆,状态持久化,会话恢复,AI Agent 容错机制 1. 检查点系统的核心价值 在复杂对话场景中,AI Agent 需要处理长达数十轮甚至数百轮的交…

鸿蒙完整项目-仿盒马App(一)首页静态页面

跟着鸿蒙小林博主&#xff0c;练习下项目~记录下首页的搭建,后续继续完善和整体项目完成会进行布局修改&#xff0c;先按照博主的跟做&#xff0c;后续在改 1.分为底部整体框架搭建 2.首页布局&#xff08;顶部搜索、新人专享、金刚区&#xff08;两个不同集合数据&#xff09…

LINUX安装运行jeelowcode后端项目(idea启动)

参考 LINUX安装运行jeelowcode后端项目&#xff08;命令行&#xff09;-CSDN博客 IntelliJ IDEA下载地址&#xff08;社区版、付费版&#xff09;-CSDN博客 软件已安装好&#xff0c;数据库也初始化完毕。 步骤1&#xff1a;打开项目目录步骤2&#xff1a;配置JDK步骤3&…

Web Vitals 核心指标快速掌握指南

Next.js 内置了对测量和报告性能指标的支持,我们可以通过 useReportWebVitals 钩子自行管理报告。它会在应用的前端代码开始之前运行,用于对应用进行全局分析、错误跟踪以及性能监控。 本篇内容主要详细介绍 6 个性能分析的指标,帮助我们更好的进行性能优化。 1. TTFB 定…

专业课复习笔记 10

感觉专业课就是考研的几个科目里面难度最高的科目&#xff0c;我要好好加油&#xff0c;争取拿下一百二十分。这个要是过不了线&#xff0c;考研基本废完了。我感觉专业课练习题没有说像是数学那么多练习题&#xff0c;反而是需要自己仔细去理解里面的知识&#xff0c;记住知识…

C语言 文件操作(2)

目录 1.文件的顺序读写 2.文件的随机读写 3.文件读取结束的判定 4.文件的缓冲区 1.文件的读取顺序 1.1 顺序读写函数介绍 上面说的适用于所有输入流一般指适用于标准输入流和其他输入流&#xff08;如文件输入流&#xff09;&#xff1b;所有输出流 一般指适用于标准输出…

QGIS新手教程2:线图层与多边形图层基础操作指南(点线互转、中心点提取与WKT导出)

QGIS新手教程&#xff1a;线图层与多边形图层基础操作指南&#xff08;点线互转、中心点提取与WKT导出&#xff09; 目录 QGIS新手教程&#xff1a;线图层与多边形图层基础操作指南&#xff08;点线互转、中心点提取与WKT导出&#xff09;&#x1f4cc; 引言第一部分&#xff1…

Netty 框架介绍

1. Netty 框架介绍 Netty 是一个基于 Java NIO&#xff08;Non-blocking I/O&#xff09;的异步事件驱动网络应用框架&#xff0c;旨在快速开发高性能、高可靠性的网络服务器和客户端。它简化了 TCP/UDP 等协议的编程&#xff0c;并提供了高度可定制的组件&#xff0c;适用于高…

Eclipse 插件开发 5.2 编辑器 获取当前编辑器

Eclipse 插件开发 5.2 编辑器 获取当前编辑器 1 获取活跃编辑器2 获取全部编辑器 Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Click1 Bundle-SymbolicName: com.xu.click1;singleton:true Bundle-Version: 1.0.0 Bundle-Activator: com.xu.click1.Activato…