1.前言

关于现代密码学算法,可以查看以下博客全面了解

CISSP考试要求里的“应用密码学”内容辅助记忆趣味串讲_晓翔仔的博客-CSDN博客

AES的细节知识,可以查阅

AES加密算法的详细介绍与实现_TimeShatter的博客-CSDN博客

AES 加密最常用的模式就是 ECB模式 和 CBC 模式,当然还有很多其它模式,他们都属于AES加密。ECB模式和CBC 模式俩者区别就是 ECB 不需要 iv偏移量,而CBC需要。

AES加解密算法的参数
参数作用及数据类型
秘钥加密的时候用秘钥,解密的时候需要同样的秘钥才能解出来; 数据类型为bytes
明文需要加密的参数; 数据类型为bytes
模式aes 加密常用的有 ECB 和 CBC 模式(这两个模式最常见,还有其他模式);数据类型为aes类内部的枚举量
iv 偏移量这个参数在 ECB 模式下不需要,在 CBC 模式下需要;数据类型为bytes

2.ECB模式

针对ECB模式的加密解密,参数中有几个限制:

  1. 秘钥必须为16字节或者16字节的倍数的字节型数据。
  2. 明文必须为16字节或者16字节的倍数的字节型数据,如果不够16字节需要进行补全

2.1 短字符串加解密

如果需要加解密的是很短的额字符串,直接使用以下代码

from Crypto.Cipher import AESpassword = b'1234567812345678' #秘钥,b就是表示为bytes类型text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型aes = AES.new(password,AES.MODE_ECB) #创建一个aes对象# AES.MODE_ECB 表示模式是ECB模式en_text = aes.encrypt(text) #加密明文print("密文:",en_text) #加密明文,bytes类型den_text = aes.decrypt(en_text) # 解密密文print("明文:",den_text)

自测输出

密文: b'WU\xe0\x0e\xa3\x87\x12\x95\\]O\xd7\xe3\xd4 )'明文: b'abcdefghijklmnhi'Process finished with exit code 0

如果是BASE64编码的密文需要解密呢?

使用如下代码

from Crypto.Cipher import AESimport base64password = b'1234567812345678'aes = AES.new(password,AES.MODE_ECB)# en_text = b"Pd04a4bt7Bcf97KEfgLGQw=="en_text = "Pd04a4bt7Bcf97KEfgLGQw==".encode() #将字符串转换成bytes数据en_text = base64.decodebytes(en_text) #将进行base64解码,返回值依然是bytesden_text = aes.decrypt(en_text)print("明文:",den_text.decode("gbk"))

因为无论是utf8gbk编码,针对英文字符编码都是一个字符对应一个字节,所以这里**encode()**函数主要作用就是转换成bytes数据,然后使用base64进行解码。

自测输出

明文: 好好学习天天向上Process finished with exit code 0

有一些AES加密,所用的秘钥,或者IV向量是通过 base64编码或者 hexstr编码后的。针对这种,首先要进行的就是进行解码,都转换回 bytes数据,再次强调,python实现 AES加密解密传递的参数都是 bytes(字节型) 数据。

hexstr,base64编码解码例子:

import base64import binasciidata = "hello".encode()data = base64.b64encode(data)print("base64编码:",data)data = base64.b64decode(data)print("base64解码:",data)data = binascii.b2a_hex(data)print("hexstr编码:",data)data = binascii.a2b_hex(data)print("hexstr解码:",data)

自测输出:

base64编码: b'aGVsbG8='base64解码: b'hello'hexstr编码: b'68656c6c6f'hexstr解码: b'hello'Process finished with exit code 0

2.2 对二进制格式的密文进行解密

如果需要解密的是一个很长的二进制文件,那么可以使用以下代码(代码用chatgpt获得的,质量不错)

密钥要转为bytes格式

输入文件: xxx.zip.enc

输出文件:xxx.zip

from Crypto.Cipher import AESimport ossecret_key = b'xxxxxx' # Convert the secret key to bytesinput_file = 'xxx.zip.enc'output_file = 'xxx.zip'# Initialize the AES cipher with the secret key and ECB modecipher = AES.new(secret_key, AES.MODE_ECB)# Get the size of the input filefile_size = os.path.getsize(input_file)# Open the input and output fileswith open(input_file, 'rb') as in_file, open(output_file, 'wb') as out_file:# Read and decrypt the input file in chunkswhile True:chunk = in_file.read(AES.block_size)if len(chunk) == 0:breakout_chunk = cipher.decrypt(chunk)out_file.write(out_chunk)# Remove any padding from the output fileout_file.truncate(file_size - AES.block_size + len(out_chunk))

自测结果(考虑填充,AES的输出和输入长度一样)

3.CBC 模式

CBC模式与ECB模式的区别:AES.new() 解密和加密重新生成了aes对象,加密和解密不能调用同一个aes对象,否则会报错。为了防止这类错误,写代码无论是什么模式都重新生成AES对象。

代码

from Crypto.Cipher import AESpassword = b'1234567812345678' #秘钥,b就是表示为bytes类型iv = b'1234567812345678' # iv偏移量,bytes类型text = b'abcdefghijklmnhi' #需要加密的内容,bytes类型aes = AES.new(password,AES.MODE_CBC,iv) #创建一个aes对象# AES.MODE_CBC 表示模式是CBC模式en_text = aes.encrypt(text) print("密文:",en_text) #加密明文,bytes类型aes = AES.new(password,AES.MODE_CBC,iv) #CBC模式下解密需要重新创建一个aes对象den_text = aes.decrypt(en_text)print("明文:",den_text)

自测结果

密文: b'\x93\x8bN!\xe7~>\xb0M\xba\x91\xab74;0'明文: b'abcdefghijklmnhi'Process finished with exit code 0

4. 填充模式

前面使用秘钥,还有明文,包括IV向量,都是固定16字节,也就是数据块对齐了。而填充模式就是为了解决数据块不对齐的问题,使用什么字符进行填充就对应着不同的填充模式。

填充模式
模式意义
ZeroPadding用b’\x00’进行填充,这里的0可不是字符串0,而是字节型数据的b’\x00’
PKCS7Padding当需要N个数据才能对齐时,填充字节型数据为N、并且填充N个
PKCS5Padding与PKCS7Padding相似
no padding当为16字节数据时候,可以不进行填充,而不够16字节数据时同ZeroPadding一样

如果你写的python代码需要考虑填充模式,可以参考这一篇博客的代码。

python实现AES加密解密_python aes_Hello_wshuo的博客-CSDN博客

5.最后

AES是常见非对称加密算法。