如何在PowerShell中将哈希字符串转换为字节数组?

gt0wga4j  于 2023-01-20  发布在  Shell
关注(0)|答案(4)|浏览(237)

当我的脚本运行时,我读取了一个哈希值,我想把它写入注册表。我发现下面的命令可以做到这一点:

New-ItemProperty  $RegPath -Name $AttrName -PropertyType Binary -Value $byteArray

我还找到了How to set a binary registry value (REG_BINARY) with PowerShell?
然而,所有答案都假设字符串的形式为:

"50,33,01,00,00,00,00,00,...."

但我只能读取以下形式的哈希值:

"F5442930B1778ED31A....."

我想不出,我怎么能把它转换成一个字节数组,值为F5,44等。

tquggr8v

tquggr8v1#

vonPryz明智地建议直接将散列作为 * string *(REG_SZ)存储在注册表中。
如果您真的希望将数据存储为REG_BINARY类型,即存储为一个 * bytes * 数组,则必须在字符串表示之间来回转换。

    • 将 * 转换 * 为 * [byte[]]数组**(使用缩短的示例哈希字符串):
PS> [byte[]] -split ('F54429' -replace '..', '0x$& ')
245 # 1st byte: decimal representation of 0xF5
68  # 2nd byte: decimal representation of 0x44
41  # ...

-replace '..', '0x$& '为每对字符添加前缀(十六进制数字)-..,在替换操作数中引用为$&-与0x替换,然后插入一个空格。-split将生成的字符串拆分为0xHH字符串数组(H表示十六进制数字),PowerShell的自动类型转换将其识别为强制转换中[byte[]]数组的元素。换句话说:上述内容相当于:
x1米11米1x
以上是PowerShell默认的结果数组输出表示
[byte[]] (0xF5, 0x44, 0x29).

# PowerShell (Core) 7.1+ / .NET 5+
# -> (0xF5, 0x44, 0x29)
[System.Convert]::FromHexString('F54429')

# -> 'F54429'
[System.Convert]::ToHexString([byte[]] (0xF5, 0x44, 0x29))
    • 将 * [byte[]]数组**转换为 *(转换回字符串):

[System.BitConverter]::ToString()输出用- * 分隔的两个十六进制数字表示 *,因此要获得所需的表示,必须使用-replace操作删除所有-示例:

# -> 'F54429'
[System.BitConverter]::ToString([byte[]] (0xf5, 0x44, 0x29)) -replace '-'

把所有这些放在一起:

# Sample hash string.
$hashString = 'F54429'

# Convert the hash string to a byte array.
$hashByteArray = [byte[]] -split ($hashString -replace '..', '0x$& ')

# Create a REG_BINARY registry value from the byte array.
Set-ItemProperty -LiteralPath HKCU:\ -Name tmp -Type Binary -Value $hashByteArray

# Read the byte array back from the registry (PSv5+)
$hashByteArray2 = Get-ItemPropertyValue -LiteralPath HKCU:\ -Name tmp

# Convert it back to a string.
$hashString2 = [System.BitConverter]::ToString($hashByteArray2) -replace '-'

# (Clean up.)
Remove-ItemProperty -LiteralPath HKCU:\ -Name tmp
cyvaqqii

cyvaqqii2#

若要解析不具有正则表达式权重的十六进制字符串:

# parse the hex string into a BigInt
# leading zeros avoids parsing as negative
$bytes = [bigint]::Parse("00$value",'HexNumber').ToByteArray()

# undo the reversed bytes
[array]::Reverse($bytes)

# drop the leading zero byte
$null,$bytes = $bytes
b4qexyjb

b4qexyjb3#

下面是另一种不使用正则表达式的方法。

function HexToByteArray([string]$hex) {
(0..([Math]::Floor( ($hex.Length+1)/2)-1)).ForEach({[Convert]::ToByte($(if ($hex.Length -ge 2*($_+1)) {$hex.Substring($_*2,2)} else {$hex.Substring($_*2,1).PadRight(2,'0')}),16)})

}
它可能比你想要的更健壮--它试图支持奇数长度的输入字符串,你可能更喜欢不允许奇数长度的输入字符串,在这种情况下,转换表达式可以被简化。

t40tm48m

t40tm48m4#

.Net有一个内置函数。它有点隐藏...

$x = 'F5442930B1778ED31A'
$bytes = [System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary]::Parse($x).Value

另一个方向是这样的

[System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary]::new($bytes).ToString()

相关问题