PyCryptodome QuickStart


文档: https://www.pycryptodome.org/,本文代码大多参考Examples示例章节。

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。

1. 文档解读

重点看API部分,了解一下库的目录。

PackageDescription
Crypto.CipherModules for protecting confidentiality that is, for encrypting and decrypting data (example: AES).
Crypto.SignatureModules for assuring authenticity, that is, for creating and verifying digital signatures of messages (example: PKCS#1 v1.5).
Crypto.HashModules for creating cryptographic digests (example: SHA-256).
Crypto.PublicKeyModules for generating, exporting or importing public keys (example: RSA or ECC).
Crypto.ProtocolModules for faciliting secure communications between parties, in most cases by leveraging cryptograpic primitives from other modules (example: Shamir’s Secret Sharing scheme).
Crypto.IOModules for dealing with encodings commonly used for cryptographic data (example: PEM).
Crypto.RandomModules for generating random data.
Crypto.UtilGeneral purpose routines (example: XOR for byte strings).

2. Demo

对称加密

基于官方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"))

加解密

官方PKCS1_OAEP示例

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)
  • PKCS#1 PSS (RSA)
  • Edwards-curve Digital Signature Algorithm (EdDSA)
  • Digital Signature Algorithm (DSA and ECDSA)

这里试一下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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值