Python实现AES128_ECB_pkcs7padding数据加解密
Python实现AES128_ECB_pkcs7padding数据加解密
由于公司测试需要,需要模拟物联网设备向业务系统上传数据和接收数据,但是由于上下行数据为加密数据,寻找了很多方法,网上的加密方法大多实现的都是普通字符串的加解密,而设备的数据格式为字节式16进制字符串,如时间‘230213091406’代表2023-02-13 09:14:06每两位为一个字节,加解密后与期望的结果不一致,所以根据需求,使用python实现需求数据的加解密。
1.实现需求
1.采用标准的分组加密对称密钥加密算法: AES128 算法 advanced encryption standard 128 algorithm
2.数据补齐算法:补齐算法使用PKCS7Padding算法
PKCS7Padding:填充的原则是,如果需要N字节补齐,报文长度少于N个字节,需要补满N个字节,补(N-len)个(N-len)。如果报文长度正好时N字节的整数倍,则需要补N个十进制N。
举例:
需要8字节补齐,123这个节符串余3个字节,8-3= 5,补满后如:123+5个十进制的5,
如果字符串长度正好是8字节的整数倍,则需要再补8个字节的十进制的8。
本协议采用AES128 ECB加密算法。补齐对齐位数为128位,即16字节。
2.代码实现
话不多说,直接上代码,代码中也标明了每个函数的功能
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
-------------------------------------------------------------------------
@Project :
@File :
@IDE :PyCharm
@Author :
@Date :
function : AES128_ECB_pkcs7Padding加密16进制字符串
-------------------------------------------------------------------------
'''
import codecs
from Crypto.Cipher import AES
def hexStr_to_hexList(hexstr):
'''
将16进制字符串转换成16进制列表
:param hexstr:
:return:
'''
hexstrLen = len(hexstr)
if hexstrLen % 2 == 0:
hexList = [f'0x{hexstr[i:i+2]}' for i in range(0, hexstrLen, 2)]
else:
hexstr = hexstr + '0'
hexList = [f'0x{hexstr[i:i + 2]}' for i in range(0, hexstrLen, 2)]
return hexList
def hexStr_to_padd7ing_hexBytes(hexStr, block_size=16):
'''
将16进制字符串转换成16进制字节列表,并按pksc7Padding要求进行填充
:param hexStr:
:param block_size:
:return:
'''
hexList = hexStr_to_hexList(hexstr=hexStr)
eval_hexList = [eval(hexval) for hexval in hexList]
hexListLen = len(hexList)
pad = block_size - hexListLen % block_size
for i in range(pad):
eval_hexList.append(pad)
return bytearray(eval_hexList)
def keyStr_to_hexBytes(key, size=16):
'''
将秘钥的字符串转换成字节列表,不够16位用0补齐
:param key:
:param size:
:return:
'''
keyList = hexStr_to_hexList(hexstr=key)
if len(keyList) < size:
for i in range(0, size-len(keyList)):
keyList.append('0x00')
evalKey = [eval(val) for val in keyList]
return bytearray(evalKey)
def hexList_to_hexStr(hexList):
'''
将16进制字符串列表转换成一个16进制字符串
:param hexList:
:return:
'''
hex_str = ''
for hex in hexList:
str_list = hex.split('x')
if len(str_list[1]) == 1:
str_list[1] = '0'+str_list[1]
hex_str = hex_str + str_list[1]
return hex_str
def encryptData(data, key):
'''
加密数据
:param data:
:param key:
:return:
'''
key_byte = keyStr_to_hexBytes(key)
data_byte = hexStr_to_padd7ing_hexBytes(data)
# 通过AES.MODE_ECB处理初始密码字符串,并返回cipher对象
cipher = AES.new(key_byte, AES.MODE_ECB)
# 输入需要加密的字符串,注意字符串长度要是16的倍数。
encrypt_data = cipher.encrypt(data_byte)
encrypt_data = codecs.encode(encrypt_data, 'hex').upper()
data = str(encrypt_data).split("'")[1] # 将Byte类型转换成字符串
return data
def decryptData(data, key):
'''
解密数据
:param data:
:param key:
:return:
'''
hexStr = hexStr_to_hexList(hexstr=str(data))
eval_data = [eval(val) for val in hexStr]
data_byte = bytearray(eval_data)
key_byte = keyStr_to_hexBytes(key)
# 通过AES.MODE_ECB处理初始密码字符串,并返回cipher对象
cipher = AES.new(key_byte, AES.MODE_ECB)
# 输入需要解密的字符串,注意字符串长度要是16的倍数。
decrypt_data = cipher.decrypt(data_byte)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
unpad_data = unpad(s=decrypt_data)
decrypt_hexStr_list = [hex(data) for data in unpad_data]
data = hexList_to_hexStr(hexList=decrypt_hexStr_list)
return data
if __name__ == "__main__":
key = '35472468183894402541'
data = '230213091406000028690101FFFFFFB30000000002141264200330010000'
encrypt_data = encryptData(data=data, key=key)
print(f'原始数据:{data}')
print(f'加密前的数据:{encrypt_data}')
decrypt_data = decryptData(data=encrypt_data, key=key)
print(f'解密后的数据:{decrypt_data}')
接下来可以看看结果如何:
至此已完成数据的加解密,并且与预期结果一致。