处理凭据的一般方法是避免使用它们,而是依赖其他方式进行身份验证,例如证书或 Windows 身份验证。 https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md
正如您显然自己发现的那样,尝试编写一个单因素身份验证 https://en.wikipedia.org/wiki/Authentication要么最终以catch-22 https://en.wikipedia.org/wiki/Catch-22_(logic)或者不安全,因为无论您使用脚本隐藏多深,有权访问您的脚本的每个人都可以访问密钥通过默默无闻实现安全 https://en.wikipedia.org/wiki/Security_through_obscurity.
如果您无法更改应用程序的身份验证方式,最安全的实用方法可能是创建您自己的“单点登录 https://en.wikipedia.org/wiki/Single_sign-on” 在使用 Windows 的方式DPAPI(数据保护API) https://en.wikipedia.org/wiki/Single_sign-on其中加密基于计算机和用户凭据。
为此,您可以使用 PowerShell转换为安全字符串 https://learn.microsoft.com/powershell/module/microsoft.powershell.security/convertto-securestring and ConvertFrom-SecureString https://learn.microsoft.com/powershell/module/microsoft.powershell.security/convertfrom-securestringcmdlet。
首先创建一个安全字符串(在相关计算机/用户帐户下):
Read-Host 'Enter your password' -AsSecureString | ConvertFrom-SecureString
这将返回一个类似的字符串:
01000000d08c9ddf0115d1118c7a00c04fc297eb01000000da4b9d0c09bdb140b3060606f3557e1200000000020000000000106600000001000020000000319f97dca4698fd8848b183e0a7e3fa26127043f68b75ed0ffad6e60eee59201000000000e8000000002000020000000e7f6f6c563f442ef7563967ab907abd528147e1cb8d03efdb4892f29ecbe38d3100000003098dedec04172048148654f5846bbcd40000000d270797bc32ba3d42a217d26dc1395b4bbf4fb4a9f9fe701b98270e1db848de3b048c36a792061fea06e1123b0288d687ffdda2ae934f63f60d58a8c19631007
⚠️警告
SecureString 的内容在非 Windows 系统上未加密。
您可以将此字符串放入环境变量或其他位置,甚至简单地将其嵌入到脚本中:
$EncryptedPassword = '01000000d08c9ddf...
请注意,此字符串只能在特定计算机上由创建该字符串的用户帐户解密$EncryptePassword
。这个限制实际上增加了安全性(也知道每次你使用ConvertFrom-SecureString
命令你会得到一个不同的字符串)。
要在脚本中显示纯文本密码,您可以执行以下操作:
$Password = $EncryptedPassword | ConvertTo-SecureString | ConvertFrom-SecureString -AsPlainText
请注意,您实际上应该尽量避免使用上述命令,因为这会泄露密码并可能留下内存痕迹。因此,至少删除解密的变量是一件好事,例如:Remove-Variable Password
.
加密您的脚本
您甚至可以考虑使用 DPAPI 加密您的整个脚本,包括硬编码的纯密码(这实际上比使用工具更好地保护它)PS2EXE
):
param(
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[string] $Path,
[switch] $AsBase64
)
$Item = Get-Item $Path
if ($Item) {
$OutPath = "$($Item.DirectoryName)\$($Item.BaseName).Protected$($Item.Extension)"
$ScriptBlock = Get-Content -Raw -Path $Path
$Hex = $ScriptBlock | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
if ($AsBase64) {
$Bytes = [byte[]] -split ($Hex -replace '..', '0x$& ')
$Base64 = [Convert]::ToBase64String($Bytes)
Set-Content -Path $OutPath "`$Base64 = '$Base64'"
Add-Content -Path $OutPath '$Bytes = [System.Convert]::FromBase64String($Base64)'
Add-Content -Path $OutPath '$Hex = -Join $Bytes.Foreach{ $_.ToString("x2") }'
}
else {
Set-Content -Path $OutPath "`$Hex = '$Hex'"
}
Add-Content -Path $OutPath '$ScriptBlock = $Hex | ConvertTo-SecureString | ConvertFrom-SecureString -AsPlainText'
Add-Content -Path $OutPath 'Invoke-Expression $ScriptBlock'
Add-Content -Path $OutPath 'Remove-Variable Base64, Bytes, Hex, ScriptBlock -ErrorAction SilentlyContinue'
}
Usage:
.\Protect-Script.ps1 .\MailMessage.ps1 -AsBase64
.\MailMessage.Protected.ps1
再次:.\MailMessage.Encrypted.ps1
脚本仅适用于创建该脚本的计算机和帐户。