2010-05-28 212 views
4

我正在使用SslStream进行SSL3握手,但尽管我尽了最大的努力,SslStream从不以我的名义发送客户端证书。下面是代码:无法通过SslStream发送客户端证书

SSLConnection = new System.Net.Security.SslStream(SSLInOutStream, false, new System.Net.Security.RemoteCertificateValidationCallback(AlwaysValidRemoteCertificate), new System.Net.Security.LocalCertificateSelectionCallback(ChooseLocalCertificate)); 

X509CertificateCollection CC = new X509CertificateCollection(); 
CC.Add(Org.BouncyCastle.Security.DotNetUtilities.ToX509Certificate(MyLocalCertificate)); 

SSLConnection.AuthenticateAsClient("test", CC, System.Security.Authentication.SslProtocols.Ssl3, false); 

,然后我有AlwaysValidRemoteCertificate刚刚返回true,并ChooseLocalCertificate返回数组的零元素。

该代码可能看起来有点奇怪,因为该项目有点奇怪,但我认为这是在这里旁边。 SSL握手完成。问题在于,代替使用ASN.1编码证书(MyLocalCertificate)代替我(在握手过程中)发送证书消息,SslStream发送SSL警报号码41(无证书),然后继续。我从包嗅探中知道这一点。握手完成后,SslStream将IsAuthenticated标记为true,IsMutuallyAuthenticated为false,并且其LocalCertificate成员为空。

我觉得我可能在这里错过了一些非常明显的东西,所以任何想法将不胜感激。我是一个SSL的新手,这个项目不在我们的路上,所以我有点不知所措。

P.S. 1:我的ChooseLocalCertificate例程在握手期间被调用两次,并返回一个有效的(据我所知),两次都是非空的证书。

P.S. 2:SSLInOutStream是我自己的类,不是NetworkStream。就像我说的那样,握手大部分都是正常进行的,所以我怀疑这是罪魁祸首......但谁知道呢?

+0

请提供API文档的链接。 – erickson 2010-05-28 22:35:54

回答

5

我不熟悉用于SSL的Bouncycastle .NET API,但首先看,我猜你没有提供API的私钥。

即使私钥本身从未发送到服务器,也需要对某些数据进行数字签名,以便向服务器证明您拥有它。应该有一些API为此签名操作提供私钥。

7

出于某种原因,网站不会让我对上面发布的解决方案发表评论,但它解决了我的问题。这是我的评论:

嘿,这是一个伟大的猜测,它解决了我的问题。非常感谢你。 C#X509Certificate类似乎不支持设置私钥,但子类X509Certificate2却支持。我不得不猴子周围BouncyCastle的东西一点,但执行(如果有人需要它的未来)是这样的:

X509CertificateCollection CC = new X509CertificateCollection(); 
X509Certificate2 C2 = new X509Certificate2(MyLocalCertificate.GetEncoded()); 
C2.PrivateKey = Org.BouncyCastle.Security.DotNetUtilities.ToRSA((Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)MyPrivateKey.Private); 
CC.Add(C2); 

MyLocalCertificate是BouncyCastle的的X509Certificate类的一个实例,MyPrivateKey是BouncyCastle的的AsymmetricCipherKeyPair的实例。