对称加密(AES)
对称加密(AES)
AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个。
常见的对称加密:AES,DES,3DES.我们这里讨论AES。
安装:
pip install pycryptodome
AES
加密最常用的模式就是CBC
模式和ECB
模式,当然还有很多其它模式,他们都属于AES加密。ECB
模式和CBC
模式俩者区别就是ECB
不需要iv
偏移量,而CBC
需要。
长度
16:*AES-128*
24: *AES-192*
32:*AES-256*
MODE加密模式.
常见的ECB,CBC
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
"""
ECB 以 16:*AES-128* 算法为例:我们有一个要加密的,就会按照16分割,然后分别加密,再把所有的加密的组合起来
"""
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解
难度。
"""
CBC:也是分块,第一块加密之后,第一块加密数据与第二块明文做异或
"""
CBC加密流程
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
# (1) 确认 key 和 iv 必须是16位/24位/32位
key = "0123456789123456".encode()
iv = "qazwsxedcrfvtgby".encode()
# (2)创建AES对象
aes = AES.new(key, AES.MODE_CBC, iv) # key, 模式, iv
# (3)对数据做加密,数据一定要是16/24/32的倍数
data = "xiaoxiaoxiao".encode() # 数据不实16的倍数,下面使用pad函数补齐
pad_data = pad(data, 16) # 不是16的倍数,需要补齐,这里有个规律就是缺几位就补几【现在是缺4位补的就是4】
print(pad_data) # b'xiaoxiaoxiao\x04\x04\x04\x04'
encrypt_date = aes.encrypt(pad_data)
print(encrypt_date) # b'\x91\x8f\xcb\xcfM\xa8\xbf\xc2\x87\x8b\x1c\x01Y\xb5\x17X'
# (4)base64编码,原因是encrypt_date会有很多特殊的符号
base64_encrypt_date = base64.b64encode(encrypt_date).decode()
print(base64_encrypt_date) # kY/Lz02ov8KHixwBWbUXWA==
如果加密的是一个字典,在解密的时候就有一个“坑”
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
# (1) 确认 key 和 iv 必须是16位/24位/32位
key = "0123456789123456".encode()
iv = "qazwsxedcrfvtgby".encode()
# (2)创建AES对象
aes = AES.new(key, AES.MODE_CBC, iv) # key 模式 iv
# (3)对数据做加密,数据一定要是16/24/32的倍数
# data = "xiaoxiaoxiao".encode() # 数据不实16的倍数,下面使用pad函数补齐
data = "{'a':1}".encode()
pad_data = pad(data, 16) # 不是16的倍数,需要补齐,这里有个规律就是缺几位就补几【现在是缺4位补的就是4】
print(pad_data) # b"{'a':1}\t\t\t\t\t\t\t\t\t"
encrypt_date = aes.encrypt(pad_data)
print(encrypt_date) # b"\xaftD7'\x9e\x89(A\x80\x0e$\x19\x98\x80{"
# (4)base64编码,原因是encrypt_date会有很多特殊的符号
base64_encrypt_date = base64.b64encode(encrypt_date).decode()
print(base64_encrypt_date) # r3RENyeeiShBgA4kGZiAew==
解密
以上面的字典的加密为例,来解密
# 此段代码是个半成品
import base64
from Crypto.Cipher import AES
base64_encrypt_date = "r3RENyeeiShBgA4kGZiAew=="
# (1)base64解码
encrypt_date = base64.b64decode(base64_encrypt_date)
print(encrypt_date) # b"\xaftD7'\x9e\x89(A\x80\x0e$\x19\x98\x80{"
# (2)解密
# 2.1 确认好解密的参数
key = "0123456789123456".encode()
iv = "qazwsxedcrfvtgby".encode()
# 2.2 创建AES对象
aes = AES.new(key, AES.MODE_CBC, iv) # key 模式 iv
# 2.3 对数据进行解密
data = aes.decrypt(encrypt_date)
print(data) # b"{'a':1}\t\t\t\t\t\t\t\t\t"
此时我们的数据有了\t,,,因为我们在数据加密的是不够位数,就补齐的原因,所有要去掉【见下面代码】
完整版
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
base64_encrypt_date = "r3RENyeeiShBgA4kGZiAew=="
# (1)base64解码
encrypt_date = base64.b64decode(base64_encrypt_date)
print(encrypt_date) # b'\x91\x8f\xcb\xcfM\xa8\xbf\xc2\x87\x8b\x1c\x01Y\xb5\x17X'
# (2)解密
# 2.1 确认好解密的参数
key = "0123456789123456".encode()
iv = "qazwsxedcrfvtgby".encode()
# 2.2 创建AES对象
aes = AES.new(key, AES.MODE_CBC, iv) # key 模式 iv
# 2.3 对数据进行解密
data = aes.decrypt(encrypt_date)
# 2.4 去掉填充
# data = unpad(data, AES.block_size) # AES.block_size 默认就是16
print(data, type(data)) # b"{'a':1}"