在 PowerShell 中将十六进制字符串转换为 base 64

Gra*_*ell 3 powershell base64 hex

我正在尝试在 PowerShell 中复制以下 Python 代码段的功能:

allowed_mac_separators = [':', '-', '.']
for sep in allowed_mac_separators:
    if sep in mac_address:
        test = codecs.decode(mac_address.replace(sep, ''), 'hex')
        b64_mac_address = codecs.encode(test, 'base64')
        address = codecs.decode(b64_mac_address, 'utf-8').rstrip()
Run Code Online (Sandbox Code Playgroud)

它需要一个 MAC 地址,删除分隔符,将其转换为十六进制,然后是 base64。(我没有编写 Python 函数,也无法控制它或它是如何工作的。)

例如,MAC 地址AA:BB:CC:DD:E2:00将转换为AABBCCDDE200,然后转换为,b'\xaa\xbb\xcc\xdd\xe2\x00'最后作为输出b'qrvM3eIA'。我尝试做类似的事情:

$bytes = 'AABBCCDDE200' | Format-Hex
[System.BitConverter]::ToString($bytes);
Run Code Online (Sandbox Code Playgroud)

但这会产生MethodException: Cannot find an overload for "ToString" and the argument count: "1".,我不确定它在寻找什么。我发现的所有使用该调用的示例都只有一个参数。这有效:

[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('AABBCCDDE200'))

但显然不会先将其转换为十六进制,从而产生不正确的结果。任何帮助表示赞赏。

mkl*_*nt0 5

# Remove everything except hex digits from the string.
$sanitizedHexStr = 'AA:BB:CC:DD:E2:00' -replace '[^0-9a-f]'

# Convert all hex-digit pairs in the string to an array of bytes.
$bytes = [byte[]] ($sanitizedHexStr -split '(..)' -ne '' -replace '^', '0x')

# Get the Base64 encoding of the byte array.
[System.Convert]::ToBase64String($bytes)
Run Code Online (Sandbox Code Playgroud)

有关用于创建$bytes数组的技术的说明,请参阅此答案


至于你尝试什么

Format-Hex返回字节数组(直接),其主要目的是为人类观察者以十六进制格式可视化输入数据。

通常,Format-*cmdlet 输出对象的唯一目的是向 PowerShell 的输出格式化系统提供格式化指令- 请参阅此答案。简而言之:只使用Format-*cmdlet 来格式化数据以供显示,永远不要用于后续的程序处理

也就是说,Format-Hex输出对象的特殊情况下,类型为[Microsoft.PowerShell.Commands.ByteCollection]确实包含有用的数据,并且确实包含输入字符串属性的转码字符的字节.Bytes,正如Cpt.Whale指出的那样。

但是,$bytes = ($sanitizedHexStr | Format-Hex).Bytes不会在你的情况下工作,因为你会得到有效的字节值反映了ASCII码点的字符,如A(见下文) -而你需要的是这些字符的解释十六进制数字

但即使在一般情况下,我建议不要依赖于Format-Hex字节数组转换

  • 在哲学上,如上所述,Format-*cmdlet的目的是生成用于显示的输出,而不是数据,并且值得观察这种区别,尽管有这种例外 - 输出对象的类型可以被视为实现细节

  • Format-Hex将字符串转换为字节基础上首先施加固定的字符转换(例如,你不能让一个.NET字符串的字节表示原样的基础上,UTF-16代码单元),而固定转换不同之间Windows PowerShell中PowerShell(核心)

    • 在 Windows PowerShell 中,.NET 字符串被转码为 ASCII(!),导致非 ASCII 范围字符丢失 - 它们被转码为文字 ?

    • 在 PowerShell (Core) 中,通过转码为 UTF-8 可以避免该问题。


System.BitConverter.ToString失败,因为$bytes在你的代码本身不是一个字节数组([byte[]]),只有其.Bytes属性值是(但不包含感兴趣的值)。

也就是说,您不希望将 bytes 重新转换为string,而是希望将字节直接转换为 Base64 编码,如上所示。

  • @SantiagoSquarzon,是的,从输入字符串中的相邻十六进制数字对创建了一个由 2 个字符组成的字符串数组;链接的答案更详细地解释了它。 (2认同)