用 Python 校验下载文件的 SHA-256
【摘要】 用 Python 标准库分块计算文件 SHA-256,校验下载内容,并区分摘要格式错误、内容不一致和文件读取失败。示例包含可运行的检查代码。
下载脚本、安装包或数据文件后,可以计算 SHA-256,并与发布方提供的摘要比较。这个过程能发现传输损坏或文件被替换的情况,但不能证明文件来源可信;摘要本身也需要来自可信渠道。
下面的示例分块读取文件,避免把大文件全部放入内存。它还会检查期望摘要的格式,减少因为空白、字母大小写或长度错误造成的误判。
from hashlib import sha256
from pathlib import Path
def file_sha256(path: Path, chunk_size: int = 1024 * 1024) -> str:
if chunk_size <= 0:
raise ValueError("chunk_size 必须大于 0")
digest = sha256()
with path.open("rb") as source:
while chunk := source.read(chunk_size):
digest.update(chunk)
return digest.hexdigest()
def verify_file(path: Path, expected: str) -> tuple[bool, str]:
expected = expected.strip().lower()
if len(expected) != 64 or any(c not in "0123456789abcdef" for c in expected):
raise ValueError("SHA-256 摘要必须是 64 位十六进制字符串")
actual = file_sha256(path)
return actual == expected, actual
if __name__ == "__main__":
path = Path("download.zip")
ok, actual = verify_file(
path,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
)
print(f"SHA-256: {actual}")
print("校验通过" if ok else "校验失败")
sha256() 返回的是哈希状态对象,read() 每次只读取一个数据块并交给 update()。因此,内存占用主要取决于 chunk_size,不会随文件大小线性增长。示例默认每块读取 1 MiB,对小文件也能正常工作。
verify_file() 先规范化期望值,再检查它是否为 64 位十六进制字符串。真实的摘要比较使用不区分大小写的十六进制字符;统一转成小写后比较即可。格式错误会直接抛出 ValueError,不会悄悄返回“失败”,这样可以区分输入错误和内容不一致。
可以用标准库做一个小规模检查:
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as directory:
sample = Path(directory) / "sample.bin"
sample.write_bytes(b"hello\n")
ok, actual = verify_file(
sample,
"5891B5B522D5DF086D0FF0B110FBD9D21BB4FC7163AF34D08286A2E846F6BE03",
)
assert ok is True
assert actual == "5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03"
ok, _ = verify_file(sample, "0" * 64)
assert ok is False
实际使用时,还要处理文件不存在、没有读取权限、磁盘 I/O 错误和下载不完整等情况。它们会以 FileNotFoundError、PermissionError 或 OSError 等形式出现,调用方应保留错误信息,方便定位问题。校验通过只说明当前文件与给定摘要一致,不能替代 HTTPS、签名验证或可信发布流程。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)