Powershell 导入带有私钥的证书

Powershell 导入带有私钥的证书,powershell,x509certificate,pfx,Powershell,X509certificate,Pfx,我正在尝试导入一个带有私钥的证书,尽管我的脚本正在“工作”,但它缺少一些我似乎无法理解的东西 我有一个与KeyVault对话的应用程序,并使用此证书进行授权。我有所述证书的密码,当我手动安装PFX并分配网络服务帐户权限时,这一切正常。但是,使用下面的PowerShell,我得到错误键集不存在。当我在cert manager下检查时,一切似乎都正常。显然,UI正在做一些不同的事情。。有什么想法吗 编辑 当我手动添加网络服务帐户时,效果很好。当我执行脚本时,PowerShell正在管理模式下运行,所

我正在尝试导入一个带有私钥的证书,尽管我的脚本正在“工作”,但它缺少一些我似乎无法理解的东西

我有一个与KeyVault对话的应用程序,并使用此证书进行授权。我有所述证书的密码,当我手动安装
PFX
并分配
网络服务
帐户权限时,这一切正常。但是,使用下面的PowerShell,我得到错误
键集不存在
。当我在cert manager下检查时,一切似乎都正常。显然,UI正在做一些不同的事情。。有什么想法吗

编辑 当我手动添加
网络服务
帐户时,效果很好。当我执行脚本时,PowerShell正在管理模式下运行,所以这可能有些奇怪

剧本

cls
$certName = "certname.pfx"
$path = "C:\Certificates\$certName"
$serviceAccount = 'NETWORK SERVICE'
$permissionType = 'Read'
$password = 'somepassword'

try {
    # Import the certificate maintaining the private key format
    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
    $cert.Import($path, $password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")

    # Add the cert to personal store location
    $store = Get-Item Cert:\LocalMachine\My
    $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]"ReadWrite")
    $store.Add($cert)
    $store.Close()

    # Get SecurityIdentifier value from current username
    $currentUser = New-Object System.Security.Principal.NTAccount($env:USERNAME)
    $strSID = $currentUser.Translate([System.Security.Principal.SecurityIdentifier])
    $path = "$env:USERPROFILE\AppData\Roaming\Microsoft\Crypto\RSA\$($strSID.Value)\$($cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
    $acl = Get-Acl $path
    $rule = New-Object Security.AccessControl.FileSystemAccessRule $serviceAccount, 'FullControl', Allow
    $acl.AddAccessRule($rule)
    Set-Acl $path $acl

    Write-Host "Cert installed, press any key to continue" -ForegroundColor Green
    Read-Host
}
catch {
    Write-Error -Message $_
}
回答 对于遇到与我相同问题的其他人,只需提供多个存储标志:

$flags = @([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"MachineKeySet", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($path, $password, $flags)
您可能希望同时使用
PersistKeySet
MachineKeySet
导入证书。看看你在这里是怎么做的

  • 打开PFX,但不指定用户与机器键集
  • 将其添加到
    LocalMachine
    存储中
  • 在当前用户的SID下查找密钥文件
Windows证书存储区AFAIK不会记录哪个用户拥有密钥,只是该证书与“用户密钥{id}”配对。所以它需要是机器(共享)密钥存储

“密钥集不存在”是因为网络服务用户的密钥库中没有使用该ID命名的密钥

因此,区别可能在于,UI正在断言
MachineKeySet
(等效),因为它知道您正在导入本地机器存储。

您可能希望同时使用
PersistKeySet
MachineKeySet
导入证书。看看你在这里是怎么做的

  • 打开PFX,但不指定用户与机器键集
  • 将其添加到
    LocalMachine
    存储中
  • 在当前用户的SID下查找密钥文件
Windows证书存储区AFAIK不会记录哪个用户拥有密钥,只是该证书与“用户密钥{id}”配对。所以它需要是机器(共享)密钥存储

“密钥集不存在”是因为网络服务用户的密钥库中没有使用该ID命名的密钥


因此,可能不同之处在于,UI正在断言
MachineKeySet
(等效),因为它知道您正在导入本地机器存储。

在哪里得到错误?当我运行应用程序时。脚本执行良好,但我没有正确添加网络服务帐户,因为当我手动添加网络服务帐户时,它会起作用。是的,但哪一行/哪一步?上面的脚本确实有效,只有当我尝试使用网络服务帐户运行我的应用程序时,它才会失败,并出现错误“Keyset not exist”.你从哪里得到错误?当我运行应用程序时。脚本执行良好,但我没有正确添加网络服务帐户,因为当我手动添加网络服务帐户时,它会起作用。是的,但哪一行/哪一步?上面的脚本确实有效,只有当我尝试使用网络服务帐户运行我的应用程序时,它才会失败,并出现错误“Keyset not exist”。