一、安装pip install pycryptodome二、包模块介绍包名描述Crypto.Cipher数据的加密、解密模块,例如 AESCrypto.Signature数据的签名、验签Crypto.Hash消息摘要Crypto.PublicKey用于公钥的生成、导出和导入Crypto.Random用于生成随机数据Crypto.Util工具类,例如数据填充1、Crypto.PublicKey用于公钥、私钥证书的生成以及证书格式转换(字符串)pycryptodome支持的Key类型:• RSA keys• DSA keys• Elliptic Curve keys在导入公钥、私钥时,需要进行格式填充RSA私钥文件结构:-----BEGIN RSA PRIVATE KEY-----
私钥正文
-----END RSA PRIVATE KEY-----RSA公钥文件:-----BEGIN PUBLIC KEY-----
公钥正文
-----END PUBLIC KEY-----# 生成私钥、公钥
bits指定生成的私钥文件大小
passphrase指定私钥文件加密密码
key = RSA.generate(bits=2048)
with open('private_key.pem', 'wb') as fp:
fp.write(key.export_key(format='PEM', passphrase='123456'))
with open('public_key.pem', 'wb') as fp:
fp.write(key.publickey().export_key())
导入公钥、私钥文件
private_key_start = '-----BEGIN RSA PRIVATE KEY-----'
private_key_end = '-----END RSA PRIVATE KEY-----'
public_key_start = r'-----BEGIN PUBLIC KEY-----'
public_key_end = r'-----END PUBLIC KEY-----'
with open('private_key.pem', 'rb') as fp:
pk = fp.read().decode('utf-8')
if not pk.startswith(private_key_start):
pk = private_key_start + pk
if not pk.endswith(private_key_end):
pk += private_key_end
private_key = RSA.import_key(pk, passphrase='123456')2、Crypto.CipherCipher模块用于数据的加密和解密• 对称算法:双方使用相同的密钥进行数据的加密和解密。对称加密的速度通常比较快,代表有 AES,DES3• 非对称算法发送方和接收方使用不同的密钥。发送方使用公钥(非机密)加密,而接收方使用私钥(机密)解密。非对称密钥通常很慢。代表有 PKCS#1 OAEP (RSA)pycryptodome支持的算法:• Single DES and Triple DES (block ciphers)• RC2 (block cipher)• ARC4 (stream cipher)• Blowfish (block cipher)• CAST-128 (block cipher)• PKCS#1 v1.5 encryption (RSA) (asymmetric cipher)AES(Advanced Encryption Standard)AES具有16字节的固定数据块大小。它的密钥可以是128、192或256位(bit)长。• 使用ECB(Electronic Code Book)进行数据的加密解密: ECB将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。所以在加密的时候需要对明文数据进行填充保证数据的长度是密码长度的倍数。# 数据加密
plain_text = b'hello'
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_ECB)
ct_bytes = cipher.encrypt(pad(plain_text, AES.block_size))
enc_data = base64.b64encode(ct_bytes).decode('utf-8')
数据解密
enc_data = '/zgUiJHvUyu1h+wr9evHCA=='
key = 'dhcvKhdF3kwoXUjGTmK3Ww=='
cipher = AES.new(base64.b64decode(key), AES.MODE_ECB)
pad_plain_data = cipher.decrypt(base64.b64decode(enc_data))
plain_data = unpad(pad_plain_data, AES.block_size)
print(plain_data.decode('utf-8'))• CBC模式的加密首先也是将明文分成固定长度的块,然后将前面一个加密块输出的密文与下一个要加密的明文块进行异或操作,将计算结果再用密钥进行加密得到密文。第一明文块加密的时候,因为前面没有加密的密文,所以需要一个初始化向量。# 数据加密
plain_text = b'hello'
key = get_random_bytes(16)
初始偏移量可以不指定,如果不指定非随机生成
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
ct_bytes = cipher.encrypt(pad(plain_text, AES.block_size))
enc_data = base64.b64encode(ct_bytes).decode('utf-8')
print('加密密文==', enc_data)
数据解密
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
pad_plain_data = cipher.decrypt(base64.b64decode(enc_data))
plain_text = unpad(pad_plain_data, AES.block_size).decode('utf-8')
print('解密后明文==', plain_text)RSARSA加解密一般是公钥加密,私钥解密;PyCryptodome当前建议使用 PKCS1_OAEP算法;如果加解密双方为 Python与 Java且 Java端采用 RSA/ECB/PKCS1Padding时,Python端需要采用 PKCS1_v1_5加解密模块为:Crypto.Cipher模块import base64
from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5
from Crypto.PublicKey import RSA
数据加密--公钥
data = "I met aliens in UFO. Here is the map.".encode("utf-8")
with open('public_key.pem', mode='rb') as fp:
# 如果是读取字符串公钥需要补齐字符串格式
public_key = RSA.import_key(fp.read())
cipher_rsa = PKCS1_v1_5.new(public_key)
#cipher_rsa = PKCS1_OAEP.new(public_key)
enc_data = cipher_rsa.encrypt(data)
print(base64.b64encode(enc_data).decode('utf-8'))
数据解密--私钥
enc_data = 'rDrJC9aaAmL5szCKzPy1peJ/Yx8noKuBEDFsUGSjDQgxRId3jgG9fAVuXpJnqRtHL+RXncOLuqRtKVowyt5H3Ag/KZm+7RJDeY7nT3AvgUiy0xfQgZChOW63BDoIMFIDZqXv5yPwqoMDT2Tz3Yj7FWYb5/0zbbFbJqwyA3knY2vUOFOp/YyqpZ7gzzyKjgAgi8pWgEDs2bXMirGIWA1McHFVdDfHF7Xi2s2Ob2oHylW7rJT9SXfQh0CPvWRxTstv6e8GWRQo4qYK/qGxqGQfLexSw2/o10DIAsYOxN9xubVKPLA+jXQchSH7Z/Js2g9t3WSI8027JXg//HTB5AO74A=='
with open('private_key.pem', mode='rb') as fp:
# 如果是读取字符串公钥需要补齐字符串格式
pk = RSA.import_key(fp.read(), passphrase='123456')
cipher = PKCS1_v1_5.new(pk)
#sentinel:当发生错误时返回对象
plain_data_byte = cipher.decrypt(base64.b64decode(enc_data), sentinel='no')
# PKCS1_OAEP解密
#cipher = PKCS1_OAEP.new(pk)
#plain_data_byte = cipher.decrypt(base64.b64decode(enc_data))
print(plain_data_byte.decode('utf-8'))
3、Crypto.SignatureRSA使用私钥签名,公钥验签;签名验签在 Crypto.Signature模块包提供pycryptodome支持的算法:• PKCS#1 v1.5 (RSA)• PKCS#1 PSS (RSA)• Digital Signature Algorithm (DSA and ECDSA)import base64
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
plain_data = "Hello, World!!"
with open('private_key.pem', mode='rb') as fp:
# 如果是读取字符串公钥需要补齐字符串格式
private_key = RSA.import_key(fp.read(), passphrase='123456')
hash_data = SHA256.new(plain_data.encode('utf-8'))
sign_data = PKCS1_v1_5.new(private_key).sign(hash_data)
print(base64.b64encode(sign_data).decode('utf-8'))
验签
plain_data = "Hello, World!!"
sign_data = 'itVttV7vTzB8OoglNtuPn2PgpRzpZ3ILOnLWQDAqiOuQig9Whs0a6ht5P3oc1baUZ6PfVksSNzuPd8sNaR9eQeKkaSiuiJP11BJ8cugPuSyn'
with open('public_key.pem', mode='rb') as fp:
hash_data = SHA256.new(plain_data.encode('utf-8'))
public_key = RSA.import_key(fp.read())
try:
PKCS1_v1_5.new(public_key).verify(hash_data, signature=base64.b64decode(sign_data))
except Exception as e:
print('验签失败', e)4、Crypto.HashHash模块主要用于消息摘要pycryptodome支持的算法:• SHA-2 family (FIPS 180-4)• SHA-224• SHA-256• SHA-384• SHA-512, SHA-512/224, SHA-512/256• SHA-3 family (FIPS 202)• SHA3-224• SHA3-256• SHA3-384• SHA3-512• TupleHash128• TupleHash256• BLAKE2• BLAKE2s• BLAKE2b示例:def cal_hash256(data: str) -> str:
"""
sha256计算
:param data: 需要计算hash值的文本字符串
:return 十六进制hash值
"""
return SHA256.new(data.encode('utf-8')).hexdigest()
评论0
暂时没有评论