您是否可以使用PtrToStringAuto在macOS上的Powershell 7中解密安全字符串? [英] Are you able to use PtrToStringAuto to decrypt a secure string in Powershell 7 on macOS?

查看:34
本文介绍了您是否可以使用PtrToStringAuto在macOS上的Powershell 7中解密安全字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有成功获取下面的代码片段以输出"Hello World!".在PS7中

I have had no success in getting the following code snippet to output "Hello World!" in PS7

$string = $("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string))

上面的代码是不指定长度就解密安全字符串的示例.

The above code is an example of decrypting a secure string without specifying a length.

此代码在PS6和PS5中可以完全解密安全字符串,但在PS7中不起作用.我发现的唯一解决方法是使用PtrToStringBSTR.然后,在此用例的所有PS版本中,它都能按预期工作.

This same code works in PS6 and PS5 to fully decrypt the Secure String, but does not work in PS7. The only way around this I have found is to use PtrToStringBSTR. Then it works as expected across all versions of PS for this use case.

我在Github上的Powershell存储库中提出了一个问题,但没有任何回应.老实说,我只是在寻找一些确认,以确保其他人的行为相同.

I raised an issue at the Powershell repo on Github, but haven't had any responses. I'm honestly just looking for some confirmation that the behavior is the same for others.

https://github.com/PowerShell/PowerShell/issues/11953

我认为对于许多移植到PS7的代码来说,这将是一项重大突破.

I would think something like this would be a breaking change for a lot of code being ported to PS7.

这是我到目前为止所发现的:

Here is what I have found so far:

文档

https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.marshal.ptrtostringauto?view = netframework-4.8

根据文档,当指定整数PtrToStringAuto时:

According to the documentation, when specifying an integer, PtrToStringAuto:

分配一个托管字符串,并从存储在非托管内存中的字符串中复制指定数量的字符.

指定int为11返回"Hello",这是因为返回的所有其他char为Null.在这种情况下,您必须指定一个int 23以返回完整的字符串"Hello World!".使用这种方法.我将输出存储在变量中以演示这一点.

Specifying an int of 11 Returns "Hello", this is because every other char returned is Null. In this case, you must specify an int of 23 to return the complete string "Hello World!" using this method. I have stored the output in a variable to demonstrate this.

$String = $("Hello World!" | ConvertTo-SecureString -AsPlainText -Force)
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($string), 23)

$String[0] Returns H
$String[1] Returns NULL
$String[2] Returns E
$String[3] Returns NULL
etc.... 

如果未指定整数,则PtrToStringAuto:

If no integer is specified, PtrToStringAuto:

分配一个托管字符串,并将所有字符复制到非托管内存中存储的字符串中的第一个空字符为止.

我认为这表明安全字符串是使用NULL值存储的,而在PS6中则不是,或者PtrToStringAuto函数的行为已更改,并且现在遵循上述文档中的行为.

I believe this suggests that either the Secure String is being stored with NULL values, whereas in PS6 it was not, or that the behavior of the PtrToStringAuto function has changed, and now adheres to the behavior the documentation describes above.

这只是macOS上的一个问题;但是,使用PtrToStringBSTR代替PtrToStringAuto解密安全字符串可以在Windows和macOS上正常工作.

This is only an issue on macOS; however, using PtrToStringBSTR in place of PtrToStringAuto to decrypt the Secure String works as expected across windows and macOS.

这似乎与以下内容有关: https://stackoverflow.com/a/11022662/4257163

This seems related: https://stackoverflow.com/a/11022662/4257163

我也看不到有任何更改.

I also do not see anywhere that a change was made.

推荐答案

请注意, [安全字符串]

Note that [securestring] is not recommended for new code anymore.

在Windows上,安全字符串通过

While on Windows secure strings offer limited protection - by storing the string encrypted in memory - via the DPAPI - and by shortening the window during which the plain-text representation is held in memory, no encryption at all is used on Unix-like platforms.[1]

解决这个问题的唯一方法是使用 PtrToStringBSTR .

这不仅是解决问题的一种方法,

That is not only a way around the problem, PtrToStringBSTR is the method that should have been used to begin with, given that the input string is a BSTR.[2]

请注意,在常规的 [string] 实例之间来回转换安全字符串会失去使用 [securestring] 开头的目的:您将最终以敏感内容的纯文本表示形式保存在进程的内存中,这些内存的生命周期无法控制.

Do note that converting a secure string to and from a regular [string] instance defeats the very purpose of using [securestring] to begin with: you'll end up with a plain-text representation of your sensitive data in your process' memory whose lifetime you cannot control.

如果您确实想执行此操作,则一种更简单的,跨平台兼容的方法是:

If you really want to do this, a simpler, cross-platform-compatible approach is:

[System.Net.NetworkCredential]::new('dummy', $string).Password


[1]当通过 ConvertFrom-SecureString Export-CliXml 将安全字符串保存在文件中时,这尤其成问题.代码>-请参见此答案.


[1] This is especially problematic when you save a secure string in a file, via ConvertFrom-SecureString or Export-CliXml - see this answer.

[2] PtrToStringAuto()中的 Auto 表示假定 unmanaged 输入字符串使用适用于平台的字符编码,而 BSTR all 平台上的"Unicode"(UTF-16)字符串.在Windows上,假定非托管字符串具有UTF-16编码(这就是代码起作用的原因),而在类Unix平台上,因为.NET Core 3.0(基于PowerShell [Core] 7.0,所以它是UTF-8)在.NET Core 3.1上),它可以解释您的症状: NUL 字符.(错误)解释为UTF-8时,在 BSTR 实例中将UTF-16代码单元本身解释为字符.请注意, .NET Core 2.x(这是PowerShell [Core] 6.x所基于的基础)(不当地)默认为UTF-16 ,它是

[2] The Auto in PtrToStringAuto() means that the unmanaged input string is assumed to use a platform-appropriate character encoding, whereas BSTR is a "Unicode" (UTF-16) string on all platforms. On Windows, an unmanaged string is assumed to have UTF-16 encoding (which is why the code works), whereas on Unix-like platforms it is UTF-8 since .NET Core 3.0 (PowerShell [Core] 7.0 is based on .NET Core 3.1), which explains your symptoms: the NUL chars. in the BSTR instance's UTF-16 code units are interpreted as characters in their own right when (mis)interpreted as UTF-8. Note that .NET Core 2.x (which is what PowerShell [Core] 6.x is based on) (inappropriately) defaulted to UTF-16, which this PR fixed, amounting to a breaking change.

这篇关于您是否可以使用PtrToStringAuto在macOS上的Powershell 7中解密安全字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆