web-dev-qa-db-ja.com

BouncyCastleを使用して生成された証明書でサーバーとして認証する際の「パッケージに提供された資格情報が認識されませんでした」エラー

BouncyCastle.Crypto dllを使用して証明書を作成しようとしています。これは、ローカルシステムアカウントで実行されるWindowsサービスプロセスでサーバーとしてSslStreamを認証するために使用されます。

ただし、SslStream.AuthenticateAsServer(certificate)呼び出しに到達すると、Win32例外がスローされ、「パッケージに提供された資格情報が認識されませんでした」というエラーメッセージが表示されます。

このエラーメッセージに関するいくつかの質問がありますが、どれも私の特定の問題を説明または解決しているようには見えません。

誰かが何らかの助けを提供できるようになることを期待して、証明書の作成とインストールに使用しているコードを含めます。

// First create a certificate using the BouncyCastle classes
BigInteger serialNumber = BigInteger.ProbablePrime(120, new Random());
AsymmetricCipherKeyPair keyPair = GenerateKeyPair();

X509V1CertificateGenerator generator = new X509V1CertificateGenerator();
generator.SetSerialNumber(serialNumber);
generator.SetIssuerDN(new X509Name("CN=My Issuer"));
generator.SetNotBefore(DateTime.Today);
generator.SetNotAfter(DateTime.Today.AddYears(100));
generator.SetSubjectDN(new X509Name("CN=My Issuer"));
generator.SetPublicKey(keyPair.Public);
generator.SetSignatureAlgorithm("SHA1WITHRSA");

Org.BouncyCastle.X509.X509Certificate cert = generator.Generate(
    keyPair.Private, SecureRandom.GetInstance("SHA1PRNG"));

// Ok, now we have a BouncyCastle certificate, we need to convert it to the 
// System.Security.Cryptography class, by writing it out to disk and reloading
X509Certificate2 dotNetCert;

string tempStorePassword = "Password01"; // In real life I'd use a random password
FileInfo tempStoreFile = new FileInfo(Path.GetTempFileName());

try
{
    Pkcs12Store newStore = new Pkcs12Store();

    X509CertificateEntry entry = new X509CertificateEntry(cert);

    newStore.SetCertificateEntry(Environment.MachineName, entry);

    newStore.SetKeyEntry(
        Environment.MachineName,
        new AsymmetricKeyEntry(keyPair.Private),
        new [] { entry });

    using (FileStream s = tempStoreFile.Create())
    {
        newStore.Save(s, 
            tempStorePassword.ToCharArray(), 
            new SecureRandom(new CryptoApiRandomGenerator()));
    }

    // Reload the certificate from disk
    dotNetCert = new X509Certificate2(tempStoreFile.FullName, tempStorePassword);
}
finally
{
    tempStoreFile.Delete();
}

// Now install it into the required certificate stores
X509Store targetStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
targetStore.Open(OpenFlags.ReadWrite);
targetStore.Add(dotNetCert);
targetStore.Close();

さて、証明書を作成してインストールしました。次に、生成した証明書の拇印を指定して、この証明書を使用するようにWindowsサービスを構成します。次に、次のような証明書を使用します。

// First load the certificate
X509Certificate2 certificate = null;

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

foreach (X509Certificate2 certInStore in store.Certificates)
{
    if (certInStore.Thumbprint == "...value not shown...")
    {
        certificate = certInStore;
        break;
    }
}

SslStream sslStream = new SslStream(new NetworkStream(socket, false), false);

// Now this line throws a Win32Exception 
// "The credentials supplied to the package were not recognized"
sslStream.AuthenticateAsServer(certificate);

誰かがここで問題が何であるか考えていますか?

「makecert」で作成した証明書をインストールしても問題は発生しませんが、これは製品証明書には適していません。

また、サーバー認証用に別のx509v1 CA証明書を作成し、次にx509v3証明書を作成しようとしましたが、同じエラーが発生するため、簡単にするためにサンプルコードでこれを削除しました。

30
peter reay

その特定のエラーメッセージはベルを鳴らします。証明書に秘密キーを保存していないか、Windowsサービスが秘密キーにアクセスできないようです。これを確認するには、証明書を開きますMMCスナップイン:

  1. Mmcを実行します(たとえば、[スタート]メニューから)
  2. [ファイル]メニュー> [スナップインの追加と削除]
  3. 左側のペインで[証明書]を選択し、[追加]をクリックします
  4. [コンピューターアカウント](LocalMachineの場合)を選択し、[次へ]をクリックして、[完了]をクリックします

証明書に移動し、右側のペインをダブルクリックします。表示される[全般]タブの下部に、「この証明書に対応する秘密キーがあります。」というテキストと共に小さなキーアイコンが表示されます。そうでない場合は、それが問題です。秘密鍵は保存されませんでした。

秘密キーisが存在する場合は、Okをクリックしてこのダイアログを閉じ、右側のペインで証明書を右クリックしてポップアップメニューを選択します:[すべてのタスク]> [秘密キーの管理]そのダイアログで、サービスを実行するWindowsアカウントに秘密キーへの読み取りアクセス権があることを確認します。そうでない場合は、それが問題です。

編集:おっと、サービスはローカルシステムとして実行されるので、これらの2つの問題のいずれかである場合は、秘密鍵が欠落している必要があります。とにかく、これにヒットしてローカルシステムとして実行されていない他の人のために、キーアクセスチェックを私の回答に残しておきます。

41
Jim Flood

アプリケーションが証明書にアクセスしようとするときに、証明書にアクセスするための十分な権限がない場合に問題が発生することがあります。アプリケーションを管理者として実行すると、問題が解決する場合があります。

11
Bruce

このソリューションはオンラインで見つかりましたが、クレジットを提供するためのソースが見つかりません。

AuthenticateAsClient()(クライアント検証用)で「パッケージに提供された資格情報が認識されなかった」という問題に遭遇したので、解決方法を文書化したいと思います。同じ最終目標を持つ別の方法です。 AuthenticateAsServer()には便利かもしれないので、なぜそうでないのかを考えました。

ここでは、BC証明書を.NET証明書に変換します。これを.NET X509Certificate2に変換して、PrivateKeyプロパティを格納するための追加の手順を追加します。

Org.BouncyCastle.X509.X509Certificate bcCert;

X509Certificate dotNetCert = DotNetUtilities.ToX509Certificate(bcCert);
X509Certificate2 dotNetCert2 = new X509Certificate2(dotNetCert);

BouncyCastle秘密鍵を.NET秘密鍵に追加するときに問題が発生しました。 X509証明書は正常に変換されましたが、秘密鍵は変換されませんでした。提供されたDotNetUtilitiesを使用して、BCプライベートキーをRSACryptoServiceProviderに変換しました。残念ながら、変換が完了していないようです。そこで、別のRSACryptoServiceProviderを作成し、それを初期化しました。次に、作成した秘密鍵を秘密鍵にインポートしました。

// Apparently, using DotNetUtilities to convert the private key is a little iffy. Have to do some init up front.
RSACryptoServiceProvider tempRcsp = (RSACryptoServiceProvider)DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)ackp.Private);
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider(new CspParameters(1, "Microsoft Strong Cryptographic Provider", 
            new Guid().ToString(), 
            new CryptoKeySecurity(), null));

rcsp.ImportCspBlob(tempRcsp.ExportCspBlob(true));
dotNetCert2.PrivateKey = rcsp;

その後、X509Certificate2オブジェクトを直接キーストアに保存することができました。実際のファイルは必要なかったので、そのステップはスキップしました。

6
Miguel Moll

私は同じ問題を抱えており、多くの投稿からすべてを試し、グーグルリサーチを行った。しかし、私は修正を見つけたようです。 IdentifyApplicationPoolIdentityからLocalSystemに変更すると、すべてが完全に機能し始めます。

誰かの役に立つかもしれません。

3
rootnix911

私にとってWindows Server 2012 R2(.net 4.6.1)-「すべてのタスク>秘密鍵の管理」で動作し、アクセス権をEveryoneに設定します(IS_IUSRSへの設定では不十分)

2
MariuszW

クライアント証明書を添付する必要がある.NETアプリケーションからWCF RESTサービスを呼び出すときにも同様の問題がありました。必要なことは、証明書ストアの証明書へのアクセスを提供することだけです[mmc console ] "NETWORKSERVICE"オフコースmy IISプールは、NETWORKServiceユーザーアカウントの使用を示すデフォルトのプールでした。

私がした間違いは、証明書を別のストアからローカルマシン->証明書がパスワードで保護されている人事ストアにコピーしたことです。証明書を必要なストアに明示的にインポートする必要があります。

1
user3264937

以前は、この問題に遭遇するたびに、ローカルマシンの証明書ストアから証明書を削除して再インポートする必要がありました。それからそれはすべて幸せそうです。単にインポートするだけで問題が修正される場合、グローバルなアクセス許可の問題や無効な証明書である可能性があることを確認できません。

最後に修正した方法は、Windowsリソースキットの winhttpcertcfg ツールを使用して、証明書を使用していた特定のユーザーに権限を付与することでした。

構文は次のようになります。

"C:\Program Files (x86)\Windows Resource Kits\Tools\winhttpcertcfg" -i cert.p12 -c LOCAL_MACHINE\My -a UserWhoUsesTheCert -p passwordforp12
1
NitrusCS

このエラーは覚えていませんが、作成している証明書はSSL/TLSに使用するには有効ではありません。

  • v1(v3ではない)証明書。
  • 拡張子がありません。
  • 無効なCN;
  • ...

TLS(1.2)で RFC5246 を含む、これについて説明するRFCがいくつかあります。

最後にown証明書を作成することは、makecertによって作成された証明書を使用するよりも適切ではありません(ただし、最後の証明書は最小値を生成できます) SSL/TLSサーバー証明書に使用できるように設定します)。

私は強くよく知られている認証局(CA)からのSSL/TLS証明書を購入することをお勧めします生産。これにより、ほとんどのブラウザーとツールで認識される有効な証明書が得られます。

0
poupou