Python加解密库——pycrypto(pycryptodome)

简介

pycrypto 实现了哈希函数(如 SHA256)和加密算法(如 AES、DES、RSA)。

注意!pycrypto 已很久未维护,有安全漏洞。

建议使用 pycryptodome 替代 pycrypto,它是后者的一个分支,一直在维护。




安装

以下方法均可,推荐方法二



方法一:Visual Studio

Windows 需要安装 Visual Studio 2015 或以上版本,本人是 Visual Studio 2017,安装方法大同小异。

cd C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build
vcvars64.bat
set CL=-FI"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\include\stdint.h"
pip install pycrypto

    
    
  • 1
  • 2
  • 3
  • 4



方法二:pycryptodome(推荐)

也可以用 pycryptodome 替代 pycrypto,它是后者的一个分支,一直在维护。

pip uninstall pycrypto
pip install pycryptodome

    
    
  • 1
  • 2




初试

SHA256 计算散列值(哈希值)

from Crypto.Hash import SHA256

hash = SHA256.new()
hash.update(‘message’.encode())
print(hash.digest())
# b’\xabS\n\x13\xe4Y\x14\x98+y\xf9\xb7\xe3\xfb\xa9\x94\xcf\xd1\xf3\xfb"\xf7\x1c\xea\x1a\xfb\xf0+F\x0cm\x1d’

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6




公钥

公钥系统下,发送方和接收方使用不同密钥——公钥或私钥。

场景发送方接收方
加解密公钥私钥
数字签名私钥公钥
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’)) # 导出私钥

  • 1
  • 2
  • 3
  • 4
  • 5




加解密

三种加密方式:

  1. 对称加密:参与方使用相同密钥进行加解密,速度快,适合处理大量数据。如 AES
  2. 非对称加密:发送方使用公钥加密,接收方使用私钥解密,速度慢。如 RSA
  3. 混合加密:将上述加密进行组合,优点兼具,非对称加密用于保护有效时间短的对称密钥,对称加密用于加密实际数据。



对称加密

两种对称加密方式:

  1. 流加密:一次加密一个字节数据。如 ChaCha20、XChaCha20Salsa20
  2. 分组密码:对固定数量的数据进行加密。如 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!'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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(‘密钥不正确或消息被破坏’)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18



非对称加密

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)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

实际场景下,密钥长度应使用 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(‘非法’)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

推荐阅读:什么是数字签名?




哈希函数

用于信息摘要。

将任意二进制字符串作为输入,并产生类似随机的固定长度的输出,即摘要或哈希值。

SHA256 计算散列值(哈希值)

from Crypto.Hash import SHA256

hash = SHA256.new()
hash.update(‘message’.encode())
print(hash.digest())
# b’\xabS\n\x13\xe4Y\x14\x98+y\xf9\xb7\xe3\xfb\xa9\x94\xcf\xd1\xf3\xfb"\xf7\x1c\xea\x1a\xfb\xf0+F\x0cm\x1d’

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6




安全通信

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:]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

推荐阅读:PBKDF2函数,比「Hash加盐」更好的口令保护方案




加密IO




封装




遇到的坑




参考文献

  1. pycrypto GitHub
  2. PyCryptodome GitHub
  3. PyCryptodome Documentation
  4. python 3.6.5 在windows下安装PyCrypto
  5. windows下python3.9安装pycrypto成功总结
  6. Installing pycrypto on windows (popular solution not working)
  7. How do I install PyCrypto on Windows?
  8. RSA Encrypt / Decrypt
  9. 什么是数字签名?
  10. PBKDF2函数,比「Hash加盐」更好的口令保护方案
文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树首页概览 399874 人正在系统学习中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值