AES (高级加密标准)是由NIST标准化的对称分组密码。它具有16字节的固定数据块大小。它的密钥可以是128、192或256位长。
AES非常快速和安全,它是对称加密的事实上的标准。
例如,可以按以下方式进行加密:
>>> from Crypto.Cipher import AES
>>>
>>> key = b'Sixteen byte key'
>>> cipher = AES.new(key, AES.MODE_EAX)
>>>
>>> nonce = cipher.nonce
>>> ciphertext, tag = cipher.encrypt_and_digest(data)
收件人可以使用相同的密钥和传入的三元组获取原始消息:(nonce, ciphertext, tag)
>>> from Crypto.Cipher import AES
>>>
>>> key = b'Sixteen byte key'
>>> cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
>>> plaintext = cipher.decrypt(ciphertext)
>>> try:
>>> cipher.verify(tag)
>>> print("The message is authentic:", plaintext)
>>> except ValueError:
>>> print("Key incorrect or message corrupted")
对称分组密码的经典操作模式
分组密码使用对称密钥来加密固定且长度非常短(数据块大小)的数据,例如AES的16个字节。为了处理任意长度的数据,必须将密码与一种操作模式结合使用。
您可以new()在相关模块下的函数下创建一个密码对象Crypto.Cipher:
第一个参数始终是加密密钥(字节字符串)
第二个参数始终是选择所需操作模式的常数
在每种算法的模块级别定义每种操作模式的常量。MODE_例如,它们的名称以开头Crypto.Cipher.AES.MODE_CBC。请注意,并非所有密码都支持所有模式。
例如:
>>> from Crypto.Cipher import AES
>>> from Crypto.Random import get_random_bytes
>>>
>>> key = get_random_bytes(16)
>>> cipher = AES.new(key, AES.MODE_CBC)
>>>
>>> # You can now use use cipher to encrypt or decrypt...
配置为经典模式的密码的状态机为:
密码块链接CBC模式为例
密文块链接,在NIST SP 800-38A,第6.2节中定义。这是一种操作模式,其中每个明文块在加密之前都会与前一个密文块进行异或。
new()模块级别的功能Crypto.Cipher为相关的基础算法实例化了一个新的CBC密码对象。在以下定义中,可能是AES:
Crypto.Cipher.<algorithm>.new(key, mode, *, iv=None)
使用<algorithm>作为基本分组密码,创建一个新的CBC对象。
参数:
密钥(字节)–加密密钥
模式–常数Crypto.Cipher.<algorithm>.MODE_CBC
iv(字节)–初始化向量。对手无法预测的一条数据。它与块大小一样长(例如AES为16字节)。如果不存在,该库将创建一个随机IV值。
返回值:
CBC密码对象
CBC密码对象的方法encrypt()(同样decrypt())期望数据的长度为块大小的倍数(例如AES为16字节)。您可能需要使用Crypto.Util.Padding将明文与右边界对齐。
CBC密码对象具有只读属性iv,其中包含 初始化向量(字节)。
示例(加密):
>>> from base64 import b64encode
>>> from Crypto.Cipher import AES
>>> from Crypto.Util.Padding import pad
>>> from Crypto.Random import get_random_bytes
>>>
>>> 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 = b64encode(cipher.iv).decode('utf-8')
>>> ct = b64encode(ct_bytes).decode('utf-8')
>>> result = json.dumps({'iv':iv, 'ciphertext':ct})
>>> print(result)
'{"iv": "bWRHdzkzVDFJbWNBY0EwSmQ1UXFuQT09", "ciphertext": "VDdxQVo3TFFCbXIzcGpYa1lJbFFZQT09"}'
示例(解密):
>>> from base64 import b64decode
>>> from Crypto.Cipher import AES
>>> from Crypto.Util.Padding import unpad
>>>
>>> # We assume that the key was securely shared beforehand
>>> try:
>>> b64 = json.loads(json_input)
>>> iv = b64decode(b64['iv'])
>>> ct = b64decode(b64['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")