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

目录

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

引言

SHA-1(Secure Hash Algorithm 1)是一种安全哈希算法,用于生成一个固定长度的160位(20字节)哈希值。虽然SHA-1在密码学中的安全性已被削弱,不再建议用于数字签名等安全应用,但它仍然在某些非安全场景中使用。SHA-1的设计基于MD4和MD5算法,并被广泛用于数据完整性验证和哈希表等领域。

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


SHA-1 算法介绍

SHA-1 是一种基于块的哈希算法,它对输入的消息进行处理,输出固定长度的160位哈希值。SHA-1的工作原理与其他哈希算法类似,通过对输入数据进行多次非线性和不可逆的操作,生成唯一的摘要。

SHA-1 的主要步骤包括:

  1. 消息填充(Padding):将消息的长度扩展到接近512的倍数,最后64位表示原始消息的长度。
  2. 初始化哈希值:使用5个32位寄存器(A, B, C, D, E)来存储中间和最终的哈希值。
  3. 处理消息块:将消息块划分为512位的块,每块处理80轮,使用5个逻辑函数和固定常量来进行哈希计算。
  4. 输出哈希值:最后输出一个160位的哈希值。
SHA-1 算法的详细步骤
  1. 消息填充

    • 首先在消息的末尾添加一个 1 位,接着添加足够的 0 位,使其长度模512为448。
    • 然后在末尾附加一个64位的二进制数,表示填充前的消息长度。
  2. 初始化哈希值

    • SHA-1 使用五个32位的初始哈希值:
      • A = 0x67452301
      • B = 0xEFCDAB89
      • C = 0x98BADCFE
      • D = 0x10325476
      • E = 0xC3D2E1F0
  3. 处理每个消息块

    • 消息被分为512位的块,每个块再划分为16个32位的字(word)。
    • 然后扩展为80个字,每个字是前四个字的异或操作。
    • 对于每个字,SHA-1进行80轮的哈希运算,使用5个逻辑函数 F(t) 和5个常量 K(t)
  4. 逻辑函数

    • 不同的逻辑函数用于每20轮的操作:
      • F(t) = (B AND C) OR ((NOT B) AND D), 0 ≤ t ≤ 19
      • F(t) = B XOR C XOR D, 20 ≤ t ≤ 39
      • F(t) = (B AND C) OR (B AND D) OR (C AND D), 40 ≤ t ≤ 59
      • F(t) = B XOR C XOR D, 60 ≤ t ≤ 79
  5. 常量 K(t)

    • 每20轮的操作使用一个不同的常量:
      • K(0 ≤ t ≤ 19) = 0x5A827999
      • K(20 ≤ t ≤ 39) = 0x6ED9EBA1
      • K(40 ≤ t ≤ 59) = 0x8F1BBCDC
      • K(60 ≤ t ≤ 79) = 0xCA62C1D6
  6. 输出最终哈希值

    • 将每个块的计算结果累加到初始哈希值中,最后输出160位的哈希值。

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

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

python 复制代码
import struct

class SHA1:
    def __init__(self, message):
        """
        初始化SHA1实例
        """
        self.message = message
        self.h = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
        self._hash = self._calculate_sha1()

    def _left_rotate(self, n, b):
        """
        执行左循环位移操作
        """
        return ((n << b) | (n >> (32 - b))) & 0xFFFFFFFF

    def _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_sha1(self):
        """
        计算SHA-1哈希值的主方法
        """
        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] * 64
            for j in range(16, 80):
                w[j] = self._left_rotate(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1)

            a, b, c, d, e = self.h

            # 80轮操作
            for j in range(80):
                if 0 <= j <= 19:
                    f = (b & c) | ((~b) & d)
                    k = 0x5A827999
                elif 20 <= j <= 39:
                    f = b ^ c ^ d
                    k = 0x6ED9EBA1
                elif 40 <= j <= 59:
                    f = (b & c) | (b & d) | (c & d)
                    k = 0x8F1BBCDC
                else:
                    f = b ^ c ^ d
                    k = 0xCA62C1D6

                temp = (self._left_rotate(a, 5) + f + e + k + w[j]) & 0xFFFFFFFF
                e = d
                d = c
                c = self._left_rotate(b, 30)
                b = a
                a = temp

            # 更新初始哈希值
            self.h[0] = (self.h[0] + a) & 0xFFFFFFFF
            self.h[1] = (self.h[1] + b) & 0xFFFFFFFF
            self.h[2] = (self.h[2] + c) & 0xFFFFFFFF
            self.h[3] = (self.h[3] + d) & 0xFFFFFFFF
            self.h[4] = (self.h[4] + e) & 0xFFFFFFFF

        return ''.join(f'{value:08x}' for value in self.h)

    def hexdigest(self):
        """
        返回计算出来的SHA-1哈希值
        """
        return self._hash

# 使用SHA1算法计算哈希值
message = "Hello, SHA-1!"
sha1_instance = SHA1(message)
print(f"原始消息: {message}")
print(f"SHA-1哈希值: {sha1_instance.hexdigest()}")
代码解释
  1. SHA1类:该类实现了SHA-1算法的所有计算步骤和常量。
  2. _padding()方法:对消息进行填充操作,使其满足SHA-1算法的要求。
  3. _calculate_sha1()方法:实现了SHA-1算法的主步骤,包含消息扩展和80轮哈希计算。
  4. hexdigest()方法:返回计算出来的SHA-1哈希值。
场景应用:文件完整性验证

SHA-1常用于验证文件的完整性。假设你从网络上下载了一个文件,你可以使用SHA-1来计算文件的哈希值,并与文件发布者提供的SHA-1哈希值进行比较,验证文件是否被篡改。

示例:文件完整性验证
python 复制代码
import hashlib

class FileIntegrityChecker:
    def

 __init__(self, file_path):
        self.file_path = file_path

    def compute_sha1(self):
        sha1 = hashlib.sha1()
        with open(self.file_path, "rb") as f:
            while chunk := f.read(4096):
                sha1.update(chunk)
        return sha1.hexdigest()

    def verify(self, expected_sha1):
        calculated_sha1 = self.compute_sha1()
        print(f"计算得到的SHA-1哈希值: {calculated_sha1}")
        return calculated_sha1 == expected_sha1

# 示例用法
file_path = "example.txt"  # 替换为你的文件路径
checker = FileIntegrityChecker(file_path)
expected_sha1 = "expected_sha1_hash"  # 替换为预期的SHA-1值
if checker.verify(expected_sha1):
    print("文件完整性验证通过!")
else:
    print("文件可能被篡改!")
总结

本文详细介绍了SHA-1哈希算法的原理、Python实现及其在文件完整性验证中的应用。尽管SHA-1已不再被推荐用于安全场景,但在非安全应用中它仍然是一个有效的工具。理解和实现SHA-1算法,有助于加深对哈希算法的理解及其在信息安全中的作用。

相关推荐
追风赶月、9 分钟前
【QT】认识QT
开发语言·qt
Hockor30 分钟前
写给前端的 Python 教程三(字符串驻留和小整数池)
前端·后端·python
码农之王30 分钟前
记录一次,利用AI DeepSeek,解决工作中算法和无限级树模型问题
后端·算法
网安小张32 分钟前
解锁FastAPI与MongoDB聚合管道的性能奥秘
数据库·python·django
GeekAGI33 分钟前
Python 定时器框架
python
秋田君1 小时前
深入理解JavaScript设计模式之闭包与高阶函数
开发语言·javascript·设计模式
KENYCHEN奉孝1 小时前
Pandas和Django的示例Demo
python·django·pandas
拾零吖1 小时前
《Pytorch深度学习实践》ch8-多分类
人工智能·pytorch·python
亿牛云爬虫专家1 小时前
NLP驱动网页数据分类与抽取实战
python·分类·爬虫代理·电商·代理ip·网页数据·www.goofish.com
weixin_466485111 小时前
PyCharm中运行.py脚本程序
ide·python·pycharm