【问题标题】:Understanding Python's representation of base64 decoded bytes理解 Python 对 base64 解码字节的表示
【发布时间】:2023-03-27 18:45:01
【问题描述】:

上下文: 我正在尝试一个捕获一些 MQTT 消息然后记录它们的程序。这样做时,我遇到了一个奇怪的问题,我需要帮助。

在传入的消息中,我得到一个 base64 编码的字符串。我的程序尝试解码和解析二进制数据以找出数据包的一些标头。我的代码如下所示:

result = base64.standard_b64decode("AO/Nq4lnRSMBZXMnLHcKXhSObYxiFvY=")

结果的输出如下所示:

b"\x00\xef\xcd\xab\x89gE#\x01es',w\n^\x14\x8em\x8cb\x16\xf6"

如果使用 nodeJS 实现同样的操作,输出是完全不同的:

<Buffer 00 ef cd ab 89 67 45 23 01 65 73 27 2c 77 0a 5e 14 8e 6d 8c 62 16 f6>

我在堆栈溢出中阅读了其他一些链接,但不明白为什么存在差异。链接NodeJS base64 Vs Python base64 有一些关于已完成编码的有效点,因此 Python 在这里所做的并没有错。

进一步阅读后,我发现了另一个使用 binascii 函数的技巧。所以,如果我应用这个逻辑,我的输出看起来和 NodeJS 的输出完全一样!

import binascii
binascii.hexlify(result)
b'00efcdab89674523016573272c770a5e148e6d8c6216f6'

现在我的输出看起来像我想要的。然而,还有另一个新问题。 base64 解码的输出格式为 b'\x00',而 hexlify 的输出格式为 b'0'。由于这种差异,我无法运行代码的另一部分,该代码将这个输出逐字节拆分以根据数据包的标头以不同的格式执行 struct.unpack。

有什么帮助我可以继续吗?

【问题讨论】:

标签: python node.js python-3.x base64


【解决方案1】:

如果我理解得很好,您对 Python 的字节格式感到困惑。

基本上,当在 Python 中显示一个字节时,如果这个字节匹配一个 ASCII 字符,则使用该字符而不是数值。结果在 Python 和 NodeJS 中其实是一样的,只是表示不同。

您可以通过对齐两种表示来检查它:

b"    \x00\xef\xcd\xab\x89  g  E  #\x01  e  s  '  ,  w \n  ^\x14\x8e  m\x8c  b\x16\xf6"
<Buffer 00  ef  cd  ab  89 67 45 23  01 65 73 27 2c 77 0a 5e  14  8e 6d  8c 62  16  f6>

如您所见,这些值是相同的,除了:

67 -> g
45 -> E
23 -> #
65 -> e
73 -> s
27 -> '
2c -> ,
0a -> \n
5e -> ^
6d -> m

事实上,上面显示的每个十六进制值都与 ASCII 表中的一个字符相匹配。

您可以在 Python 解释器中轻松验证它(ord 给出给定字符的 ascii 代码,hex 将其转换为十六进制表示):

>>> hex(ord('g'))
'0x67'
>>> hex(ord('E'))
'0x45'
>>> hex(ord('#'))
'0x23'

最后你甚至可以在几行 Python 中获得与 NodeJS 完全相同的表示:

>>> bytes = b"\x00\xef\xcd\xab\x89gE#\x01es',w\n^\x14\x8em\x8cb\x16\xf6"
>>> print('<Buffer {}>'.format(' '.join([format(c, '02x') for c in bytes])))
<Buffer 00 ef cd ab 89 67 45 23 01 65 73 27 2c 77 0a 5e 14 8e 6d 8c 62 16 f6>

【讨论】:

  • 哇。你是对的,我无法弄清楚 NodeJS 和 Python 输出的相似性。非常感谢您为我澄清这一点。我现在有了一个想法来推进这件事。
【解决方案2】:

base64.standard_b64decode 返回一个bytes 对象,它是一个不可变的单字节序列。这由" 之前的b 字母表示。

来自docs

字节字面量总是以'b''B' 为前缀;它们生成bytes 类型的实例,而不是str 类型。它们可能只包含 ASCII 字符;数值为 128 或更大的字节必须用转义符表示。

您在此处看到的是 bytes 对象的 ASCII 表示,而不是字符串。

为了将bytes对象转换成类似于你从nodeJS得到的结果的字符串,你可以使用bytes对象方法hex

import base64

result = base64.b64decode(b"AO/Nq4lnRSMBZXMnLHcKXhSObYxiFvY=")

print(result.hex())

>>> 00efcdab89674523016573272c770a5e148e6d8c6216f6

【讨论】:

  • 谢谢雅克。我的代码中缺少 result.hex() !我得到了我想要的东西,现在可以继续记录我收到的信息。
  • 很高兴听到它有帮助。 bytes 一开始可能会有点混乱,但没什么好害怕的。祝你好运!
猜你喜欢
  • 1970-01-01
  • 2011-10-18
  • 2012-11-13
  • 2020-12-26
  • 2021-04-15
  • 2019-10-12
  • 2020-06-24
  • 2021-09-16
  • 1970-01-01
相关资源
最近更新 更多