
python中手动逐字符解析十六进制字符串时因utf-8编码引入多余字节,导致输入到md5的原始字节流与php不一致;应直接使用`bytes.fromhex()`或`binascii.unhexlify()`进行无损十六进制解码。
在跨语言接口(如Python客户端对接PHP服务端)中,MD5校验失败是常见问题。本例中,PHP端将十六进制字符串 "96f6e3a1c4748b81e41ac58dcf6ecfa0" 正确解析为原始字节序列后计算MD5,得到 b761f889707191e6b96954c0da4800ee;而Python原代码却错误地将每个两位十六进制数先转为整数、再用 chr() 转为Unicode字符,最后调用 .encode("utf-8") —— 这一过程会将单个字节(如 0x96)映射为UTF-8多字节序列(如 b'\xc2\x96'),彻底破坏原始二进制语义。
✅ 正确做法:跳过字符编码层,直接将十六进制字符串解码为原始字节对象。推荐以下任一方式:
import hashlib key_string = '96f6e3a1c4748b81e41ac58dcf6ecfa0' # 方法1:推荐,简洁安全(Python 3.5+) raw_bytes = bytes.fromhex(key_string) # 方法2:兼容旧版本(需 import binascii) # import binascii # raw_bytes = binascii.unhexlify(key_string) # 直接传入hashlib.md5() —— 它接受bytes类型,无需.encode() md5_hash = hashlib.md5(raw_bytes) print(md5_hash.hexdigest()) # 输出:b761f889707191e6b96954c0da4800ee
⚠️ 注意事项:
- 绝不使用 chr(int(hex_pair, 16)) + .encode() 组合:chr() 生成的是Unicode码点,而 0x96 等值超出ASCII范围(0–127),其UTF-8编码必然产生2字节以上序列,导致输入字节长度翻倍且内容失真;
- 确保两端处理逻辑完全对等:PHP的 chr(hexdec(...)) 实际执行的是字节级转换(假设运行环境为单字节编码),Python必须用 bytes.fromhex() 保持同等语义;
- 验证中间结果:调试时可打印 raw_bytes(如 b'\x96\xf6\xe3\xa1...')与PHP中 $server_rand_code 的 ord() 序列比对,确认字节一致性。
总结:MD5是纯字节摘要算法,输入必须严格一致。跨语言场景下,应统一使用十六进制字符串 → 原始字节的标准解码方式,避免任何中间字符编码介入。bytes.fromhex() 是Python中最直接、最可靠的解决方案。
立即学习“PHP免费学习笔记(深入)”;











