“无法识别提供给包的凭据"使用 BouncyCastle 生成的证书作为服务器进行身份验证时出错 [英] "The credentials supplied to the package were not recognized" error when authenticating as server with certificate generated using BouncyCastle

查看:70
本文介绍了“无法识别提供给包的凭据"使用 BouncyCastle 生成的证书作为服务器进行身份验证时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 BouncyCastle.Crypto dll 创建证书,然后使用该证书将 SslStream 验证为 Windows 服务进程中的服务器,该进程在本地系统帐户下运行.

I'm trying to create a certificate using the BouncyCastle.Crypto dll, which is then used to authenticate a SslStream as the server in a Windows Service process, which runs under the Local System account.

但是,当我调用 SslStream.AuthenticateAsServer(certificate) 时,它会引发 Win32 异常并显示错误消息无法识别提供给包的凭据".

However when I get to the SslStream.AuthenticateAsServer(certificate) call, it throws a Win32 exception with the error message "The credentials supplied to the package were not recognized".

这里有几个关于此错误消息的问题,但似乎没有一个能描述或解决我的特定问题.

There are several questions on here about this error message, but none of them seem to describe, or solve, my particular problem.

希望有人能够提供一些帮助,我包含了用于创建和安装证书的代码:

In the hope that someone may be able to offer some help, I include the code I am using to create and install the certificate:

// 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 服务以使用该证书.然后我像这样使用证书:

Ok, now I have created and installed the certificate. I then configure my Windows Service to use this certificate by supplying it with the generated certificate's thumbprint. I then use the certificate like this:

// 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);

有人知道这里可能有什么问题吗?

Does anyone have any idea what the problem could be here?

如果我安装了使用makecert"创建的证书,则不会出现问题,但这不适用于生产证书.

I don't get the problem if I install a certificate created with 'makecert', but that isn't suitable for production certificates.

我还尝试创建一个单独的 x509v1 CA 证书,然后创建 x509v3 证书用于服务器身份验证,但我遇到了同样的错误,所以为了简单起见,我在示例代码中删除了它.

I've also tried creating a separate x509v1 CA certificate and then x509v3 certificate for server authentication, but I get the same error, so I removed this in the example code for simplicity.

推荐答案

该特定错误消息敲响了警钟.我猜要么您没有将私钥与证书一起存储,要么 Windows 服务无权访问私钥.要检查这一点,请打开证书 MMC 管理单元:

That particular error message rings a bell. I'll guess that either you did not store the private key with the certificate, or, the Windows service does not have access to the private key. To check this, open the Certificates MMC snap-in:

  1. 运行 mmc(例如从开始菜单)
  2. 文件菜单 > 添加/删除管理单元
  3. 在左侧窗格中选择证书",然后单击添加"
  4. 选择计算机帐户"(对于本地机器),然后单击下一步,然后完成

导航到证书并在右侧窗格中双击.在出现的常规"选项卡上,您应该在底部看到一个小钥匙图标,以及您有一个与此证书对应的私钥"的文本.如果没有,那就是问题所在.私钥未保存.

Navigate to the certificate and double-click in the right pane. On the General tab that comes up, you should see a little key icon at the bottom, along with the text, "You have a private key that corresponds to this certificate." If not, that's the problem. The private key was not saved.

如果私钥存在,单击确定关闭此对话框,然后右键单击右窗格中的证书并在弹出菜单中选择:所有任务 > 管理私有钥匙.在该对话框中,确保运行该服务的 Windows 帐户具有对私钥的读取访问权限.如果没有,那就是问题所在.

If the private key is present, click Ok to dismiss this dialog, and then right-click on the certificate in the right pane and select on the pop-up menu: All Tasks > Manage Private Keys. In that dialog, make sure that the Windows account that the service runs under has read access to the private key. If it doesn't, that's the problem.

哎呀,你写的服务作为本地系统运行,所以它一定是缺少私钥,如果它是这两个问题之一.无论如何,我会将密钥访问检查留在我的答案中,对于其他任何遇到此问题且未作为本地系统运行的人.

Oops, you wrote that the service runs as Local System, so it must be a missing private key, if it is one of these two problems. I'll leave the key access check in my answer anyway, for anybody else that hits this and is not running as Local System.

这篇关于“无法识别提供给包的凭据"使用 BouncyCastle 生成的证书作为服务器进行身份验证时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆