Python 实现 SHA-2 数字摘要签名算法

2024-09-03 03:52

本文主要是介绍Python 实现 SHA-2 数字摘要签名算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

      • 使用 Python 实现 SHA-2 数字摘要签名算法的博客
        • 引言
        • SHA-2 算法介绍
        • SHA-2 算法的详细步骤
        • Python 面向对象实现 SHA-256 算法
        • 代码解析
        • 应用场景:文件完整性验证
        • 总结

使用 Python 实现 SHA-2 数字摘要签名算法的博客

引言

SHA-2(Secure Hash Algorithm 2)是一组加密散列函数,由美国国家安全局(NSA)设计,并由国家标准与技术研究院(NIST)发布。SHA-2系列包含六种不同的哈希算法:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA-512/256。最常用的是 SHA-256 和 SHA-512。SHA-2 是 SHA-1 的后继者,比 SHA-1 提供更强的安全性,被广泛用于数字签名、证书生成和数据完整性验证等领域。

本文将详细介绍 SHA-2 算法的工作原理,提供一个基于 Python 面向对象的实现,并结合一个实际场景来演示如何使用 SHA-2 算法进行文件完整性验证。


SHA-2 算法介绍

SHA-2 是一种基于块的哈希算法,它对输入的消息进行处理,输出固定长度的哈希值(如 SHA-256 的 256 位,SHA-512 的 512 位)。SHA-2 的设计灵感来自 SHA-1,但做了重要改进,以增强抗碰撞和抗预映射攻击的能力。

SHA-2 算法的主要步骤包括:

  1. 消息填充(Padding):将消息的长度扩展到接近块大小的倍数(如 512 位或 1024 位)。
  2. 初始化哈希值:使用特定的初始哈希值来初始化状态变量。
  3. 消息分块处理:将消息分割成固定长度的块,并使用哈希计算循环迭代更新哈希值。
  4. 压缩函数(Compression Function):SHA-2 使用一个复杂的压缩函数,它在每轮操作中使用多个常量和位运算。
  5. 输出哈希值:生成一个固定长度的哈希值作为输出。
SHA-2 算法的详细步骤
  1. 消息填充

    • 原始消息在末尾添加一个 1 位,然后在末尾添加足够的 0 位,以使消息的长度接近块大小的倍数(例如 512 位或 1024 位)。最后,附加一个 64 位(或 128 位,取决于具体算法)的二进制数,表示填充前的消息长度。
  2. 初始化哈希值

    • SHA-2 使用一组初始哈希值(H0, H1, H2, …)来初始化状态。对于 SHA-256,这些初始值是前八个素数的平方根的小数部分的前 32 位。
  3. 处理消息块

    • 将消息分为512位(SHA-256)或1024位(SHA-512)的块。每个块再被划分为16个32位(SHA-256)或64位(SHA-512)的字(word)。
  4. 压缩函数

    • 对于每个块,SHA-2 进行多轮哈希计算。每轮计算包括扩展消息、使用逻辑函数和常量进行复杂操作,以及更新哈希值。SHA-256 进行 64 轮操作,SHA-512 进行 80 轮操作。
  5. 逻辑函数和常量

    • 使用多种逻辑函数(例如,右旋转、与、或、异或等)和固定的常量值来计算每轮操作的结果。
  6. 输出最终哈希值

    • 将每个块的计算结果累加到初始哈希值中,最后输出一个固定长度的哈希值。

Python 面向对象实现 SHA-256 算法

以下是一个基于 Python 面向对象的 SHA-256 实现,用于计算输入字符串的 SHA-256 哈希值。

import structclass SHA256:def __init__(self, message):"""初始化 SHA256 实例"""self.message = messageself.h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]self.k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]self._hash = self._calculate_sha256()def _right_rotate(self, n, b):"""执行右循环位移操作"""return ((n >> b) | (n << (32 - b))) & 0xFFFFFFFFdef _padding(self):"""对消息进行填充,使其长度为512的倍数"""original_byte_len = len(self.message)original_bit_len = original_byte_len * 8# 对消息填充一个 '1' 位self.message += b'\x80'# 填充 '0' 直到消息长度模512等于448位(56字节)self.message += b'\x00' * ((56 - (original_byte_len + 1) % 64) % 64)# 在最后添加64位的原始消息长度self.message += struct.pack('>Q', original_bit_len)def _calculate_sha256(self):"""计算 SHA-256 哈希值的主方法"""self.message = bytearray(self.message, 'utf-8')self._padding()# 每512位一个分组进行处理for i in range(0, len(self.message), 64):w = list(struct.unpack('>16L', self.message[i:i + 64])) + [0] * 48for j in range(16, 64):s0 = self._right_rotate(w[j - 15], 7) ^ self._right_rotate(w[j - 15], 18) ^ (w[j - 15] >> 3)s1 = self._right_rotate(w[j - 2], 17) ^ self._right_rotate(w[j - 2], 19) ^ (w[j - 2] >> 10)w[j] = (w[j - 16] + s0 + w[j - 7] + s1) & 0xFFFFFFFFa, b, c, d, e, f, g, h = self.h# 64轮操作for j in range(64):s1 = self._right_rotate(e, 6) ^ self._right_rotate(e, 11) ^ self._right_rotate(e, 25)ch = (e & f) ^ (~e & g)temp1 = (h + s1 + ch + self.k[j] + w[j]) & 0xFFFFFFFFs0 = self._right_rotate(a, 2) ^ self._right_rotate(a, 13) ^ self._right_rotate(a, 22)maj = (a & b) ^ (a & c) ^ (b & c)temp2 = (s0 + maj) & 0xFFFFFFFFh = gg = ff = ee = (d + temp1) & 0xFFFFFFFFd = cc = bb = aa = (temp1 + temp2) & 0xFFFFFFFFself.h = [(x + y) & 0xFFFFFFFF for x, y in zip(self.h, [a, b, c, d, e, f, g, h])]return ''.join(f'{i:08x}' for i in self.h)def hexdigest(self):"""返回最终的SHA-256哈希值"""return self._hash# 示例用法
if __name__ == "__main__":message = "Hello, SHA-256!"sha256 = SHA256(message)print(f"原始消息: {message}")print(f"SHA-256 哈希值: {sha256.hexdigest()}")
代码解析
  1. 消息填充与初始化_padding 方法用于填充消息,并确保其符合 SHA-256 要求的 512 位块大小。

  2. 逻辑操作_right_rotate 方法实现了右旋转操作,这是 SHA-256 哈希计算中的基础操作。

  3. 主哈希计算_calculate_sha256 方法实现了 SHA-256 的核心逻辑,包括消息调度、64 轮的哈希计算、以及状态变量更新。

  4. 输出结果hexdigest 方法返回计算所得的 SHA-256 哈希值。

应用场景:文件完整性验证

在文件传输或存储过程中,数据的完整性是非常重要的。SHA-256 哈希可以用于验证文件是否被篡改或损坏。以下是一个基于 Python 的场景演示,展示如何使用 SHA-256 算法进行文件完整性验证:

class FileIntegrityVerifier:def __init__(self, file_path):self.file_path = file_pathdef calculate_sha256(self):"""计算文件的SHA-256哈希值"""sha256 = SHA256("")hash_obj = hashlib.sha256()with open(self.file_path, 'rb') as f:for chunk in iter(lambda: f.read(4096), b''):hash_obj.update(chunk)return hash_obj.hexdigest()def verify_integrity(self, expected_hash):"""验证文件的完整性"""calculated_hash = self.calculate_sha256()print(f"计算得到的 SHA-256 哈希值: {calculated_hash}")return calculated_hash == expected_hash# 示例使用
file_verifier = FileIntegrityVerifier("example.txt")
expected_hash = "d47a8a..."if file_verifier.verify_integrity(expected_hash):print("文件完整性验证通过!")
else:print("文件可能已被篡改!")
总结

本文详细介绍了 SHA-2 算法的原理和 Python 实现,并提供了一个基于 SHA-256 的文件完整性验证示例。SHA-256 是一个安全性强、应用广泛的哈希算法,在信息安全中起着关键作用。了解其实现和应用有助于更好地掌握加密和安全技术。

这篇关于Python 实现 SHA-2 数字摘要签名算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131951

相关文章

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

C# Where 泛型约束的实现

《C#Where泛型约束的实现》本文主要介绍了C#Where泛型约束的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用的对象约束分类where T : structwhere T : classwhere T : ne

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

Python实现特殊字符判断并去掉非字母和数字的特殊字符

《Python实现特殊字符判断并去掉非字母和数字的特殊字符》在Python中,可以通过多种方法来判断字符串中是否包含非字母、数字的特殊字符,并将这些特殊字符去掉,本文为大家整理了一些常用的,希望对大家... 目录1. 使用正则表达式判断字符串中是否包含特殊字符去掉字符串中的特殊字符2. 使用 str.isa

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin