轉載https://www.jianshu.com/p/5d27888e7c93#!/xh #!/usr/bin/env python # -*- coding=utf-8 -*- """ AES加密解密工具類 @author jzx @date 2018/10/24 此工具類加密解密結果與 htt ...
轉載https://www.jianshu.com/p/5d27888e7c93#!/xh
#!/usr/bin/env python
# -*- coding=utf-8 -*-
"""
AES加密解密工具類
@author jzx
@date 2018/10/24
此工具類加密解密結果與 http://tool.chacuo.net/cryptaes 結果一致
數據塊128位
key 為16位
iv 為16位,且與key相等
字元集utf-8
輸出為base64
AES加密模式 為cbc
填充 pkcs7padding
"""
import base64
from Crypto.Cipher import AES
import random
def pkcs7padding(text):
"""
明文使用PKCS7填充
最終調用AES加密方法時,傳入的是一個byte數組,要求是16的整數倍,因此需要對明文進行處理
:param text: 待加密內容(明文)
:return:
"""
bs = AES.block_size # 16
length = len(text)
bytes_length = len(bytes(text, encoding='utf-8'))
# tips:utf-8編碼時,英文占1個byte,而中文占3個byte
padding_size = length if(bytes_length == length) else bytes_length
padding = bs - padding_size % bs
# tips:chr(padding)看與其它語言的約定,有的會使用'\0'
padding_text = chr(padding) * padding
return text + padding_text
def pkcs7unpadding(text):
"""
處理使用PKCS7填充過的數據
:param text: 解密後的字元串
:return:
"""
length = len(text)
unpadding = ord(text[length-1])
return text[0:length-unpadding]
def encrypt(key, content):
"""
AES加密
key,iv使用同一個
模式cbc
填充pkcs7
:param key: 密鑰
:param content: 加密內容
:return:
"""
key_bytes = bytes(key, encoding='utf-8')
iv = key_bytes
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
# 處理明文
content_padding = pkcs7padding(content)
# 加密
encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
# 重新編碼
result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
return result
def decrypt(key, content):
"""
AES解密
key,iv使用同一個
模式cbc
去填充pkcs7
:param key:
:param content:
:return:
"""
key_bytes = bytes(key, encoding='utf-8')
iv = key_bytes
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
# base64解碼
encrypt_bytes = base64.b64decode(content)
# 解密
decrypt_bytes = cipher.decrypt(encrypt_bytes)
# 重新編碼
result = str(decrypt_bytes, encoding='utf-8')
# 去除填充內容
result = pkcs7unpadding(result)
return result
def get_key(n):
"""
獲取密鑰 n 密鑰長度
:return:
"""
c_length = int(n)
source = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
length = len(source) - 1
result = ''
for i in range(c_length):
result += source[random.randint(0, length)]
return result
# Test
# 非16位元組的情況
aes_key = get_key(16)
print('aes_key:' + aes_key)
# 對英文加密
source_en = 'Hello!'
encrypt_en = encrypt(aes_key, source_en)
print(encrypt_en)
# 解密
decrypt_en = decrypt(aes_key, encrypt_en)
print(decrypt_en)
print(source_en == decrypt_en)
# 中英文混合加密
source_mixed = 'Hello, 韓- 梅 -梅'
encrypt_mixed = encrypt(aes_key, source_mixed)
print(encrypt_mixed)
decrypt_mixed = decrypt(aes_key, encrypt_mixed)
print(decrypt_mixed)
print(decrypt_mixed == source_mixed)
# 剛好16位元組的情況
en_16 = 'abcdefgj10124567'
encrypt_en = encrypt(aes_key, en_16)
print(encrypt_en)
# 解密
decrypt_en = decrypt(aes_key, encrypt_en)
print(decrypt_en)
print(en_16 == decrypt_en)
mix_16 = 'abx張三豐12sa'
encrypt_mixed = encrypt(aes_key, mix_16)
print(encrypt_mixed)
decrypt_mixed = decrypt(aes_key, encrypt_mixed)
print(decrypt_mixed)
print(decrypt_mixed == mix_16)