- 简介
- 安装
- 方法一:Visual Studio
- 方法二:pycryptodome(推荐)
- 初试
- 公钥
- 加解密
- 对称加密
- 非对称加密
- 数字签名
- 哈希函数
- 安全通信
- 加密IO
- 封装
- 遇到的坑
- 参考文献
pycrypto 实现了哈希函数(如 SHA256)和加密算法(如 AES、DES、RSA)。
注意!pycrypto 已很久未维护,有安全漏洞。
建议使用 pycryptodome 替代 pycrypto,它是后者的一个分支,一直在维护。
以下方法均可,推荐方法二。
Windows 需要安装 Visual Studio 2015 或以上版本,本人是 Visual Studio 2017,安装方法大同小异。
cd C:Program Files (x86)Microsoft Visual Studio2017ProfessionalVCAuxiliaryBuild vcvars64.bat set CL=-FI"C:Program Files (x86)Microsoft Visual Studio2017ProfessionalVCToolsMSVC14.16.27023includestdint.h" pip install pycrypto
也可以用 pycryptodome 替代 pycrypto,它是后者的一个分支,一直在维护。
pip uninstall pycrypto pip install pycryptodome
SHA256 计算散列值(哈希值)
from Crypto.Hash import SHA256
hash = SHA256.new()
hash.update('message'.encode())
print(hash.digest())
# b'xabSnx13xe4Yx14x98+yxf9xb7xe3xfbxa9x94xcfxd1xf3xfb"xf7x1cxeax1axfbxf0+Fx0cmx1d'
公钥系统下,发送方和接收方使用不同密钥——公钥或私钥。
| 场景 | 发送方 | 接收方 |
|---|---|---|
| 加解密 | 公钥 | 私钥 |
| 数字签名 | 私钥 | 公钥 |
from Crypto.PublicKey import RSA
key_pair = RSA.generate(4096) # 生成密钥对
open('public.pem', 'wb').write(key_pair.public_key().export_key('PEM')) # 导出公钥
open('private.pem', 'wb').write(key_pair.export_key('PEM')) # 导出私钥
三种加密方式:
- 对称加密:参与方使用相同密钥进行加解密,速度快,适合处理大量数据。如 AES。
- 非对称加密:发送方使用公钥加密,接收方使用私钥解密,速度慢。如 RSA。
- 混合加密:将上述加密进行组合,优点兼具,非对称加密用于保护有效时间短的对称密钥,对称加密用于加密实际数据。
两种对称加密方式:
- 流加密:一次加密一个字节数据。如 ChaCha20、XChaCha20 和 Salsa20
- 分组密码:对固定数量的数据进行加密。如 AES,一次加密 16 个字节。
Salsa20 加密
from Crypto.Cipher import Salsa20 # 加密方 plaintext = b'Hello World!' # 明文 key = b'0123456789012345' # 密钥 cipher = Salsa20.new(key=key) msg = cipher.nonce + cipher.encrypt(plaintext) # 消息=随机数+密文 # 解密方 key = b'0123456789012345' # 密钥 msg_nonce = msg[:8] ciphertext = msg[8:] cipher = Salsa20.new(key=key, nonce=msg_nonce) plaintext = cipher.decrypt(ciphertext) print(plaintext) # b'Hello World!'
AES 加密
from Crypto.Cipher import AES
# 加密方
plaintext = b'Hello World!' # 明文
key = b'0123456789012345' # 密钥
cipher = AES.new(key, AES.MODE_EAX)
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
# 解密方
key = b'0123456789012345' # 密钥
cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
plaintext = cipher.decrypt(ciphertext)
try:
cipher.verify(tag) # 验证真实性
print(plaintext)
except ValueError:
print('密钥不正确或消息被破坏')
RSA 加密
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
# 生成公私密钥
key_pair = RSA.generate(1024)
open('public.pem', 'wb').write(key_pair.public_key().export_key('PEM'))
open('private.pem', 'wb').write(key_pair.export_key('PEM'))
# 加密方
plaintext = b'Hello World!'
public_key = RSA.importKey(open('public.pem').read())
cipher = PKCS1_OAEP.new(public_key)
ciphertext = cipher.encrypt(plaintext)
# 解密方
private_key = RSA.importKey(open('private.pem').read())
cipher = PKCS1_OAEP.new(private_key)
plaintext = cipher.decrypt(ciphertext)
print(plaintext)
实际场景下,密钥长度应使用 3072 或 4096 位
用于保证完整性和不可抵赖性。
PKCS#1 RSA 签名
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
# 生成公私密钥
key_pair = RSA.generate(1024)
open('public.pem', 'wb').write(key_pair.public_key().export_key('PEM'))
open('private.pem', 'wb').write(key_pair.export_key('PEM'))
# 发送方
plaintext = b'Hello World!'
private_key = RSA.importKey(open('private.pem').read())
signer = pkcs1_15.new(private_key)
hash = SHA256.new(plaintext)
signature = signer.sign(hash)
# 接收方
plaintexts = [b'Hello World!', b'abc']
public_key = RSA.importKey(open('public.pem').read())
signer = pkcs1_15.new(public_key)
for plaintext in plaintexts:
hash = SHA256.new(plaintext)
try:
signer.verify(hash, signature)
print('合法')
except:
print('非法')
推荐阅读:什么是数字签名?
用于信息摘要。
将任意二进制字符串作为输入,并产生类似随机的固定长度的输出,即摘要或哈希值。
SHA256 计算散列值(哈希值)
from Crypto.Hash import SHA256
hash = SHA256.new()
hash.update('message'.encode())
print(hash.digest())
# b'xabSnx13xe4Yx14x98+yxf9xb7xe3xfbxa9x94xcfxd1xf3xfb"xf7x1cxeax1axfbxf0+Fx0cmx1d'
PBKDF2 进行口令保护
from Crypto.Hash import SHA512 from Crypto.Protocol.KDF import PBKDF2 from Crypto.Random import get_random_bytes password = '123456' # 口令 salt = get_random_bytes(16) # 加盐 keys = PBKDF2(password, salt, 64, count=1000000, hmac_hash_module=SHA512) key1 = keys[:32] key2 = keys[32:]
推荐阅读:PBKDF2函数,比「Hash加盐」更好的口令保护方案
- pycrypto GitHub
- PyCryptodome GitHub
- PyCryptodome Documentation
- python 3.6.5 在windows下安装PyCrypto
- windows下python3.9安装pycrypto成功总结
- Installing pycrypto on windows (popular solution not working)
- How do I install PyCrypto on Windows?
- RSA Encrypt / Decrypt
- 什么是数字签名?
- PBKDF2函数,比「Hash加盐」更好的口令保护方案



