Python3 hashlib 模块

哈希(散列)算法能把任意长度的数据算成一个固定长度的"指纹"字符串:同样的输入必然得到同样的输出,且几乎无法从结果反推原文。典型用途是文件完整性校验与密码的不可逆存储。Python 的 hashlib 模块封装了 md5、sha1、sha256 等常用算法。

基本用法:md5 / sha1 / sha256

给算法喂字节串(字符串需加 b 或先 .encode()),再用 hexdigest() 取十六进制结果:

import hashlib

print(hashlib.md5(b'hello').hexdigest())
# 输出:5d41402abc4b2a76b9719d911017c592
print(hashlib.sha1(b'hello').hexdigest())
# 输出:aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
print(hashlib.sha256(b'hello').hexdigest())
# 输出:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

# 中文字符串需编码成字节
print(hashlib.md5('你好'.encode('utf-8')).hexdigest())

注意:同一算法、同一输入,任何机器任何时间计算结果都相同;多一个空格或换行结果就完全不同。

update 分块更新

数据较大或分段得到时,可多次 update,效果等价于一次性喂入全部数据:

import hashlib

h = hashlib.sha256()
h.update(b'hello ')
h.update(b'world')          # 等价于 h.update(b'hello world')
print(h.hexdigest())
# 输出:b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

文件完整性校验

逐块读取大文件计算哈希,用于校验下载的文件是否完整:

import hashlib

h = hashlib.md5()
with open('file.zip', 'rb') as f:        # 二进制方式打开
    for chunk in iter(lambda: f.read(4096), b''):
        h.update(chunk)
print('文件 MD5:', h.hexdigest())

加盐存储密码示例

直接用 md5 存密码很危险:相同密码得到相同哈希,攻击者可借助"彩虹表"反查。加盐即给密码拼一段随机字符串再哈希,同一密码因盐不同而哈希不同:

import hashlib
import os

password = '123456'
salt = os.urandom(16).hex()              # 每个用户生成不同的随机盐
digest = hashlib.sha256((salt + password).encode()).hexdigest()
print('盐   :', salt)                   # 输出:如 8f3a2c...(随机)
print('摘要 :', digest)                 # 输出:64 位十六进制
# 数据库同时保存 salt 与 digest;
# 登录时用该用户的盐重新计算再与 digest 比较,相同则密码正确。

密码安全提示

  • 不要用 md5/sha1 直接存储用户密码,它们已被证明不够安全;存储密码应优先考虑专门的慢哈希算法(如 bcrypt、scrypt、argon2,属第三方库)。
  • md5/sha1 仍广泛用于文件校验、内容去重等非安全场景。
  • 盐要随机、每个用户独立,长度建议至少 16 字节。

小结

hashlib 用法统一:选算法 → 喂字节 → hexdigest() 出结果,大文件用 update 分块。记住"校验文件用 md5/sha256,存储密码必须加盐或改用慢哈希"。

笔记加载中…