← 中文资源

简体中文版本

流式计算文件 SHA-256 校验和

按固定大小分块计算文件校验和,支持其他 hashlib 算法,并以常量时间核对期望摘要。

阅读英文原文

功能说明

file_checksum 以二进制模式打开文件,循环读取固定大小的块并更新哈希对象,因此不会把整个文件载入内存,适合校验大文件、下载包和备份镜像。默认使用 SHA-256,也可以通过 algorithm 指定 hashlib 支持的算法,例如 sha1、sha512 或 md5。chunk_size 可以按磁盘和网络特性调整。

verify_checksum 先计算实际摘要,再用 hmac.compare_digest 与期望值比较。这个比较是常量时间的,可以避免通过响应时间推测摘要内容。比较前会统一去掉期望值两端空白并转成小写,兼容常见的大写十六进制表示。

关键代码

核心循环使用海象运算符逐块读取,读到空字节串时结束:

with file_path.open("rb") as handle:
    while chunk := handle.read(chunk_size):
        digest.update(chunk)

文件不存在、权限不足或其他 I/O 错误会被包装成 ChecksumError,并保留原始异常作为 __cause__。不支持的算法同样转换成本模块的错误类型,调用方只需捕获一种异常。

使用注意

校验和只能检测意外损坏,不能替代签名或 MAC;如果攻击者可以同时替换文件和摘要,校验和无法证明来源可信。MD5 和 SHA-1 已不适合安全用途,仅可用于兼容旧系统。读取过程中文件可能被其他进程修改,校验结果会不确定;需要强一致时应先加锁或复制快照。

chunk_size 必须为正整数,过小会增加系统调用次数,过大则增加单次内存占用。函数接受 str 或 Path,其他类型交给 Path 构造并可能抛 TypeError。verify_checksum 不会自动识别摘要算法,调用方必须保证算法与期望值匹配。异常消息包含文件路径,记录日志时要注意路径隐私。

验证方式

示例在临时目录写入约 11 KB 的重复内容,以 256 字节分块计算 SHA-256,得到 64 位十六进制摘要。用同一摘要验证应返回 True,用全零摘要验证应返回 False。传入不存在的算法名应捕获并输出 unsupported algorithm: not-a-hash。可以再修改文件一个字节,确认摘要变化且验证失败。