2011-11-02 58 views
9

我试图创建使用BouncyCastle.Crypto DLL,然后将其用于对认证SslStream作为服务器的证书时产生“供给到封装体的凭证无法识别”错误在Windows服务进程中,在本地系统帐户下运行。与证书服务器验证使用BouncyCastle的

但是,当我到达SslStream.AuthenticateAsServer(证书)调用时,它会抛出一个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服务器身份验证证书,但我得到了同样的错误,所以我在简单的示例代码移除了这个。

回答

0

我不记得这个错误,但要创建的证书不是用于SSL/TLS有效的,包括:

  • V1(非V3)证书;
  • 缺失扩展名;
  • 无效CN;
  • ...

有几个RFC谈到有关这一点,包括RFC5246在TLS(1.2)。

最后使你自己证书并不比使用makecert所做的那些(但最后一个可以产生最低设置为一个SSL/TLS服务器证书使用)更适合

强烈建议你买,从已知的证书颁发机构(CA)的好,一个SSL/TLS证书生产。这将使您获得大多数浏览器和工具认可的工作证书。

+0

我尝试将我的v1证书生成器更改为v3版本,但将n ovail。我们不可能购买证书 - 我们将在安装时为我们的服务生成证书。显然,它不会有可信的认证路径,但仍然允许我们在传输数据时对其进行加密。 –

+0

我不认为你可以提供有关'缺少扩展名'和'无效CN'的含义的更多细节吗? –

+0

属于“可以写一本书”(参见FAQ)类别;-)您可以通过查看“makecert”(或来自网站的任何SSL证书)的内部内容来获得**最小**猜测制作。很多垃圾(可悲的),但浏览器也接受它们。 – poupou

17

该特定错误消息响起。我猜你要么没有将证书存储在私钥中,要么Windows服务不能访问私钥。要检查此问题,请打开证书MMC管理单元:

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

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

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

编辑:哎呀,你写道服务作为本地系统运行,所以它必须是缺少的私钥,如果它是这两个问题之一。无论如何,我将在我的答案中留下关键访问检查,对于任何其他碰到此问题的人,并且不以本地系统身份运行。

+0

嗯,我不认为这是其中一个问题 - 我肯定有一个私钥对应证书(我可以看到你描述的图标和文本) 。我尝试进入“管理私钥”对话框并授予每个人完全控制证书,但我仍然得到相同的错误。 –

+0

检查此答案,看看它是否有帮助:http://stackoverflow.com/questions/2322560/certificate-problem-with-a-new-machine-credentials-supplied-to-package-not-rec –

+0

另一件尝试将第三个X509KeyStorageFlags参数添加到“新的X509Certificate2(...)”中,例如X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet,只是为了确保将其保存到商店时,所有内容都能正确排列。 –

6

在网上找到了这个解决方案,但我找不到信用来源。

由于我遇到了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对象直接保存到密钥存储区。我不需要实际的文件,所以我跳过了这一步。

+0

这个答案对我非常有帮助。不知道为什么DotNetUtilities转换不能正常工作,但这解决了我的问题,同样的错误!谢谢! –

5

有时,如果应用程序尝试访问证书时没有足够的权限访问证书,则可以通过以管理员身份运行应用程序来解决问题。

+0

谢谢,这对我来说诀窍 –

+0

希望我能两次加注这个,这让我几个月后烧了我,并且今天又烧了我一次,这个答案在两个场合都有所帮助。 – Sully

0

此前,每次遇到此问题时,我都必须从本地机器证书存储区中删除证书,然后重新导入证书。然后这一切似乎都很开心。如果仅仅重新导入它就可以解决问题,我无法看到它可能是全局权限问题还是无效证书。

我如何最终解决它是使用Windows资源工具包中的winhttpcertcfg工具向正在使用该证书的特定用户授予权限。

的语法是:

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

我打电话从.NET应用程序中的WCF REST服务,我需要连接客户端证书时有类似的问题;我所要做的只是在证书存储区[mmc控制台]中提供对“NETWORKSERVICE”off课程的访问权限,我的IIS Pool是默认池,表示使用NETWORKService用户帐户。

我做的错误是,我将另一家商店的证书复制到本地 机器 - >证书受密码保护的人员商店应该在所需商店中明确导入证书

1

对于我在Windows Server 2012 R2(.net 4.6.1 ) - “所有任务>管理私钥”并将访问权设置为Everyone(设置为IS_IUSRS是不够的)