Python实现对txt文本内容的SHA1、MD5的hash值计算(不依赖hashlib库)
·
基于基本原理,不依赖hashlib库,实现对txt文件中文本内容的SHA1/MD5算法的hash值计算,支持文件拖拽,支持两个hash值校验一致性
目录
准备工作
- Python 3.12.4(华为镜像下载,https://mirrors.huaweicloud.com/python/)
- Notepad++:网上搜的任意版本都可以
- 配置notepad++:编写python后Ctrl+S保存.py文件,F5运行选择python安装目录下的python.exe或输入“python路径\python.exe "$(FULL_CURRENT_PATH)" & ECHO. & PAUSE & EXIT”,双引号中间为自己的python路径,保存设置快捷键F10,后期编辑按设置的快捷键F10即可运行
- 安装库:pip install hahslib tkinter tkinterdnd2
- pyinstaller:exe打包工具,cmd命令行输入 pip install pyinstaller 安装即可
Python代码
# Author: Johnny Zhang
# Date: 2024-10-29
# Description: This is a tool for hash calculation.
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinterdnd2 import TkinterDnD, DND_FILES
# 定义一些常量用于SHA1和MD5计算
SHA1_BLOCK_SIZE = 64
MD5_BLOCK_SIZE = 64
SHA1_DIGEST_SIZE = 20
MD5_DIGEST_SIZE = 16
# 辅助函数:将字节流转换为整数(大端序)
def bytes_to_int(bytes_data):
return int.from_bytes(bytes_data, byteorder='big')
# 辅助函数:将整数转换为字节流(大端序)
def int_to_bytes(num, length):
return num.to_bytes(length, byteorder='big')
# SHA1的逻辑函数
def sha1_f1(x, y, z):
return (x & y) | (~x & z)
def sha1_f2(x, y, z):
return x ^ y ^ z
def sha1_f3(x, y, z):
return (x & y) | (x & z) | (y & z)
def sha1_f4(x, y, z):
return x ^ y ^ z
# MD5的逻辑函数
def md5_f1(x, y, z):
return (x & y) | (~x & z)
def md5_f2(x, y, z):
return (x & z) | (y & ~z)
def md5_f3(x, y, z):
return x ^ y ^ z
def md5_f4(x, y, z):
return y ^ (x | ~z)
# SHA1的循环左移操作
def sha1_rotate_left(n, x):
return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
# MD5的循环左移操作
def md5_rotate_left(n, x):
return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
# 定义浏览文件方法,限定为txt格式,并显示文件内容
def browse_file(text_path, text_content):
file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
if file_path:
text_path.delete("1.0", tk.END)
text_path.insert(tk.END, file_path)
with open(file_path, 'r', encoding='utf-8') as f:
file_content = f.read()
text_content.delete("1.0", tk.END)
text_content.insert(tk.END, file_content)
text_hash.delete("1.0", tk.END)
# 定义计算SHA1哈希值的方法(不使用hashlib)
def calculate_sha1(text_content):
data = text_content.get("1.0", tk.END).encode('utf-8')
# 填充消息
padded_data = pad_sha1(data)
# 分割成块
blocks = [padded_data[i:i + SHA1_BLOCK_SIZE] for i in range(0, len(padded_data), SHA1_BLOCK_SIZE)]
# 初始化哈希值
h0 = 0x67452301
h1 = 0xEFCDAB89
h2 = 0x98BADCFE
h3 = 0x10325476
h4 = 0xC3014698
# 处理每个块
for block in blocks:
w = [0] * 80
for i in range(len(block)):
w[i // 4] |= bytes_to_int(block[i:i + 1]) << ((3 - (i % 4)) * 8)
for i in range(16, 80):
w[i] = sha1_rotate_left(1, w[i - 3] ^ w[i - 8] ^ w[i - 13] ^ w[i - 16])
a = h0
b = h1
c = h2
d = h3
e = h4
for i in range(80):
if 0 <= i < 20:
f = sha1_f1(b, c, d)
k = 0x5A827999
elif 20 <= i < 40:
f = sha1_f2(b, c, d)
k = 0x6ED9EBA1
elif 40 <= i < 60:
f = sha1_f3(b, c, d)
k = 0x8F1BBCDC
elif 60 <= i < 80:
f = sha1_f4(b, c, d)
k = 0xCA62C1D6
temp = sha1_rotate_left(5, a) + f + e + k + w[i]
e = d
d = c
c = sha1_rotate_left(3, b)
b = a
a = temp & 0xFFFFFFFF
h0 = (h0 + a) & 0xFFFFFFFF
h1 = (h1 + b) & 0xFFFFFFFF
h2 = (h2 + c) & 0xFFFFFFFF
h3 = (h3 + d) & 0xFFFFFFFF
h4 = (h4 + e) & 0xFFFFFFFF
return "{:08x}{:08x}{:08x}{:08x}{:08x}".format(h0, h1, h2, h3, h4)
# 定义计算MD5哈希值的方法(不使用hashlib)
def calculate_md5(text_content):
data = text_content.get("1.0", tk.END).encode('utf-8')
# 填充消息
padded_data = pad_md5(data)
# 分割成块
blocks = [padded_data[i:i + MD5_BLOCK_SIZE] for i in range(0, len(padded_data), MD5_BLOCK_SIZE)]
# 初始化哈希值
a = 0x67452301
b = 0xEFCDAB89
c = 0x98BADCFE
d = 0x10325476
# 处理每个块
for block in blocks:
w = [0] * 64
for i in range(len(block)):
w[i // 4] |= bytes_to_int(block[i:i + 1]) << ((3 - (i % 4)) * 8)
for i in range(16, 64):
w[i] = md5_rotate_left(1, w[i - 3] ^ w[i - 8] ^ w[i - 13] ^ w[i - 16])
aa = a
bb = b
cc = c
dd = d
for i in range(64):
if 0 <= i < 16:
f = md5_f1(b, c, d)
g = i
elif 16 <= i < 32:
f = md5_f2(b, c, d)
g = (5 * i + 1) % 16
elif 32 <= i < 48:
f = md5_f3(b, c, d)
g = (3 * i + 5) % 16
elif 48 <= i < 64:
f = md5_f4(b, c, d)
g = (7 * i) % 16
temp = md5_rotate_left(5, a) + f + c + w[g]
a = d
d = c
c = md5_rotate_left(3, b)
b = temp & 0xFFFFFFFF
a = (a + aa) & 0xFFFFFFFF
b = (b + bb) & 0xFFFFFFFF
c = (c + cc) & 0xFFFFFFFF
d = (d + dd) & 0xFFFFFFFF
return "{:08x}{:08x}{:08x}{:08x}".format(a, b, c, d)
# SHA1的填充函数
def pad_sha1(data):
padding_length = SHA1_BLOCK_SIZE - ((len(data) + 9) % SHA1_BLOCK_SIZE)
padding = b'\x80' + b'\x00' * (padding_length - 1)
length = int_to_bytes(len(data) * 8, 8)
return data + padding + length
# MD5的填充函数
def pad_md5(data):
padding_length = MD5_BLOCK_SIZE - ((len(data) + 9) % MD5_BLOCK_SIZE)
padding = b'\x80' + b'\x00' * (padding_length - 1)
length = int_to_bytes(len(data) * 8, 8)
return data + padding + length
# 定义计算hash方法
def calculate_hash(text_content, algorithm):
if algorithm == 'SHA1':
return calculate_sha1(text_content)
elif algorithm == 'MD5':
return calculate_md5(text_content)
# 定义更新hash方法
def update_hash(text_path, text_content, text_hash, algorithm_var):
file_path = text_path.get("1.0", tk.END).strip()
algorithm = algorithm_var.get()
hash_value = calculate_hash(text_content, algorithm)
text_hash.delete("1.0", tk.END)
text_hash.insert(tk.END, hash_value)
messagebox.showinfo("哈希值长度", f"当前{algorithm}算法计算哈希长度为:{len(hash_value)}")
# 定义校验hash方法
def check_hash(text_path, text_content, text_hash, original_hash):
calculated_hash = text_hash.get("1.0", tk.END).strip()
original = original_hash.get("1.0", tk.END).strip()
if calculated_hash == original:
messagebox.showinfo("校验结果", "计算hash 与 原始hash 校验一致!")
else:
messagebox.showinfo("校验结果", "计算hash 与 原始hash 校验不一致!")
# 定义窗体名称
root = TkinterDnD.Tk()
root.title("Hash计算工具_V0.2 By Johnny")
# 第一行:选择文件按钮和文件路径输入框,自动清空路径和计算hash值
browse_button = tk.Button(root, text="选择文件", width=15, command=lambda: (text_path.delete("1.0", tk.END),text_hash.delete("1.0", tk.END),browse_file(text_path, text_content)))
browse_button.grid(row=0, column=0, padx=10, pady=10)
# 文本框长度 50 字符,默认高度 3 行
text_path = tk.Text(root, width=50, height=3, wrap=tk.WORD)
text_path.grid(row=0, column=1, padx=10, pady=10)
# 新增文本框用于显示txt文件内容
text_content = tk.Text(root, width=50, height=5, wrap=tk.WORD)
text_content.grid(row=1, column=1, padx=10, pady=10)
# 鼠标左键长按拖动文件到文本框,自动清空路径和计算hash值,松开鼠标输入文件路径
text_path.drop_target_register(DND_FILES)
text_path.dnd_bind('<<Drop>>', lambda event: (text_path.delete("1.0", tk.END),text_path.insert(tk.END, event.data),text_hash.delete("1.0", tk.END)))
# 第二行:2个算法选择按钮
algorithm_var = tk.StringVar()
algorithm_var.set('SHA1') # 默认选中 SHA1
# 创建一个框架来容纳按钮
frame = tk.Frame(root)
frame.grid(row=2, column=0, columnspan=2, padx=10, pady=10) # 框架占据两列
# 自行调整单选按钮前后顺序
sha1_button = tk.Radiobutton(frame, text="SHA1", variable=algorithm_var, value='SHA1')
sha1_button.pack(side=tk.LEFT, padx=10)
md5_button = tk.Radiobutton(frame, text="MD5", variable=algorithm_var, value='MD5')
md5_button.pack(side=tk.LEFT, padx=10)
# 第三行:计算哈希值按钮和哈希值输入框
calculate_button = tk.Button(root, text="计算Hash", width=15, command=lambda: update_hash(text_path, text_content, text_hash, algorithm_var))
calculate_button.grid(row=3, column=0, padx=10, pady=10)
# 文本框长度 50 字符,默认高度 3 行
text_hash = tk.Text(root, width=50, height=3, wrap=tk.WORD)
text_hash.grid(row=3, column=1, padx=10, pady=10)
# 第四行:原始 Hash 校验按钮和输入框
check_button = tk.Button(root, text="原始Hash校验", width=15, command=lambda: check_hash(text_path, text_content, text_hash, original_hash))
check_button.grid(row=4, column=0, padx=10, pady=10)
# 文本框长度 50 字符,默认高度 3 行
original_hash = tk.Text(root, width=50, height=3, wrap=tk.WORD)
original_hash.grid(row=4, column=1, padx=10, pady=10)
root.mainloop()
bat一键打包exe独立程序
常用打包方法:在py文件目录地址栏输入cmd,输入以下命令打包exe,如要改exe程序logo,在py同目录自备logo.ico文件,最终exe文件在dist文件夹下
-
pyinstaller -F test.py -ntest #打包不带logo的exe
-
pyinstaller -F -w -i logo.ico test.py -ntest #打包带logo的exe
bat脚本命令打包:新建空白txt,输入以下命令后重名为*.bat后双击运行即可
@echo off
pyinstaller -F -w -i logo.ico --add-data "C:\Users\izhan\AppData\Local\Programs\Python\Python312\Lib\site-packages\tkinterdnd2;tkinterdnd2" hash.py
pause
因拖拽需使用tkinterdnd2库,常规打包运行后报错找不到tkdnd,估打包时需引用本地库,方法为“
pyinstaller -F -w -i logo.ico --add-data "本地库地址;库名" 文件名.py”

运行界面见下图

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)