公司动态
Python模块:内置模块hashlib哈希与加密入门
Python模块内置模块hashlib哈希与加密入门一、开篇把任意数据变成固定长度的指纹哈希Hash函数接受任意长度的数据输出固定长度的摘要——就像数据的指纹。相同的输入永远产生相同的输出但输出无法反推出输入输入的任何微小变化都会导致输出完全不同雪崩效应。⌨️ 最简单的例子importhashlib# 对字符串做SHA256哈希messageHello, World!resulthashlib.sha256(message.encode()).hexdigest()print(f{message}的SHA256:)print(f{result})# 输出64个十六进制字符# dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f# 同样的输入永远产生同样的输出result2hashlib.sha256(message.encode()).hexdigest()print(resultresult2)# True# 输入有微小变化——输出完全不同message2Hello, world!# w变成小写result3hashlib.sha256(message2.encode()).hexdigest()print(f{message2}的SHA256:)print(f{result3})# 完全不同二、hashlib支持的算法importhashlib# 查看支持的算法print(支持的算法:,hashlib.algorithms_guaranteed)# {sha256, sha384, sha224, sha512, sha1, md5, blake2b, blake2s, ...}# 常用算法及输出长度algorithms{MD5:hashlib.md5,SHA1:hashlib.sha1,SHA224:hashlib.sha224,SHA256:hashlib.sha256,SHA384:hashlib.sha384,SHA512:hashlib.sha512,}dataPython hashlib 示例.encode()forname,funcinalgorithms.items():hfunc(data)print(f{name}:{h.digest_size}字节,{h.hexdigest()[:40]}...)# 安全性排名从低到高# MD5已破解不推荐用于安全 SHA1已破解 SHA256 SHA512三、基本使用模式3.1 三种使用方式importhashlib# 方式一一次性哈希数据量小时resulthashlib.sha256(bHello).hexdigest()# 方式二分步update()数据量大时如大文件hhashlib.sha256()h.update(bHello)h.update(b, )h.update(bWorld!)resulth.hexdigest()# 方式三一行链式调用resulthashlib.sha256(bHello, World!).hexdigest()# update()是累加的——等价于把数据拼接后一起哈希h1hashlib.sha256(bHello, World!).hexdigest()h2hashlib.sha256()h2.update(bHello, )h2.update(bWorld!)print(h1h2.hexdigest())# True# digest()返回二进制摘要hexdigest()返回十六进制字符串hhashlib.sha256(btest)print(f二进制:{h.digest()})print(f十六进制:{h.hexdigest()})3.2 大文件哈希importhashlibdeffile_sha256(filepath,chunk_size8192):计算文件的SHA256哈希值适合任意大小文件hhashlib.sha256()try:withopen(filepath,rb)asf:whileTrue:chunkf.read(chunk_size)ifnotchunk:breakh.update(chunk)returnh.hexdigest()exceptFileNotFoundError:returnNone# file_hash file_sha256(large_video.mp4)# print(f文件哈希: {file_hash})# 逐块读取每次只加载chunk_size字节到内存# 这样即使是几个GB的文件也不会撑爆内存四、实际应用4.1 密码的加盐哈希存储importhashlibimportos# ⚠️ 永远不要明文存储密码# ⚠️ 不要只用哈希存储密码彩虹表攻击# ✅ 正确做法加盐哈希defhash_password(password,saltNone):安全的密码哈希加盐多次迭代ifsaltisNone:saltos.urandom(32).hex()# 随机32字节盐# PBKDF2等效多次迭代hhashlib.sha256()h.update(salt.encode())h.update(password.encode())digesth.hexdigest()# 简单迭代10万次增加暴力破解成本for_inrange(100_000):hhashlib.sha256()h.update(digest.encode())h.update(salt.encode())digesth.hexdigest()returnf{salt}${digest}# 格式盐$哈希值defverify_password(password,stored):验证密码salt,_stored.split($,1)returnhash_password(password,salt)stored# 使用hashedhash_password(my_secret_password)print(f存储的哈希:{hashed})print(f正确密码:{verify_password(my_secret_password,hashed)})# Trueprint(f错误密码:{verify_password(wrong_password,hashed)})# False# 生产环境建议使用专门库# import bcrypt # pip install bcrypt# import argon2 # pip install argon2-cffi# Python 3.4标准库有 hashlib.pbkdf2_hmac()4.2 文件完整性校验importhashlibdefverify_file_integrity(filepath,expected_hash,algorithmsha256):验证文件完整性——对比哈希值hhashlib.new(algorithm)withopen(filepath,rb)asf:whileTrue:chunkf.read(8192)ifnotchunk:breakh.update(chunk)actual_hashh.hexdigest()is_validactual_hashexpected_hashprint(f文件:{filepath})print(f预期哈希:{expected_hash})print(f实际哈希:{actual_hash})print(f完整性:{✓ 通过ifis_validelse✗ 失败})returnis_valid# verify_file_integrity(download.zip,# abc123def456..., algorithmsha256)4.3 HMAC带密钥的哈希importhmacimporthashlib# HMACHash-based Message Authentication Code# 带密钥的哈希——验证数据完整性和来源secret_keybmy_secret_api_keymessagebimportant_data# 创建HMACsignaturehmac.new(secret_key,message,hashlib.sha256).hexdigest()print(fHMAC签名:{signature})# 验证HMAC使用compare_digest防止时序攻击defverify_hmac(message,signature,secret_key):安全地验证HMAC签名expectedhmac.new(secret_key,message,hashlib.sha256).hexdigest()returnhmac.compare_digest(expected,signature)print(f验证通过:{verify_hmac(message,signature,secret_key)})# Trueprint(f篡改检测:{verify_hmac(bhacked,signature,secret_key)})# False# HMAC的典型应用API签名、Cookie签名、JWT五、总结hashlib是Python数据安全的基础工具。从简单的数据校验到密码安全存储它都是不可或缺的。核心要点SHA256是安全场景的最低标准——MD5和SHA1已被淘汰密码存储必须加盐——防止彩虹表、相同密码不同哈希大文件逐块处理——用update()流式哈希数据校验完整性HMAC完整性认证加密用专门库——hashlib只管哈希加密用cryptography库✅ 记住hashlib.digest_size字节长度hashlib.hexdigest()输出最常用。