Github: https://github.com/Legrandin/pycryptodome
安装后,py源码位于python目录\Lib\site-packages\Crypto
。但想学习算法实现的话还是需要去github src目录查看c源码,本地只有编译好的pyd,并且在py里用load\_pycryptodome\_raw\_lib
加载。
Pycrypto、crypto这两个py库其实是同一个东西,其中crypto在python上面的名字是pycrypto,已经停止更新了;pycryptodome库则兼容PyCrypto库,用它就完了。其实查看\Lib\site-packages\pycryptodome-3.14.1.dist-info\top_level.txt
,所用的包名仍然是Crypto。
重点看API部分,了解一下库的目录。
Package | Description |
---|---|
Crypto.Cipher | Modules for protecting confidentiality that is, for encrypting and decrypting data (example: AES). |
Crypto.Signature | Modules for assuring authenticity, that is, for creating and verifying digital signatures of messages (example: PKCS#1 v1.5). |
Crypto.Hash | Modules for creating cryptographic digests (example: SHA-256). |
Crypto.PublicKey | Modules for generating, exporting or importing public keys (example: RSA or ECC). |
Crypto.Protocol | Modules for faciliting secure communications between parties, in most cases by leveraging cryptograpic primitives from other modules (example: Shamir’s Secret Sharing scheme). |
Crypto.IO | Modules for dealing with encodings commonly used for cryptographic data (example: PEM). |
Crypto.Random | Modules for generating random data. |
Crypto.Util | General purpose routines (example: XOR for byte strings). |
基于官方AES-CBC示例修改的demo,官方示例使用了base64编码,这里去掉:
import json
# from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
from binascii import b2a_hex, a2b_hex
# encrypt
data = b"secret"
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(data, AES.block_size))
iv = b2a_hex(cipher.iv).decode('utf-8')
ct = b2a_hex(ct_bytes).decode('utf-8')
jsonResult = json.dumps({'iv':iv, 'ciphertext':ct})
print(jsonResult)
# decrypt
try:
json2Dec = json.loads(jsonResult)
iv = a2b_hex(json2Dec['iv'])
ct = a2b_hex(json2Dec['ciphertext'])
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
print("The message was: ", pt)
except (ValueError, KeyError):
print("Incorrect decryption")
https://www.pycryptodome.org/src/public_key/rsa
from Crypto.PublicKey import RSA
from Crypto import Random
random_generator = Random.new().read
rsa = RSA.generate(1024, random_generator)
with open('pri.pem','wb') as f:
f.write(rsa.export_key('PEM'))
with open('pub.pem','wb') as f:
f.write(rsa.publickey().exportKey("PEM"))
AES加密数据,再用RSA公钥加密对称密钥。
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP
data = "I met aliens in UFO. Here is the map.".encode("utf-8")
with open("encrypted_data.bin", "wb") as file_out:
recipient_key = RSA.import_key(open("pub.pem").read())
session_key = get_random_bytes(16)
# Encrypt the session key with the public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
enc_session_key = cipher_rsa.encrypt(session_key)
# Encrypt the data with the AES session key
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
[ file_out.write(x) for x in (enc_session_key, cipher_aes.nonce, tag, ciphertext) ]
接收者用私钥解密对称密钥,再解密数据。
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES, PKCS1_OAEP
with open("encrypted_data.bin", "rb") as file_in:
private_key = RSA.import_key(open("pri.pem").read())
enc_session_key, nonce, tag, ciphertext = \
[ file_in.read(x) for x in (private_key.size_in_bytes(), 16, 16, -1) ]
# Decrypt the session key with the private RSA key
cipher_rsa = PKCS1_OAEP.new(private_key)
session_key = cipher_rsa.decrypt(enc_session_key)
# Decrypt the data with the AES session key
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag)
print(data.decode("utf-8"))
复用RSA示例的密钥对即可。
Crypto.Signature package目录下有以下示例:
这里试一下PKCS#1 v1.5 (RSA)
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
message = b'To be signed'
signature = ""
with open('pri.pem') as f:
key = RSA.import_key(f.read())
h = SHA256.new(message)
signature = pkcs1_15.new(key).sign(h)
with open('pub.pem') as f:
key = RSA.import_key(f.read())
h = SHA256.new(message)
try:
pkcs1_15.new(key).verify(h, signature)
print("The signature is valid.")
except (ValueError, TypeError):
print("The signature is not valid.")python