如何在PowerShell脚本中填写提示符

8
我使用以下命令:
get-pfxcertificate C:\test.pfx
输入密码: *******
该命令要求我填写提示。但我无法在我的脚本(例如 test.ps1)中执行此操作。
我需要像这样的内容:
get-pfxcertificate C:\test.pfx -password "123456"
或类似的内容,这样我就可以运行我的脚本而不必每次都填写提示。
非常感谢您的回复。
6个回答

21

没有密码参数,您可以尝试使用 .NET 类:

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import('C:\test.pfx','123456','DefaultKeySet')

[void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")[System.Windows.Forms.SendKeys]::SendWait( "123456~" ) - Tran Ngu Dang
那也可以解决问题,但对我来说还不够好,因为如果 get-pfxcertificate 不要求提示符,上述命令将会暴露我的密码。你的解决方案真的很好。非常感谢。 - Tran Ngu Dang
@ngubk,您可以使用Read-Host来提示输入密码。https://dev59.com/b2zXa4cB1Zd3GeqPUohV#30602978 - Chase Florell

6
另一种选择是扩展Get-PfxCertificate的功能,从而实现密码的传递。
# create a backup of the original cmdlet
if(Test-Path Function:\Get-PfxCertificate){
    Copy Function:\Get-PfxCertificate Function:\Get-PfxCertificateOriginal
}

# create a new cmdlet with the same name (overwrites the original)
function Get-PfxCertificate {
    [CmdletBinding(DefaultParameterSetName='ByPath')]
    param(
        [Parameter(Position=0, Mandatory=$true, ParameterSetName='ByPath')] [string[]] $filePath,
        [Parameter(Mandatory=$true, ParameterSetName='ByLiteralPath')] [string[]] $literalPath,

        [Parameter(Position=1, ParameterSetName='ByPath')] 
        [Parameter(Position=1, ParameterSetName='ByLiteralPath')] [string] $password,

        [Parameter(Position=2, ParameterSetName='ByPath')]
        [Parameter(Position=2, ParameterSetName='ByLiteralPath')] [string] 
        [ValidateSet('DefaultKeySet','Exportable','MachineKeySet','PersistKeySet','UserKeySet','UserProtected')] $x509KeyStorageFlag = 'DefaultKeySet'
    )

    if($PsCmdlet.ParameterSetName -eq 'ByPath'){
        $literalPath = Resolve-Path $filePath 
    }

    if(!$password){
        # if the password parameter isn't present, just use the original cmdlet
        $cert = Get-PfxCertificateOriginal -literalPath $literalPath
    } else {
        # otherwise use the .NET implementation
        $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
        $cert.Import($literalPath, $password, $X509KeyStorageFlag)
    }

    return $cert
}

现在你可以调用它了。

# tada: extended cmdlet with `password` parameter
Get-PfxCertificate 'C:\path\to\cert.pfx' 'password'

此外,如果您仍需要提示,则可以执行以下操作。
$pwd = Read-Host 'Please enter your SSL Certificate password.'
Get-PfxCertificate 'C:\path\to\cert.pfx' $pwd

6
现在PowerShell中有一个名为Get-PfxData的命令可用,该命令获取证书和证书链。该命令包括一个-Password参数,接受SecureString对象,因此您可以避免提示输入密码。 EndEntityCertificates属性包含证书链末尾的证书数组,并且将包含Get-PfxCertificate命令创建的同一证书对象。
以下示例将普通字符串转换为SecureString对象,从文件加载证书,然后将第一个/唯一的末尾证书分配给$SigningCert变量:
$SecurePassword=ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force
$PfxData=Get-PfxData -FilePath ".\cert_filename.pfx" -Password $SecurePassword
$SigningCert=$PfxData.EndEntityCertificates[0]

现在可以应用 $SigningCert 而无需输入密码。


哎呀,我刚刚还在苦苦挣扎呢。谢谢!为了让我的评论不至于完全没用,这里有一个一行代码的版本。 (Get-PfxData -FilePath "C:\yada\yada.pfx" -Password (ConvertTo-SecureString -String "MyPassword") -Force -AsPlainText )。EndEntityCertificates [0] - Nicholas McQuillen

2

感谢Shay为我指明了正确的方向。 我的需求是从PFX文件获取Thumbprint,因此我使用了非持久化的DefaultKeySet。 在2012 PS3下进行测试会失败,除非密钥集是完全限定的。 另外,在Import和左括号之间加一个空格,即"$cert.Import^^(Sys..."会导致错误。解析器很挑剔。

我的PFX密码在源代码中被加密。 我在运行时对其进行解密,以便它不在源代码中可见。

Set-StrictMode -Version Latest
[string] $strPW  = '123456'
[string] $strPFX = 'C:\MyCert.pfx'

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($strPFX,$strPW,[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"DefaultKeySet")
$cert.Thumbprint

1

如果你被迫使用Windows Powershell (v5.*),那么线程中的先前解决方案适用于你。

但是,如果你可以使用Powershell 7/Powershell Core,那么它自己的Get-PfxCertificate命令确实有一个-Password参数。

安装Powershell 7并确保使用pwsh而不是powershell后,你可以通过以下方式加载证书:

$certificate = (Get-PfxCertificate <certificate_path>.pfx -Password (ConvertTo-SecureString -String "<password>" -AsPlainText -Force))

-2

这也适用于使用本地 PowerShell 而不是 .NET:

$securePassword = ConvertTo-SecureString -String $strPW -Force -AsPlainText
$cert = Import-PfxCertificate -FilePath $strPFX cert:\LocalMachine\My -Password $securePassword

OP没有使用Import,而是使用了默认情况下没有密码参数的get - Chase Florell
确实,这个答案很令人困惑。PowerShell 3.0的本地Get-PfxCertificate Cmdlet在.pfx文件上提供了很多功能,但不允许将密码作为SecureString传递。这个答案是关于PKI模块的Import-PfxCertificate CmdLet,它接受一个密码参数,但相比之下缺乏功能。 - flip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接