小坑
根据字节开发文档的AES解密敏感数据的示例代码返回的是二进制,要继续处理才能拿到正确的数据json或字典。结论在最后,不想看我扯的直接看结论。
历程
拿到该用户的session_key和iv以及加密数据encryptedData后,就可以代入代码解密了。
官方代码python版:
# python
import base64
# https://www.pycryptodome.org/
# pip install pycryptodome
from Crypto.Cipher import AES
def decrypt(encrypted_data, session_key, iv):
data = base64.b64decode(encrypted_data)
_key = base64.b64decode(session_key)
_iv = base64.b64decode(iv)
cipher = AES.new(_key, AES.MODE_CBC, _iv)
return cipher.decrypt(data)
返回的数据是bytes类型:
b'{"nickName":"\xe6\xb0\xb8\xe6\x81\x92~\xe9\x82\xa2\xe5\xa4\xa9",
"avatarUrl":"https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3033762272~120x256.image",
"gender":0,"city":"","province":"",
"country":"\xe4\xb8\xad\xe5\x9b\xbd","language":"",
"openId":"PYiPmKKsWwQ18EBf",
"watermark":{"appid":"tt34tef7866ce50ed6","timestamp":1602553165}}\x03\x03\x03'
总所周知,AES算法加密时不满16字节会填充。所以最后的( \x03 )就是填充的数据,不需要知道它是什么,只需要知道这是叫PKCS#7的填充方式。
摆在面前的有两条路:
- 先处理掉填充再将bytes转化成字符串
- 先转化成字符串再处理填充
我走的第二条路
user_info = user_info.decode()
拿到str类型:
{"nickName":"永恒~邢天",
"avatarUrl":"https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3033762272~120x256.image",
"gender":0,"city":"","province":"",
"country":"中国","language":"",
"openId":"PYiPmKKsWwQ18EBf",
"watermark":{"appid":"tt34tef7866ce50ed6","timestamp":1602553165}}^C^C^C
最后的填充解析成了^C,五个( \x05 )会被解析成五个 ^E。
接下来就是去掉 ^C,由于填充长度无法确定所以不能用切片。
我就用了个正则贪心匹配括号中的数据。
reg = re.compile("{.*}")
# 匹配结果返回list
user_info = re.findall(reg, user_info)[0]
拿到 str类型:
{"nickName":"永恒~邢天",
"avatarUrl":"https://sf1-ttcdn-tos.pstatp.com/img/mosaic-legacy/3795/3033762272~120x256.image",
"gender":0,"city":"","province":"",
"country":"中国","language":"",
"openId":"PYiPmKKsWwQ18EBf",
"watermark":{"appid":"tt34tef7866ce50ed6","timestamp":1602553165}}
接下来eval(), ast.literal_eval(), json.loads() 都可以处理
结论
user_info = decrypt(encrypted_data, session_key, iv)
user_info.decode()
reg = re.compile("{.*}")
# 匹配结果返回list
user_info = re.findall(reg, user_info)[0]
user_info = json.loads(user_info)
注意事项
json.loads里面的字典都是双引号,
复制解密数据到脚本尝试解密时,不要换行。