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

49 IT屋

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.

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

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?

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

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.

解决方案

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. Run mmc (e.g. from the Start menu)
  2. File menu > Add/Remove Snap-in
  3. Select "Certificates" in left pane and then click Add
  4. Select "Computer Account" (for LocalMachine) then click Next, and then Finish

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.

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.

Edit: 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.Crypto dll创建证书,然后将该证书用于在Windows Service进程中以服务器身份验证SslStream,该服务器在本地系统帐户下运行。



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



关于此错误消息,这里有几个问题,但似乎都无法描述或解决我的特定问题。



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



  //首先使用BouncyCastle类创建一个证书
BigInteger serialNumber = BigInteger.ProbablePrime(120,new Random());
AsymmetricCipherKeyPair keyPair = GenerateKeyPair();

X509V1CertificateGenerator生成器=新的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"));

//好,现在我们有了BouncyCastle证书,我们需要将其写到磁盘上并重新加载$ ​​b $,以将其转换为
// System.Security.Cryptography类b X509Certificate2 dotNetCert;

字符串tempStorePassword =" Password01"; //在现实生活中,我会使用随机密码
FileInfo tempStoreFile = new FileInfo(Path.GetTempFileName());

试试
{
Pkcs12Store newStore = new Pkcs12Store();

X509CertificateEntry条目=新的X509CertificateEntry(cert);

newStore.SetCertificateEntry(Environment.MachineName,entry);

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

使用(FileStream s = tempStoreFile.Create())
{
newStore.Save(s,
tempStorePassword.ToCharArray(),
新的SecureRandom (新的CryptoApiRandomGenerator()));
}

//从磁盘
重新加载证书dotNetCert = new X509Certificate2(tempStoreFile.FullName,tempStorePassword);
}
最终
{
tempStoreFile.Delete();
}

//现在将其安装到所需的证书存储区中
X509Store targetStore = new X509Store(StoreName.My,StoreLocation.LocalMachine);
targetStore.Open(OpenFlags.ReadWrite);
targetStore.Add(dotNetCert);
targetStore.Close();


好,现在我已经创建并安装了证书。然后,通过为Windows服务提供生成的证书的指纹,将其配置为使用此证书。然后,我使用这样的证书:



  //首先加载证书
X509Certificate2 certificate = null;

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

foreach(商店中的X509Certificate2 certInStore.Certificates)
{
if(certInStore.Thumbprint ==" ...未显示值...")
{
证书= certInStore;
休息时间;
}
}

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

//现在,此行引发Win32Exception
//"无法识别提供给软件包的凭据"
sslStream.AuthenticateAsServer(certificate);


有人知道这个问题在哪里吗?



如果我安装了使用'makecert'创建的证书,我不会遇到问题,但这不适用于生产证书。



I还尝试创建单独的x509v1 CA证书,然后创建用于服务器身份验证的x509v3证书,但是我遇到了相同的错误,因此为了简单起见,我在示例代码中将其删除。


解决方案

该特定错误消息响起了钟声。我想您可能没有将私钥与证书一起存储,或者Windows服务无法访问私钥。要检查这一点,请打开"证书" MMC管理单元:




  1. 运行mmc(例如,从"开始"菜单)

  2. "文件"菜单>"添加/删除管理单元"

  3. 在左窗格中选择"证书",然后单击"添加"

  4. 选择"计算机帐户" "(对于LocalMachine),然后依次单击"下一步",
    和"完成"



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



如果存在私钥 ,请单击"确定"关闭此对话框,然后右键单击右窗格中的证书,然后在弹出菜单上选择:所有任务>管理私钥。在该对话框中,确保运行该服务的Windows帐户具有对私钥的读取权限。



编辑:糟糕,您写道该服务作为本地系统运行,因此它必须是缺少的私钥(如果有)是这两个问题之一。无论如何,我都会将密钥访问检查留在我的答案中,以供其他任何遇到此问题且未作为本地系统运行的人使用。


本文地址:IT屋 » “无法识别提供给软件包的凭证”。使用BouncyCastle生成的证书作为服务器身份验证时出错