1. PyCryptodome:Python开发者的加密利器
当你需要为Python应用添加加密功能时,PyCryptodome绝对是个绕不开的名字。这个库的前身是著名的PyCrypto,现在已经成为Python生态中最强大的密码学工具之一。我在多个实际项目中使用过它,从简单的文件加密到复杂的网络通信安全,PyCryptodome都能完美胜任。
PyCryptodome最吸引人的地方在于它提供了完整的密码学工具箱。无论是常见的AES对称加密,还是RSA非对称加密,甚至是各种哈希算法和数字签名,你都能在这里找到高质量的实现。更棒的是,它的API设计非常Pythonic,用起来就像在使用Python标准库一样自然。
安装PyCryptodome只需要一行命令:
pip install pycryptodome但要注意,如果你之前安装过PyCrypto,可能会遇到命名冲突。这时可以考虑使用pycryptodomex这个替代包,功能完全一样,只是为了避免命名冲突。
2. 对称加密实战:保护你的敏感数据
2.1 AES加密的多种模式
AES(高级加密标准)是目前最常用的对称加密算法。PyCryptodome提供了完整的AES实现,支持128位、192位和256位密钥长度。在实际项目中,我通常会选择256位密钥,因为它提供了最高级别的安全性。
AES有多种工作模式,每种模式都有其特点:
- ECB模式:最简单的模式,但不推荐用于加密大量数据,因为相同的明文块会产生相同的密文块
- CBC模式:需要初始化向量(IV),安全性更好,是我最常用的模式
- GCM模式:同时提供加密和认证功能,适合需要保证数据完整性的场景
下面是一个使用AES-CBC加密的完整示例:
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad # 生成随机密钥和IV key = get_random_bytes(32) # AES-256需要32字节密钥 iv = get_random_bytes(16) # AES块大小是16字节 # 准备要加密的数据 data = b"这是需要加密的敏感数据" # 加密 cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(data, AES.block_size)) # 解密 decipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(decipher.decrypt(ciphertext), AES.block_size) print(f"原始数据: {data}") print(f"加密后: {ciphertext.hex()}") print(f"解密后: {plaintext}")2.2 其他对称加密算法
除了AES,PyCryptodome还支持多种对称加密算法:
- ChaCha20:速度极快,特别适合移动设备和资源受限环境
- Blowfish:老牌加密算法,密钥长度可变
- DES/3DES:虽然已经不推荐使用,但在一些遗留系统中可能还会遇到
这里特别提一下ChaCha20,它在我的移动端项目中表现非常出色:
from Crypto.Cipher import ChaCha20 key = get_random_bytes(32) # ChaCha20需要32字节密钥 nonce = get_random_bytes(12) # 12字节随机数 cipher = ChaCha20.new(key=key, nonce=nonce) ciphertext = cipher.encrypt(b"移动端敏感数据") print(f"加密结果: {ciphertext.hex()}")3. 非对称加密与数字签名
3.1 RSA加密实战
非对称加密在安全通信中扮演着重要角色,RSA是最常用的算法之一。PyCryptodome的RSA实现既强大又易用。
生成RSA密钥对:
from Crypto.PublicKey import RSA key = RSA.generate(2048) # 2048位密钥 private_key = key.export_key() public_key = key.publickey().export_key() print(f"私钥:\n{private_key.decode()}") print(f"公钥:\n{public_key.decode()}")使用RSA加密数据:
from Crypto.Cipher import PKCS1_OAEP # 加载公钥 recipient_key = RSA.import_key(public_key) cipher_rsa = PKCS1_OAEP.new(recipient_key) # 加密 encrypted = cipher_rsa.encrypt(b"机密信息") # 解密 private_key = RSA.import_key(private_key) cipher_rsa = PKCS1_OAEP.new(private_key) decrypted = cipher_rsa.decrypt(encrypted) print(f"解密结果: {decrypted}")3.2 数字签名与验证
数字签名可以确保数据的完整性和来源真实性。PyCryptodome提供了完整的签名功能:
from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 # 准备数据 message = b"重要合同内容" hash_obj = SHA256.new(message) # 签名 signer = pkcs1_15.new(private_key) signature = signer.sign(hash_obj) # 验证 verifier = pkcs1_15.new(recipient_key) try: verifier.verify(hash_obj, signature) print("签名验证成功") except (ValueError, TypeError): print("签名验证失败")在实际项目中,我通常会结合对称和非对称加密。比如用RSA加密AES密钥,然后用AES加密实际数据,这样既保证了安全性又兼顾了性能。
4. 哈希算法与消息认证
4.1 安全哈希算法
哈希算法在密码学中有广泛应用,从密码存储到数据完整性校验。PyCryptodome支持所有主流哈希算法:
from Crypto.Hash import SHA256, SHA3_256, BLAKE2b data = b"需要计算哈希的数据" # SHA-256 h = SHA256.new(data) print(f"SHA-256: {h.hexdigest()}") # SHA3-256 h = SHA3_256.new(data) print(f"SHA3-256: {h.hexdigest()}") # BLAKE2b h = BLAKE2b.new(data) print(f"BLAKE2b: {h.hexdigest()}")对于密码存储,千万不要直接存储明文密码或简单的哈希值。正确的做法是使用加盐哈希:
import hashlib import os def hash_password(password): salt = os.urandom(32) # 生成随机盐 key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) return salt + key def verify_password(stored, password): salt = stored[:32] key = stored[32:] new_key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) return key == new_key # 使用示例 stored = hash_password("mysecretpassword") print(verify_password(stored, "mysecretpassword")) # True print(verify_password(stored, "wrongpassword")) # False4.2 HMAC消息认证
HMAC(基于哈希的消息认证码)可以确保消息在传输过程中不被篡改:
from Crypto.Hash import HMAC, SHA256 secret = b"共享密钥" message = b"重要消息" # 生成HMAC h = HMAC.new(secret, digestmod=SHA256) h.update(message) mac = h.hexdigest() # 验证 h = HMAC.new(secret, digestmod=SHA256) h.update(message) try: h.hexverify(mac) print("消息认证成功") except ValueError: print("消息被篡改")在实际的API开发中,我经常使用HMAC来验证请求的合法性,防止中间人攻击。
5. 实际应用场景与最佳实践
5.1 文件加密解密
文件加密是加密技术的常见应用场景。下面是一个完整的文件加密实现:
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import os def encrypt_file(input_file, output_file, password): # 生成随机盐和密钥 salt = get_random_bytes(32) key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32) # 加密文件 iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) with open(input_file, 'rb') as fin: with open(output_file, 'wb') as fout: fout.write(salt + iv) # 写入盐和IV while True: chunk = fin.read(64*1024) # 64KB chunks if len(chunk) == 0: break elif len(chunk) % 16 != 0: # 需要填充最后一个块 chunk = pad(chunk, 16) fout.write(cipher.encrypt(chunk)) def decrypt_file(input_file, output_file, password): with open(input_file, 'rb') as fin: salt = fin.read(32) iv = fin.read(16) key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32) cipher = AES.new(key, AES.MODE_CBC, iv) with open(output_file, 'wb') as fout: while True: chunk = fin.read(64*1024) if len(chunk) == 0: break fout.write(unpad(cipher.decrypt(chunk), 16)) # 使用示例 encrypt_file('敏感文档.pdf', '加密后的文件.enc', '强密码') decrypt_file('加密后的文件.enc', '解密后的文档.pdf', '强密码')5.2 安全通信实现
在网络通信中,我通常会结合多种加密技术来确保安全。下面是一个简化的安全通信示例:
import socket from Crypto.Cipher import AES, PKCS1_OAEP from Crypto.PublicKey import RSA def secure_server(): # 服务器密钥对 server_key = RSA.generate(2048) server_public = server_key.publickey() with socket.socket() as s: s.bind(('localhost', 12345)) s.listen() conn, addr = s.accept() # 发送公钥给客户端 conn.send(server_public.export_key()) # 接收客户端加密的AES密钥 encrypted_key = conn.recv(256) cipher_rsa = PKCS1_OAEP.new(server_key) aes_key = cipher_rsa.decrypt(encrypted_key) # 接收加密数据 iv = conn.recv(16) cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv) encrypted_data = conn.recv(1024) data = unpad(cipher_aes.decrypt(encrypted_data), AES.block_size) print(f"收到消息: {data.decode()}") def secure_client(): # 连接到服务器 s = socket.socket() s.connect(('localhost', 12345)) # 接收服务器公钥 server_public = RSA.import_key(s.recv(1024)) # 生成并加密AES密钥 aes_key = get_random_bytes(32) cipher_rsa = PKCS1_OAEP.new(server_public) encrypted_key = cipher_rsa.encrypt(aes_key) s.send(encrypted_key) # 加密并发送数据 iv = get_random_bytes(16) cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv) s.send(iv) message = pad(b"这是一条秘密消息", AES.block_size) encrypted = cipher_aes.encrypt(message) s.send(encrypted)6. 性能优化与安全注意事项
6.1 加密性能优化
加密操作可能会成为性能瓶颈,特别是在处理大量数据时。以下是我总结的几个优化技巧:
选择合适的算法:对于大量数据,对称加密比非对称加密快得多。AES-NI硬件加速可以显著提升AES性能。
合理设置块大小:在加密文件或网络流时,选择合适的块大小(如64KB)可以提高吞吐量。
并行处理:对于多核CPU,可以使用多线程或异步IO来并行加密多个数据块。
避免不必要的加密:不是所有数据都需要加密,合理区分敏感数据和非敏感数据。
6.2 安全最佳实践
在加密实践中,安全比性能更重要。以下是我踩过坑后总结的安全准则:
永远不要使用ECB模式:ECB模式会泄露数据模式,使用CBC或更好的GCM模式。
每次加密使用不同的IV:对于CBC等模式,重复使用IV会严重削弱安全性。
密钥管理要严格:加密的安全性最终取决于密钥的安全性。考虑使用硬件安全模块(HSM)或密钥管理服务。
定期更新密钥:即使没有密钥泄露的证据,也应该定期更换加密密钥。
使用认证加密:像GCM这样的模式不仅加密数据,还能验证数据完整性。
不要自己发明加密算法:总是使用经过验证的标准算法和实现,如PyCryptodome提供的那些。
7. 常见问题与解决方案
在实际项目中,我遇到过不少加密相关的问题。以下是几个典型问题及其解决方案:
问题1:加密后的数据无法解密
可能原因:
- 加密和解密使用了不同的密钥或IV
- 填充方式不一致
- 加密模式不匹配
解决方案:
- 确保密钥、IV和加密模式一致
- 检查填充设置(PKCS7是常用选择)
- 记录加密时使用的所有参数
问题2:加密性能太差
可能原因:
- 使用了不合适的算法(如用RSA加密大量数据)
- 块大小设置不合理
- 没有利用硬件加速
解决方案:
- 对大量数据使用对称加密
- 调整块大小(通常64KB是个好起点)
- 确保启用了AES-NI等硬件加速
问题3:跨平台兼容性问题
可能原因:
- 不同平台实现的加密算法有细微差异
- 编码方式不同
- 填充处理不一致
解决方案:
- 明确指定所有参数(如填充方式、加密模式)
- 使用标准编码(如Base64)
- 进行充分的跨平台测试
8. 深入理解加密模式
8.1 块加密模式详解
不同的加密模式适用于不同场景:
- ECB(电子密码本):简单但不安全,相同的明文块产生相同的密文块
- CBC(密码块链接):需要IV,安全性好,但不能并行加密
- CTR(计数器):将块密码转换为流密码,可以并行加密
- GCM(Galois/计数器模式):提供加密和认证,性能好,适合网络通信
8.2 认证加密模式
认证加密(AEAD)同时提供机密性和完整性。PyCryptodome支持以下AEAD模式:
- GCM:最常用的AEAD模式,高效安全
- EAX:比GCM更简单,但效率稍低
- SIV:对nonce误用有更强抵抗力
GCM模式示例:
from Crypto.Cipher import AES key = get_random_bytes(32) data = b"需要加密和认证的数据" header = b"关联数据(不加密但认证)" # 加密 cipher = AES.new(key, AES.MODE_GCM) cipher.update(header) # 添加关联数据 ciphertext, tag = cipher.encrypt_and_digest(data) nonce = cipher.nonce # 需要保存用于解密 # 解密 cipher = AES.new(key, AES.MODE_GCM, nonce=nonce) cipher.update(header) try: plaintext = cipher.decrypt_and_verify(ciphertext, tag) print("解密成功:", plaintext) except ValueError: print("认证失败,数据被篡改")9. 密钥管理与安全存储
9.1 密钥生成最佳实践
安全的密钥生成至关重要:
- 使用足够熵:密钥应该来自密码学安全的随机源
- 足够长度:AES至少128位,RSA至少2048位
- 避免人为选择:不要使用人为选择的"随机"密钥
PyCryptodome提供了安全的随机数生成:
from Crypto.Random import get_random_bytes # 生成安全随机密钥 aes_key = get_random_bytes(32) # AES-256 rsa_key = RSA.generate(2048) # RSA-20489.2 密钥存储方案
存储密钥是个挑战,常见方案包括:
- 环境变量:简单但不适合长期存储
- 密钥管理服务:如AWS KMS、Hashicorp Vault
- 硬件安全模块(HSM):最高安全性
- 密码保护的密钥文件:折中方案
密码保护密钥示例:
from Crypto.Protocol.KDF import scrypt from Crypto.IO import PEM key = get_random_bytes(32) password = "强密码" # 加密并保存密钥 salt = get_random_bytes(16) key_derived = scrypt(password, salt, key_len=32, N=2**14, r=8, p=1) cipher = AES.new(key_derived, AES.MODE_GCM) ciphertext, tag = cipher.encrypt_and_digest(key) with open("key.enc", "wb") as f: f.write(salt + cipher.nonce + tag + ciphertext) # 加载并解密密钥 with open("key.enc", "rb") as f: data = f.read() salt = data[:16] nonce = data[16:32] tag = data[32:48] ciphertext = data[48:] key_derived = scrypt(password, salt, key_len=32, N=2**14, r=8, p=1) cipher = AES.new(key_derived, AES.MODE_GCM, nonce=nonce) key = cipher.decrypt_and_verify(ciphertext, tag)10. 密码学哈希的高级应用
10.1 密码哈希
存储用户密码时,直接使用SHA-256等普通哈希是不够的。应该使用专门的密码哈希函数:
from Crypto.Protocol.KDF import scrypt from Crypto.Random import get_random_bytes # 创建密码哈希 password = "userpassword" salt = get_random_bytes(16) key = scrypt(password, salt, key_len=32, N=2**14, r=8, p=1) # 验证密码 def verify_password(stored_salt, stored_key, password): new_key = scrypt(password, stored_salt, key_len=32, N=2**14, r=8, p=1) return new_key == stored_key10.2 密钥派生函数
从密码派生出加密密钥时,应该使用专门的KDF:
- PBKDF2:老标准,但仍然安全
- scrypt:内存密集型,抗硬件攻击
- Argon2:密码哈希竞赛获胜者,最先进
scrypt示例:
from Crypto.Protocol.KDF import scrypt password = "weakpassword" salt = get_random_bytes(16) key = scrypt(password, salt, key_len=32, N=2**14, r=8, p=1)11. 数字证书与PKI
11.1 创建自签名证书
PyCryptodome可以处理X.509证书:
from Crypto.PublicKey import RSA from Crypto.X509 import Certificate from Crypto.X509.Extension import SubjectAltName from datetime import datetime, timedelta # 生成密钥对 key = RSA.generate(2048) # 创建证书 cert = Certificate() cert.set_version(3) cert.set_serial_number(1000) cert.set_issuer([("CN", "My CA")]) cert.set_subject([("CN", "localhost")]) cert.set_not_before(datetime.utcnow()) cert.set_not_after(datetime.utcnow() + timedelta(days=365)) cert.set_pubkey(key.publickey()) # 添加扩展 ext = SubjectAltName() ext.add_dns("localhost") cert.add_extension(ext) # 自签名 cert.sign(key, "sha256") # 导出 with open("cert.pem", "wb") as f: f.write(cert.export()) with open("key.pem", "wb") as f: f.write(key.export_key())11.2 验证证书链
证书验证是PKI的核心:
from Crypto.X509 import load_pem_x509_certificate # 加载CA证书 with open("ca.pem", "rb") as f: ca_cert = load_pem_x509_certificate(f.read()) # 加载待验证证书 with open("cert.pem", "rb") as f: cert = load_pem_x509_certificate(f.read()) # 验证 if cert.verify(ca_cert.get_pubkey()): print("证书验证成功") else: print("证书验证失败")12. 多因素认证实现
12.1 TOTP实现
时间型一次性密码(TOTP)是常见的2FA方式:
import hmac import hashlib import time import base64 def generate_totp(secret, interval=30): counter = int(time.time()) // interval msg = counter.to_bytes(8, byteorder="big") digest = hmac.new(base64.b32decode(secret), msg, hashlib.sha1).digest() offset = digest[-1] & 0x0F binary = (digest[offset] & 0x7F) << 24 | (digest[offset+1] & 0xFF) << 16 | \ (digest[offset+2] & 0xFF) << 8 | (digest[offset+3] & 0xFF) return binary % 10**6 # 使用示例 secret = base64.b32encode(get_random_bytes(10)).decode() # 生成随机密钥 print("TOTP密码:", generate_totp(secret))12.2 HOTP实现
基于计数器的一次性密码(HOTP):
def generate_hotp(secret, counter): msg = counter.to_bytes(8, byteorder="big") digest = hmac.new(base64.b32decode(secret), msg, hashlib.sha1).digest() offset = digest[-1] & 0x0F binary = (digest[offset] & 0x7F) << 24 | (digest[offset+1] & 0xFF) << 16 | \ (digest[offset+2] & 0xFF) << 8 | (digest[offset+3] & 0xFF) return binary % 10**6 # 使用示例 counter = 1 print("HOTP密码:", generate_hotp(secret, counter))13. 安全随机数生成
13.1 密码学安全随机数
PyCryptodome提供了多种随机数生成方式:
from Crypto.Random import get_random_bytes from Crypto.Random.random import randint, choice # 生成随机字节 random_bytes = get_random_bytes(32) # 生成随机整数 random_int = randint(0, 100) # 从序列中随机选择 items = ["apple", "banana", "cherry"] random_item = choice(items)13.2 随机数种子
对于需要确定性的场景,可以设置随机种子:
from Crypto.Random import random random.seed(b"固定种子") # 现在生成的随机数将是确定性的 print(random.randint(0, 100)) print(random.randint(0, 100))14. 性能对比与算法选择
14.1 对称加密算法性能
不同对称加密算法的性能差异很大:
| 算法 | 密钥长度 | 速度 | 安全性 | 适用场景 |
|---|---|---|---|---|
| AES | 128/192/256 | 快 | 高 | 通用加密 |
| ChaCha20 | 256 | 非常快 | 高 | 移动设备、网络 |
| Blowfish | 可变 | 中等 | 中 | 遗留系统 |
| 3DES | 168 | 慢 | 中 | 兼容旧系统 |
14.2 哈希算法性能
哈希算法的选择也很重要:
| 算法 | 输出长度 | 速度 | 安全性 | 适用场景 |
|---|---|---|---|---|
| SHA-256 | 256位 | 快 | 高 | 通用哈希 |
| SHA3-256 | 256位 | 中等 | 高 | 高安全性需求 |
| BLAKE2b | 可变 | 非常快 | 高 | 高性能需求 |
| MD5 | 128位 | 非常快 | 低 | 仅校验和 |
15. 调试与错误处理
15.1 常见异常处理
加密操作可能抛出多种异常:
from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto import Random try: key = get_random_bytes(32) iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) data = pad(b"test", AES.block_size) encrypted = cipher.encrypt(data) # 故意制造错误 bad_cipher = AES.new(key, AES.MODE_CBC, iv) bad_cipher.decrypt(encrypted[:-1]) # 截断密文 except ValueError as e: print(f"填充错误: {e}") except TypeError as e: print(f"类型错误: {e}") except Exception as e: print(f"其他错误: {e}")15.2 日志记录
加密操作应该记录适当日志:
import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("crypto") def encrypt_data(data, key): try: iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) encrypted = cipher.encrypt(pad(data, AES.block_size)) logger.info("数据加密成功") return iv + encrypted except Exception as e: logger.error(f"加密失败: {e}", exc_info=True) raise16. 测试与验证
16.1 单元测试加密功能
为加密代码编写测试非常重要:
import unittest from Crypto.Cipher import AES class TestEncryption(unittest.TestCase): def setUp(self): self.key = get_random_bytes(32) self.iv = get_random_bytes(16) self.data = b"测试数据" def test_encrypt_decrypt(self): cipher = AES.new(self.key, AES.MODE_CBC, self.iv) encrypted = cipher.encrypt(pad(self.data, AES.block_size)) cipher = AES.new(self.key, AES.MODE_CBC, self.iv) decrypted = unpad(cipher.decrypt(encrypted), AES.block_size) self.assertEqual(self.data, decrypted) def test_wrong_key(self): cipher = AES.new(self.key, AES.MODE_CBC, self.iv) encrypted = cipher.encrypt(pad(self.data, AES.block_size)) wrong_key = get_random_bytes(32) cipher = AES.new(wrong_key, AES.MODE_CBC, self.iv) with self.assertRaises(Exception): unpad(cipher.decrypt(encrypted), AES.block_size) if __name__ == "__main__": unittest.main()16.2 性能测试
评估加密操作的性能:
import timeit def test_aes_speed(): key = get_random_bytes(32) iv = get_random_bytes(16) data = get_random_bytes(1024 * 1024) # 1MB数据 def encrypt(): cipher = AES.new(key, AES.MODE_CBC, iv) cipher.encrypt(pad(data, AES.block_size)) time = timeit.timeit(encrypt, number=10) print(f"AES加密1MB数据平均耗时: {time/10:.3f}秒") test_aes_speed()17. 与其他库的集成
17.1 与hashlib集成
PyCryptodome可以与Python标准库hashlib配合使用:
from Crypto.Hash import SHA256 as CSHA256 import hashlib data = b"比较哈希实现" # PyCryptodome实现 c_hash = CSHA256.new(data).hexdigest() # hashlib实现 py_hash = hashlib.sha256(data).hexdigest() print(f"PyCryptodome SHA-256: {c_hash}") print(f"hashlib SHA-256: {py_hash}") print(f"结果一致: {c_hash == py_hash}")17.2 与SSL/TLS集成
可以将PyCryptodome生成的密钥用于SSL/TLS:
from Crypto.PublicKey import RSA import ssl # 生成RSA密钥 key = RSA.generate(2048) with open("key.pem", "wb") as f: f.write(key.export_key("PEM")) # 创建自签名证书 from OpenSSL import crypto cert = crypto.X509() cert.get_subject().CN = "localhost" cert.set_serial_number(1000) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(365*24*60*60) cert.set_issuer(cert.get_subject()) cert.set_pubkey(crypto.PKey.from_cryptography_key(key.publickey())) cert.sign(crypto.PKey.from_cryptography_key(key), "sha256") with open("cert.pem", "wb") as f: f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) # 使用证书创建SSL上下文 context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) context.load_cert_chain("cert.pem", "key.pem")18. 资源管理与安全清理
18.1 安全内存清理
敏感数据应该从内存中安全清除:
from Crypto.Util import Padding from Crypto.Cipher import AES import ctypes def secure_encrypt(data, password): # 派生密钥 salt = get_random_bytes(16) key = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1, dklen=32) # 加密 iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) padded = pad(data, AES.block_size) encrypted = cipher.encrypt(padded) # 安全清理内存 for i in range(len(key)): key[i] = 0 for i in range(len(padded)): padded[i] = 0 # 使用ctypes彻底清除 ctypes.memset(id(key), 0, len(key)) ctypes.memset(id(padded), 0, len(padded)) return salt + iv + encrypted18.2 安全文件删除
彻底删除包含敏感数据的文件:
import os import random def secure_delete(filename, passes=3): with open(filename, "ba+") as f: length = f.tell() for _ in range(passes): f.seek(0) f.write(os.urandom(length)) os.remove(filename) # 使用示例 with open("temp.txt", "w") as f: f.write("敏感数据") secure_delete("temp.txt")19. 密码学协议实现
19.1 实现Diffie-Hellman密钥交换
from Crypto.PublicKey import DH from Crypto.Random import get_random_bytes # 双方生成DH参数 parameters = DH.generate(2048) # Alice生成密钥对 alice_key = parameters.generate_private_key() alice_public = alice_key.publickey() # Bob生成密钥对 bob_key = parameters.generate_private_key() bob_public = bob_key.publickey() # 交换公钥后生成共享密钥 alice_shared = alice_key.derive(bob_public) bob_shared = bob_key.derive(alice_public) print(f"Alice的共享密钥: {alice_shared.hex()}") print(f"Bob的共享密钥: {bob_shared.hex()}") print(f"密钥匹配: {alice_shared == bob_shared}")19.2 实现秘密共享
from Crypto.Protocol.SecretSharing import Shamir # 分割秘密 secret = b"最高机密" shares = Shamir.split(3, 5, secret) # 3个份额可恢复,共生成5个 # 恢复秘密 recovered = Shamir.combine(shares[:3]) print(f"恢复的秘密: {recovered}")20. 硬件加速与优化
20.1 检查AES-NI支持
from Crypto.Cipher import AES from Crypto.Util import cpuid if cpuid.have_aes_ni(): print("CPU支持AES-NI加速") # 强制使用AES-NI cipher = AES.new(get_random_bytes(32), AES.MODE_CBC, get_random_bytes(16), use_aesni=True) else: print("CPU不支持AES-NI,使用软件实现")20.2 多线程加密
对于大文件,可以使用多线程加速:
from concurrent.futures import ThreadPoolExecutor from Crypto.Cipher import AES def encrypt_chunk(key, iv, chunk): cipher = AES.new(key, AES.MODE_CBC, iv) return cipher.encrypt(pad(chunk, AES.block_size)) def parallel_encrypt(filename, output, key, threads=4): iv = get_random_bytes(16) chunk_size = 1024 * 1024 # 1MB with open(filename, "rb") as fin, open(output, "wb") as fout: fout.write(iv) # 写入IV with ThreadPoolExecutor(max_workers=threads) as executor: while True: chunks = [fin.read(chunk_size) for _ in range(threads)] if not any(chunks): break # 并行加密 futures = [] for chunk in chunks: if chunk: futures.append(executor.submit( encrypt_chunk, key, iv, chunk)) # 按顺序写入 for future in futures: fout.write(future.result())21. 密码学常见误区
21.1 常见安全错误
- 使用弱密码算法:如DES、RC4、MD5等
- 重复使用IV/nonce:特别是在CBC和CTR模式中
- **不验证