6

次の PowerShell 関数を使用して、PFX を Windows 2008 R2 サーバーの証明書ストアにインポートしました

function Import-PfxCertificate ([String]$certPath,[String]$certificateStoreLocation = "CurrentUser",[String]$certificateStoreName = "My",$pfxPassword = $null)
{
    $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2    

    $pfx.Import($certPath, $pfxPassword, "Exportable,PersistKeySet")    

    $store = new-object System.Security.Cryptography.X509Certificates.X509Store($certificateStoreName,$certificateStoreLocation)    
    $store.open("MaxAllowed")    
    $store.add($pfx)    
    $store.close()
    return $pfx
}

関数の呼び出し元は、$importedPfxCert = Import-PfxCertificate $pfxFile "LocalMachine" "My" $passwordローカル マシンのマイ ストアにインストールしたようです。次に、IIS アプリケーション プールに読み取りアクセス許可を付与しました。

それを使用する必要があるWCFサービスがあります

<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceCredentials>
        <serviceCertificate findValue="MyCertName" x509FindType="FindBySubjectName" />
        <userNameAuthentication userNamePasswordValidationMode="Custom"
          customUserNamePasswordValidatorType="MyValidator" />
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

クライアントを使用してサービスを呼び出すと、WCF から例外が発生しましたIt is likely that certificate 'CN=MyCertName' may not have a private key that is capable of key exchange or the process may not have access rights for the private key.

MMC から削除し、証明書 MMC から同じ PFX ファイルを手動でインポートして、同じストアに同じアクセス許可を付与すると、クライアントは問題なくサービスを呼び出すことができます。

ですから、PowerShellを使用すると、何らかの理由で秘密鍵がねじ込まれていると思います。

おもしろいことに、MMC に移動して、インストール済みの証明書をダブルクリックするとYou have a private key that corresponds to the certificate.、PowerShell でも秘密鍵が読み込まれているように見えます。パーミッション設定は同じです。

手がかりや経験はありますか?

4

5 に答える 5

5

同じ問題があります。次のスクリプト作業:

function InstallCert ($certPath, [System.Security.Cryptography.X509Certificates.StoreName] $storeName)
{
    [Reflection.Assembly]::Load("System.Security, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")

    $flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet

    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath, "", $flags)

    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)

    $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite);

    $store.Add($cert);

    $store.Close();
}
于 2013-05-23T10:59:14.310 に答える
2

Sergeyの回答を次のように更新しました。このusing namespace ...構文は PS 5.0 以降でのみ有効であることに注意してください。以前のバージョンでこれが必要な場合は、必要に応じて完全な名前空間 を追加するSystem.Security.Cryptography.X509Certificates必要があります。

using namespace System.Security

[CmdletBinding()]
param (
    [parameter(mandatory=$true)] [string] $CertificateFile,
    [parameter(mandatory=$true)] [securestring] $PrivateKeyPassword,
    [parameter(mandatory=$true)] [string] $AllowedUsername
)

# Setup certificate
$Flags = [Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet `
    -bor [Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet `
    -bor [Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$Certificate = New-Object Cryptography.X509Certificates.X509Certificate2($CertificateFile, $PrivateKeyPassword, $Flags)

# Install certificate into machine store
$Store = New-Object Cryptography.X509Certificates.X509Store(
    [Cryptography.X509Certificates.StoreName]::My, 
    [Cryptography.X509Certificates.StoreLocation]::LocalMachine)
$Store.Open([Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$Store.Add($Certificate)
$Store.Close()

# Allow read permission of private key by user
$PKFile = Get-ChildItem "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$($Certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
$PKAcl = $PKFile.GetAccessControl("Access")
$ReadAccessRule = New-Object AccessControl.FileSystemAccessRule(
    $AllowedUsername,
    [AccessControl.FileSystemRights]::Read,
    [AccessControl.AccessControlType]::Allow
)
$PKAcl.AddAccessRule($ReadAccessRule)
Set-Acl $PKFile.FullName $PKAcl

このスクリプトをInstallCertificate.ps1に保存し、管理者として実行します。

PS C:\Users\me> .\InstallCertificate.ps1

cmdlet InstallCertificate.ps1 at command pipeline position 1
Supply values for the following parameters:
CertificateFile: c:\my\path\mycert.pfx
PrivateKeyPassword: *********************
AllowedUsername: me
PS C:\Users\me> ls Cert:\LocalMachine\My
<Observe that your cert is now listed here.  Get the thumbprint>
PS C:\Users\me> (ls Cert:\LocalMachine\My | ? { $_.Thumbprint -eq $Thumbprint }).PrivateKey

再起動後、管理者以外でも秘密鍵がインストールされていることが最後の行に表示されます。

https://stackoverflow.com/a/37402173/7864889で説明されているように、ACL ステップを追加するように編集しました。

于 2017-04-14T00:40:06.630 に答える
0

以下で参照されている Sergey Azarkevich による次のコードは、私のためにトリックを行ったものです。

$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
于 2014-04-04T23:33:15.617 に答える
0

MMC を介して証明書をインポートするときに、開発サーバーの 1 つで同様の問題が発生しました。私の問題は、Administrators グループが MachineKeys フォルダーに対するアクセス許可を持っていなかったことです。

C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys

MachineKeys フォルダーのフル コントロールを管理者に追加したところ、証明書のインポート時に秘密キーを正常に作成できました。

Powershell を実行しているユーザーに、MachineKeys フォルダーへの書き込みアクセス権があることを確認してください。

于 2014-04-01T22:39:16.340 に答える