一、前言
加解密文件是日常安全活动中非常常见的行为,对一个文件做加密通常是为了保护这个文件不被非法获取。
加密算法分为对称加密和非对称加密两种,对称加密算法的优点是加解密速度快,可以用来处理大量的文本数据,缺点是需要保护密钥的安全,最常用的算法是AES;非对称加密算法的优点是加解密使用不同密钥,这样就不存在密钥传输的安全问题,缺点是加解密速度慢,可以用来处理少量文本数据,最常用的算法是RSA。
因此,一个常见的解决方案是使用AES加密文本数据,再使用RSA加密AES的密钥,最后再将结果打包,这样既实现了加解密速度的要求,又实现了密钥传输安全的要求。
二、代码实例
代码中已有明确注释,因此不再做单独的逻辑解释。
#!/usr/bin/python
#-*- coding:utf8 -*-
from Cryptodome.Cipher import AES, PKCS1_OAEP
from Cryptodome.PublicKey import RSA
from Cryptodome.Random import get_random_bytes
from io import BytesIO
import base64
import zlib
# RSA密钥生成函数
def generate():
new_key = RSA.generate(2048)
private_key = new_key.exportKey()
public_key = new_key.publickey().exportKey()
# 将私钥写入key.pri文件中
with open('key.pri', 'wb') as f:
f.write(private_key)
f.close()
# 将公钥写入key.pub文件中
with open('key.pub', 'wb') as f:
f.write(public_key)
f.close()
# 加载私钥或公钥,传入一个密钥类型(pri/pub)作为参数
def get_rsa_cipher(keytype):
# 读取文件
with open(f'key.{keytype}') as f:
key = f.read()
f.close()
rsakey = RSA.importKey(key)
# 返回密码对象和RSA密钥的长度
return (PKCS1_OAEP.new(rsakey), rsakey.size_in_bytes())
# 加密数据函数
def encrypt(plaintext):
# 将明文数据以bytes类型传入并压缩
compressed_text = zlib.compress(plaintext)
# 随机生成一个密钥作为AES使用的密钥
session_key = get_random_bytes(16)
cipher_aes = AES.new(session_key, AES.MODE_EAX)
# 使用AES对压缩过的明文进行加密
ciphertext, tag = cipher_aes.encrypt_and_digest(compressed_text)
# 使用RSA公钥将AES密钥进行加密
cipher_rsa, _ = get_rsa_cipher('pub')
encrypted_session_key = cipher_rsa.encrypt(session_key)
# 将解密所需的全部信息打包在msg_payload中(RSA公钥加密后的值、AES密钥、标签、密文)
msg_payload = encrypted_session_key + cipher_aes.nonce + tag + ciphertext
# 再使用base64编码,之后保存成encrypted的字符串返回
encrypted = base64.encodebytes(msg_payload)
return (encrypted)
# 解密数据函数
def decrypt(encrypted):
# base64解码之前编码的数据
encrypted_bytes = BytesIO(base64.decodebytes(encrypted))
# 读取RSA私钥
cipher_rsa, keysize_in_bytes = get_rsa_cipher('pri')
# 读取RSA公钥加密后的值
encrypted_session_key = encrypted_bytes.read(keysize_in_bytes)
# 读取AES密钥
nonce = encrypted_bytes.read(16)
# 读物标签信息
tag = encrypted_bytes.read(16)
# 读取密文
ciphertext = encrypted_bytes.read()
# 使用RSA私钥解密AES密钥
session_key = cipher_rsa.decrypt(encrypted_session_key)
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
# 使用AES密钥解密正文
decrypted = cipher_aes.decrypt_and_verify(ciphertext, tag)
# 解压为明文消息并返回
plaintext = zlib.decompress(decrypted)
return plaintext
if __name__ == '__main__':
# 调用RSA密钥生成函数
generate()
# 以下是加解密这段文字的说明
plaintext = b'how old are you'
print(f'the plain text is : {plaintext}')
encrypted_text = encrypt(plaintext)
print(f'the encrypted plain text is :\n {encrypted_text}')
print(f'the decrypted plain text is :\n {decrypt(encrypted_text)}')
三、运行测试
直接执行代码即可:
python xxx.py