将安全字符串转换为纯文本


87

我正在使用PowerShell,并且我有将用户输入的密码成功转换为纯文本的代码:

$SecurePassword = Read-Host -AsSecureString  "Enter password" | convertfrom-securestring | out-file C:\Users\tmarsh\Documents\securePassword.txt

我尝试了几种将其转换回去的方法,但是似乎都无法正常工作。最近,我尝试了以下方法:

$PlainPassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt

#convert the SecureString object to plain text using PtrToString and SecureStringToBSTR
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassword)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important step to keep things secure

这也给我一个错误。

Cannot convert argument "s", with value: "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e43000000000200000000000366000
0c0000000100000008118fdea02bfb57d0dda41f9748a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8
bc271400000038c731cb8c47219399e4265515e9569438d8e8ed", for "SecureStringToBSTR" to type "System.Security.SecureString": "Cannot convert the "01000000
d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f9748a05f10
000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569438d8e8
ed" value of type "System.String" to type "System.Security.SecureString"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:14 char:1
+ $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($PlainPassw ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Cannot find an overload for "PtrToStringAuto" and the argument count: "1".
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:15 char:1
+ $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

Cannot convert argument "s", with value: "", for "ZeroFreeBSTR" to type "System.IntPtr": "Cannot convert null to type "System.IntPtr"."
At C:\Users\tmarsh\Documents\Scripts\Local Admin Script\PlainTextConverter1.ps1:16 char:1
+ [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) #this is an important ste ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Password is:  01000000d08c9ddf0115d1118c7a00c04fc297eb0100000026a5b6067d53fd43801a9ef3f8ef9e430000000002000000000003660000c0000000100000008118fdea02bfb57d0dda41f97
48a05f10000000004800000a000000010000000c50f5093f3b87fbf9ee57cbd17267e0a10000000833d1d712cef01497872a3457bc8bc271400000038c731cb8c47219399e4265515e9569
438d8e8ed

有谁知道一种可行的方法吗?

Answers:


115

您很接近,但是传递给的参数SecureStringToBSTR必须是SecureString。您似乎正在传递的结果ConvertFrom-SecureString,这是一个加密的标准字符串。因此ConvertTo-SecureString,请先传递给,然后再调用SecureStringToBSTR

$SecurePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

4
我很高兴它有效。小心你的字符串,现在,它是一个包含大概有点像一个密码,重要的一个不安全的字符串变量-它在你的进程内存等不再安全
MatthewG

19
根据Marshal.SecureStringToBSTR文档:因为此方法分配字符串所需的非托管内存,所以在完成时始终通过调用ZeroFreeBSTR方法释放BSTR。因此,您必须最后执行以下操作:[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
Rosberg Linhares

@RosbergLinhares-因为我们(大概是)专注于Powershell,所以有什么原因不能仅仅是您$BSTR = $null
Orangutech

3
@Orangutech您不能仅将变量设置为$null,因为在这里我们要处理非托管对象。您不会立即得到错误,但是随着时间的流逝,您可能会遇到问题。
Rosberg Linhares

1
如前所述,由于缺少对的调用而导致的内存泄漏ZeroFreeBSTR(),使用在PtrToStringAuto()概念上总是有缺陷的,并且-由于PowerShell是跨平台的-在类Unix平台上失败。它应该一直都是PtrToStringBSTR() -看到这个答案
mklement0

81

您也可以使用PSCredential.GetNetworkCredential():

$SecurePassword = Get-Content C:\Users\tmarsh\Documents\securePassword.txt | ConvertTo-SecureString
$UnsecurePassword = (New-Object PSCredential "user",$SecurePassword).GetNetworkCredential().Password

我已经测试了这两种方法,但它们仍然都是正确的。
Maximilian Burszley

10
支持此解决方案,因为它更强大。
吉姆(Jim

1
System.Management.Automation.PSCredential无法识别短类型名称时,在较早的PS版本中使用。
marsze

1
[PSCredential]::new(0, $SecurePassword).GetNetworkCredential().Password
简称

简短说明:[System.Net.NetworkCredential]::new("", $SecurePassword).Password
K.弗兰克

36

在PowerShell中将其转换回最简单的方法

[System.Net.NetworkCredential]::new("", $SecurePassword).Password

1
实际上,无需通过PSCredential。
Nicolas Melay

我喜欢这种方法。仅供参考,出于兼容性迷的考虑SecureString,.Net Framework 4.0中引入了此构造方法重载。在PowerShell v2上,我尝试过, (New-Object -TypeName System.Net.NetworkCredential -ArgumentList "u",$SecureString).Password但不幸的SecureString是,它已默默转换为String。调用似乎成功,但是该Password属性为文字值“ System.Security.SecureString”。小心。
约翰·里斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.