基于Crypto的python3 AES CBC pcks7padding 中文劫扒、英文、中英文混合加密
最近在模擬網(wǎng)頁(yè)請(qǐng)求時(shí)聚霜,遇到了AES加密,折騰許久珠叔,終于搞定蝎宇,獻(xiàn)上工具類給有需要的有緣人〉话玻【來(lái)自一個(gè)此前從未弄過(guò)AES加密解密的小白】
解決過(guò)程中姥芥,搜索了很多,印象深刻的是pkcs7padding汇鞭,unpadding相關(guān)代碼凉唐,查看瀏覽器歷史記錄,翻出了大大的博客鏈接:https://blog.csdn.net/davidsu33/article/details/52841955
運(yùn)行環(huán)境python3霍骄,依賴庫(kù)pycryptodome[3.3.6]
獻(xiàn)上代碼台囱,關(guān)鍵點(diǎn)都有注釋
#!/usr/bin/env python
# -*- coding=utf-8 -*-
"""
AES加密解密工具類
@author jzx
@date 2018/10/24
此工具類加密解密結(jié)果與 http://tool.chacuo.net/cryptaes 結(jié)果一致
數(shù)據(jù)塊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填充
最終調(diào)用AES加密方法時(shí)读整,傳入的是一個(gè)byte數(shù)組簿训,要求是16的整數(shù)倍,因此需要對(duì)明文進(jìn)行處理
:param text: 待加密內(nèi)容(明文)
:return:
"""
bs = AES.block_size # 16
length = len(text)
bytes_length = len(bytes(text, encoding='utf-8'))
# tips:utf-8編碼時(shí)绘沉,英文占1個(gè)byte煎楣,而中文占3個(gè)byte
padding_size = length if(bytes_length == length) else bytes_length
padding = bs - padding_size % bs
# tips:chr(padding)看與其它語(yǔ)言的約定,有的會(huì)使用'\0'
padding_text = chr(padding) * padding
return text + padding_text
def pkcs7unpadding(text):
"""
處理使用PKCS7填充過(guò)的數(shù)據(jù)
:param text: 解密后的字符串
:return:
"""
length = len(text)
unpadding = ord(text[length-1])
return text[0:length-unpadding]
def encrypt(key, content):
"""
AES加密
key,iv使用同一個(gè)
模式cbc
填充pkcs7
:param key: 密鑰
:param content: 加密內(nèi)容
: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使用同一個(gè)
模式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')
# 去除填充內(nèi)容
result = pkcs7unpadding(result)
return result
def get_key(n):
"""
獲取密鑰 n 密鑰長(zhǎng)度
: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字節(jié)的情況
aes_key = get_key(16)
print('aes_key:' + aes_key)
# 對(duì)英文加密
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字節(jié)的情況
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)
運(yùn)行結(jié)果如下
aes_key:GENjnwZR4p2M5saR
zN/Fp+aYR2XKdnNQxS/bDA==
Hello!
True
M4InzQpqqC18d1KLIr6VUl7mipdgGEbjC8a3RNM3Y74=
Hello, 韓- 梅 -梅
True
qX0vFKGQ1Av9JzoNaCfBHkAOreJBike+l9h820yYnUQ=
abcdefgj10124567
True
PcgPrSAA6Lgrng+VFr1ja2O50PgQ2TOXhWfSd4KLL2M=
abx張三豐12sa
True