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

Converting a hex string to base 64 in PowerShell

我正在尝试在 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()

它接受一个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);

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

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

但显然不会先将其转换为十六进制,因此会产生不正确的结果。感谢任何帮助。

# Remove everything except word characters from the string.
# In effect, this removes any punctuation ('-', ':', '.')
$sanitizedHexStr = 'AA:BB:CC:DD:E2:00' -replace '\W'

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

# Get the Base64 encoding of the byte array.
[System.Convert]::ToBase64String($bytes)

有关用于创建 $bytes 数组的技术的说明,以及更简单的 PowerShell(核心)7.1+ / .NET 5+ 替代方案(简而言之:[System.Convert]::FromHexString('AABBCCDDE200')),参见 .


至于你试过的

Format-Hex不是return字节数组(直接),它的主要目的是可视化 十六进制格式的输入数据对于人类观察者

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

也就是说,Format-Hex 的特定情况下,输出对象 的类型 [Microsoft.PowerShell.Commands.ByteCollection], do contain useful data, and do contain the bytes of the transcoded characters of input strings .Bytes property, as Cpt.Whale 指出。

但是,$bytes = ($sanitizedHexStr | Format-Hex).Bytes 不适用于您的情况,因为您将有效地获得反映 ASCII 代码点 [=91] 的字节值=] 等字符 A (见下文) - 而你需要的是将这些字符解释为 十六进制数字 .

但即使在一般情况下我建议不要依赖Format-Hex进行到字节数组的转换:

  • 如前所述,Format-* cmdlet 的目的是产生 for-display 输出,而不是 data,值得观察这个区别,尽管有这个例外——输出对象的类型可以被认为是一个实现细节

  • Format-Hex 根据首先应用 固定字符转码 将字符串转换为字节(例如,您无法获得.NET 字符串 原样,基于 UTF-16 代码单元),并且 之间的固定转码 Windows PowerShellPowerShell(核心):

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

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


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

也就是说,您并不是要将字节重新转换为 字符串,而是要将字节直接转换为 Base64 编码,如上所示。