一、引言
高级加密标准(Advanced Encryption Standard, AES)是一种广泛使用的对称密钥加密算法,由美国国家标准与技术研究院(NIST)于2001年发布。AES以其高效、安全和灵活性而闻名,被广泛应用于保护敏感数据的机密性。本文将深入探讨Python中AES加密的实现,包括其原理、关键参数、以及通过代码示例进行实践。
二、AES加密基础
1、对称密钥加密
AES是一种对称密钥加密算法,意味着加密和解密使用相同的密钥。这种加密方式在效率上优于非对称加密(如RSA),但密钥分发和管理成为挑战。
2、工作模式
AES支持多种操作模式,如ECB(电子密码本模式)、CBC(密码块链接模式)、CFB(密码反馈模式)、OFB(输出反馈模式)和CTR(计数器模式)等。每种模式都有其特点和适用场景。
3、密钥长度
AES支持三种长度的密钥:128位、192位和256位。密钥长度越长,加密强度越高,但加密和解密过程也相应更慢。
三、Python中的AES加密
在Python中,可以使用pycryptodome
库来实现AES加密。pycryptodome
是PyCrypto
的一个分支,提供了更全面的加密算法支持。
1、安装pycryptodome
首先,需要安装pycryptodome
库。可以使用pip进行安装:
pip install pycryptodome
2、案例一:使用CBC模式和PKCS#7填充
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64
# 生成随机的密钥(必须是16、24或32字节)
key = get_random_bytes(16)
# 生成随机的初始化向量(IV),AES块大小为16字节
iv = get_random_bytes(AES.block_size)
# 明文数据
plain_text = "Hello, AES Encryption!".encode('utf-8')
# 使用PKCS#7填充明文数据到AES块大小的倍数
padded_data = pad(plain_text, AES.block_size)
# 创建AES加密器,使用CBC模式和之前生成的密钥及IV
cipher = AES.new(key, AES.MODE_CBC, iv)
# 加密填充后的数据
encrypted_data = cipher.encrypt(padded_data)
# 将IV和密文拼接,然后Base64编码以便于存储或传输
cipher_text_str = base64.b64encode(iv + encrypted_data).decode('utf-8')
print("加密后的数据:", cipher_text_str)
# 解密过程
# 创建相同的AES解密器
decrypt_cipher = AES.new(key, AES.MODE_CBC, iv)
# 解密数据
decrypted_padded_data = decrypt_cipher.decrypt(encrypted_data)
# 去除填充
decrypted_text = unpad(decrypted_padded_data, AES.block_size)
print("解密后的数据:", decrypted_text.decode('utf-8'))
输出结果:
加密后的数据: UYQTIYCyXTclVckVAmQH3VjWjfZLhblZGNTkNe2CSIrxBwcbXRutES9I+Elid4Hj
解密后的数据: Hello, AES Encryption!
3、案例二:使用ECB模式和自定义填充
注意:ECB模式不推荐使用于加密长数据或敏感数据,因为它不使用IV且相同的明文块会产生相同的密文块。
from Crypto.Cipher import AES
import base64
from Crypto.Random import get_random_bytes
# 生成随机的密钥(必须是16、24或32字节)
key = get_random_bytes(16)
# 明文数据
plain_text = "ECB模式进行AES加密".encode('utf-8')
# 自定义填充函数(这里使用简单的'X'字符填充)
def custom_pad(s, block_size=AES.block_size):
pad_len = block_size - len(s) % block_size
return s + b'h' * pad_len
# 加密
cipher = AES.new(key, AES.MODE_ECB)
padded_data = custom_pad(plain_text)
encrypted_data = cipher.encrypt(padded_data)
# Base64编码
cipher_text_str = base64.b64encode(encrypted_data).decode('utf-8')
print("加密后输出:", cipher_text_str)
# 解密(同样需要自定义填充)
decrypted_data = cipher.decrypt(encrypted_data)
# 去除填充(注意:这里需要知道填充的规则)
decrypted_text = decrypted_data.rstrip(b'h').decode('utf-8')
print("解密后输出:", decrypted_text)
输出结果:
加密后输出: ZYUTsU3bZdWF7pq4pFA1J/mbR4DRLMHUMcoOYhODcNM=
解密后输出: ECB模式进行AES加密
3、案例三:使用GCM模式
GCM(Galois/Counter Mode)是一种结合了CTR模式和GHASH(Galois Hash)的认证加密模式,它提供了数据的机密性和完整性保护。
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad
import base64
# 生成随机的密钥(对于AES-GCM,推荐使用128位(16字节)或256位(32字节)的密钥)
key = get_random_bytes(32) # 生成一个32字节(256位)的密钥
# 生成随机的nonce(GCM中的IV被称为nonce,不需要保密,但必须确保唯一)
nonce = get_random_bytes(16) # 生成一个16字节的nonce
# 明文数据
plain_text = "AES-GCM加密!".encode('utf-8')
# AES-GCM不需要传统的填充,但我们可以使用pad函数以确保与可能的其他加密模式兼容(尽管在这里是多余的)
# 注意:对于GCM,实际上应该直接加密原始明文,不需要填充
# 这里为了展示pad函数的使用(虽然在这个上下文中是多余的),我们还是使用它
padded_data = pad(plain_text, AES.block_size) # 但GCM模式下这步是多余的
# 由于GCM模式下不需要填充,我们直接加密原始明文
# 创建AES-GCM加密器
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
# 加密数据并获取密文和认证标签
ciphertext, tag = cipher.encrypt_and_digest(plain_text) # 加密明文并获取密文和GCM认证标签
# 通常,你会将nonce、密文和标签一起发送给接收者(或存储它们以供以后使用)
# 这里,为了简化,我们将它们Base64编码并打印出来
cipher_text_with_nonce_and_tag = base64.b64encode(nonce + ciphertext + tag).decode('utf-8')
print("加密后输出:", cipher_text_with_nonce_and_tag)
# 解密过程
# 接收方需要拥有相同的密钥和nonce来解密和验证密文
decrypt_cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
# 解密数据并验证认证标签
try:
decrypted_text = decrypt_cipher.decrypt_and_verify(ciphertext, tag)
print("解密后输出:", decrypted_text.decode('utf-8'))
except ValueError:
# 如果认证标签不匹配,decrypt_and_verify将抛出一个ValueError
print("身份验证失败!.")
# 注意:在实际应用中,nonce(IV)和密钥都应该安全地存储和传输
# 密钥应该保密,而nonce(IV)应该对每个加密操作都是唯一的,但不需要保密
# 认证标签(tag)是验证密文完整性和真实性的关键部分,必须随密文一起发送或存储
输出结果:
加密后输出: FwPwETBk5pxUyKPQ8iOQReBHUS2inee//aaKDlumHoj32olJRqMLTWaaWImJwQ==
解密后输出: AES-GCM加密!