文章目录
背景
以蓝牙官方协议(V5.0)中的 sample data 为例子,看看怎么用 python 实现 AES 加密和解密。
测试数据
我们看看怎么由 SK 和 B0 得到 X1,然后从 X1 得到 B0
代码
from Crypto.Cipher import AES # install pycryptodomeimport binascii
SK = binascii.unhexlify('99AD1B5226A37E3E058E3B8E27C2C666')# MSB - LSB
B0 = binascii.unhexlify('49000000008024ABDCBABEBAAFDE0001')# LSB - MSB# 加密
plaintext = B0
rijn = AES.new(SK, AES.MODE_ECB)
ciphertext = rijn.encrypt(plaintext)
result = binascii.hexlify(ciphertext).decode('utf-8')print(result)# 解密
plaintext = rijn.decrypt(ciphertext)
result = binascii.hexlify(plaintext).decode('utf-8')print(result)
运行结果:
712eaaaae60603521d245e50786eefe4
49000000008024abdcbabebaafde0001
说明:
- 为了使用 AES 模块,需要安装 pycryptodome
binascii.unhexlify(hexstr)
:返回由十六进制字符串 hexstr 表示的二进制数据。 hexstr 必须包含偶数个十六进制数字(可以是大写或小写),否则会引发Error
异常。binascii.hexlify(data)
: 返回二进制数据 data 的十六进制表示形式。 data 的每个字节都被转换为相应的 2 位十六进制表示形式。因此返回的字节对象的长度是 data 的两倍。
遗留问题
我对字节序这块比较困惑,网上说 AES 是按照字节来加密的,可以认为明文是一个字节一个字节送进加密引擎,所以应该是低字节在前面;那 KEY 应该是什么顺序呢?是大端吗?
我尝试用 http://www.efgh.com/software/rijndael.htm 的代码实现,发现在下面的函数中:
int rijndaelSetupEncrypt(uint32_t *rk, const uint8_t *key, int keybits)
第二个参数 key,应该是从 MSB 到 LSB,也就是说 key[0] = 0x99,key[1] = 0xAD;…
补充(2021.10.6)
考虑到大小端的问题,有时候需要对字符串做端的转换,添加一个小函数。
defreverse(key):
out =''for i inrange(30,-1,-2):
out = out + key[i:i+2]return out
解释一下,假定 key 字符串的长度是 32 个字符
循环中 i 的取值是 30,28,26,…,0
这样就可以构成切片 key[30:32] , key[28:30] , key[26:28] , … , key[0:2],把它们拼在一起就可以得到结果。
【End】
版权归原作者 车子 chezi 所有, 如有侵权,请联系我们删除。