Python中AES嵌套加密消息实现错误排查:UnicodeDecodeError
错误信息
Traceback (most recent call last):
File "/home/javimp2003/Seguridad de la Información/Wuolah/ExamenPracEvaluable/b.py", line 48, in
mesIntDescifrado = json.loads(internoDescifrado)
File "/usr/lib/python3.10/json/init.py", line 341, in loads
s = s.decode(detect_encoding(s), 'surrogatepass')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x98 in position 0: invalid start byte
三方关键代码
TTP代码
ts = datetime.timestamp(dt) # dt为系统当前时间的float值 claveSesion = aes.crear_AESKey() messageParaA = [] messageParaA.append(str(ts)) messageParaA.append(claveSesion.hex()) jStr = json.dumps(messageParaA) cuatro_aes_cifrado, nonceFirst = aes.iniciarAES_CTR_cifrado(dosKBT) cuatroCifrado = aes.cifrarAES_CTR(cuatro_aes_cifrado,jStr.encode("utf-8")) #print(f"RESTOENC: {cuatroCifrado}") messageParaA.append(cuatroCifrado.hex()) jStrAux = json.dumps(messageParaA) cuatro_aes_cifrado_aux, nonceSecond = aes.iniciarAES_CTR_cifrado(unoKAT) cuatroCifradoTotal = aes.cifrarAES_CTR(cuatro_aes_cifrado_aux,jStrAux.encode("utf-8")) socketConA.enviar(nonceFirst) #interno socketConA.enviar(nonceSecond) #exterior socketConA.enviar(cuatroCifradoTotal)
Alice代码
nonceCifradoInterno = socketConTTP.recibir() nonceCifrado = socketConTTP.recibir() cuatroCifrado = socketConTTP.recibir() aes_descifrar = aes.iniciarAES_CTR_descifrado(keyConTTP,nonceCifrado) cuatroDescifrado = aes.descifrarAES_CTR(aes_descifrar,cuatroCifrado) messageDescifrado = json.loads(cuatroDescifrado) ts, claveSesion, elResto = messageDescifrado claveSesion = bytearray.fromhex(claveSesion) # 转换为字节类型的密钥 socketConTTP.cerrar() # ---------------------------------------------------------------------------------- socketConversacion = socket.SOCKET_SIMPLE_TCP('127.0.0.1',5555) socketConversacion.conectar() messageCinco = [] messageCinco.append("Alice") messageCinco.append(ts) jStrCinco = json.dumps(messageCinco) aes_cif, nonceCinco = aes.iniciarAES_CTR_cifrado(claveSesion) cincoCifrado = aes.cifrarAES_CTR(aes_cif,jStrCinco.encode("utf-8")) socketConversacion.enviar(nonceCifradoInterno) socketConversacion.enviar(elResto.encode("utf-8")) socketConversacion.enviar(nonceCinco) socketConversacion.enviar(cincoCifrado)
Bob代码
socketConversacion = socket.SOCKET_SIMPLE_TCP('127.0.0.1',5555) socketConversacion.escuchar() nonceCifradoInterno = socketConversacion.recibir() resto = socketConversacion.recibir() nonceCinco = socketConversacion.recibir() cincoCifrado = socketConversacion.recibir() descifrado_interno = aes.iniciarAES_CTR_descifrado(keyConTTP,nonceCifradoInterno) internoDescifrado = aes.descifrarAES_CTR(descifrado_interno,resto) mesIntDescifrado = json.loads(internoDescifrado) # 错误发生行 ts, claveSesion = mesIntDescifrado claveSesion = bytearray.fromhex(claveSesion) descifrarCinco = aes.iniciarAES_CTR_descifrado(claveSesion,nonceCinco) cincoDescifrado = aes.descifrarAES_CTR(descifrarCinco,cincoCifrado) mesCincoTotal = json.loads(cincoDescifrado) name, time = mesCincoTotal time = time.decode("utf-8") if ts == time: print(f"Hola {name}. Te mando el ts incrementado...")
错误原因分析
Alice端消息传递逻辑错误
TTP生成的cuatroCifrado是加密后的原始字节数据,已通过hex()转换为十六进制字符串存入消息。Alice收到后拿到的elResto是该十六进制字符串,但她错误地用encode("utf-8")将字符串转成字节发送给Bob,而非将十六进制字符串还原为原始加密字节。Bob收到的是十六进制字符串的UTF-8编码字节,直接解密后得到的不是合法UTF-8格式的JSON数据,因此抛出解码错误。Bob端冗余解码操作
Alice将ts(字符串类型)存入JSON发送,Bob解析后mesCincoTotal中的time本身就是字符串,无需再执行decode("utf-8"),该操作会引发额外错误。
解决方法
修正Alice代码
将发送elResto的代码替换为:
socketConversacion.enviar(nonceCifradoInterno) # 将十六进制字符串还原为原始加密字节后发送 resto_bytes = bytearray.fromhex(elResto) socketConversacion.enviar(resto_bytes) socketConversacion.enviar(nonceCinco) socketConversacion.enviar(cincoCifrado)
修正Bob代码
删除冗余的decode操作,修改为:
name, time = mesCincoTotal # 移除time = time.decode("utf-8"),直接使用字符串类型的time if ts == time: print(f"Hola {name}. Te mando el ts incrementado...")
验证流程
- TTP:加密JSON数据得到原始字节→ 转十六进制字符串存入消息→ 二次加密后发给Alice
- Alice:解密得到包含十六进制字符串的消息→ 将十六进制字符串还原为原始加密字节→ 发送给Bob
- Bob:收到原始加密字节→ 解密得到合法JSON数据→ 正常解析会话密钥与时间戳,完成验证
内容的提问来源于stack exchange,提问作者xxjmpxx__

