Python AES加解密

Python AES加解密

AES加密方式有五种:ECB, CBC, CTR, CFB, OFB

从安全性角度推荐CBC加密方法,本文介绍了CBC,ECB两种加密方法的python实现

python 在 Windows下使用AES时要安装的是pycryptodome 模块 pip install pycryptodome

python 在 Linux下使用AES时要安装的是pycrypto模块 pip install pycrypto

CBC加密需要一个十六位的key(密钥)和一个十六位iv(偏移量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import base64
from Crypto.Cipher import AES


# AES加密解密模块
class AESUtil:

# 每块16的bytes长度, 即是PKCS5 这种方式, 和秘钥长度一致
__BLOCK_SIZE_16 = AES.block_size

@staticmethod
def add_to_16(text): # 转bytes 并 补齐为16的倍数
b_text = text.encode("utf-8")
x = AESUtil.__BLOCK_SIZE_16 - (len(b_text) % AESUtil.__BLOCK_SIZE_16)
if x != 0:
text = text + chr(x) * x
return text.encode('utf-8')

@staticmethod
def encrypt(text: str, key: bytes, mode: str="ECB", iv: bytes=None):
"""
AES 加密方法
:param text: 要加密的字符串
:param key: 密钥
:param mode: 模式,CBC or ECB
:param iv: 偏移量(ECB模式没有偏移量)
:return: 返回加密的数据
"""
aes_mode = AES.MODE_CBC if mode == "CBC" else AES.MODE_ECB
if iv and mode == "CBC":
cipher = AES.new(key, aes_mode, iv)
else:
cipher = AES.new(key, aes_mode)
text = AESUtil.add_to_16(text)
msg = cipher.encrypt(text)
msg = base64.b64encode(msg)
return msg

@staticmethod
def decrypt(en_str: str, key: bytes, mode: str="ECB", iv: bytes=None):
"""
AES 解密方法
:param en_str: 要解密的字符串
:param key: 密钥
:param mode: 模式,CBC or ECB
:param iv: 偏移量(ECB模式没有偏移量)
:return:
"""
aes_mode = AES.MODE_CBC if mode == "CBC" else AES.MODE_ECB
if iv and mode == "CBC":
cipher = AES.new(key, aes_mode, iv)
else:
cipher = AES.new(key, aes_mode)
decrypt_bytes = base64.b64decode(en_str)
msg = cipher.decrypt(decrypt_bytes)
return msg.decode("utf-8")

# 测试
if __name__ == "__main__":
key = b"1234567812345678"
iv = b"1234567812345678"
res = AESUtil.encrypt("123456", key, "CBC", iv)
print(res) # 2eDiseYiSX62qk/WS/ZDmg==
print(AESUtil.decrypt(res, key, "CBC", iv)) # 123456

key = b"1234567812345678"
iv = b"1234567812345678"
res = AESUtil.encrypt("123456", key)
print(res) # mdSm0RmB+xAKrTah3DG31A==
print(AESUtil.decrypt(res, key)) # 123456

注:有的时候使用AES解密后,最后多出一些莫名其妙的字符,当我们使用json.loads时会出错,可以使用如下方式去除末尾多余字符:

1
2
3
4
msg = cipher.decrypt(decrypt_bytes)
msg = msg.decode('utf-8')
unpadding = ord(msg[len(msg)-1])
return msg[0:length-unpadding]