如何使用BouncyCastle生成可用于WCF身份验证的X509Certificate2?

时间:2012-02-12 16:04:16

标签: c# wcf security x509certificate bouncycastle

这是我的WCF服务代码:

        ServiceHost svh = new ServiceHost(typeof(MyClass));

        var tcpbinding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential, true);
        //security

        tcpbinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
        svh.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new BWUserNamePasswordValidator();
        svh.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =UserNamePasswordValidationMode.Custom;
        svh.Credentials.ServiceCertificate.Certificate = GenerateCertificate(myCert);

        svh.AddServiceEndpoint(typeof(IMyClass), tcpbinding, location);            

        svh.Open();

这是代码,我用它来生成证书:

    static X509Certificate2 GenerateCertificate(string certName)
    {
        var keypairgen = new RsaKeyPairGenerator();
        keypairgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));

        var keypair = keypairgen.GenerateKeyPair();

        var gen = new X509V3CertificateGenerator();

        var CN = new X509Name("CN=" + certName);
        var SN = BigInteger.ProbablePrime(120, new Random());

        gen.SetSerialNumber(SN);
        gen.SetSubjectDN(CN);
        gen.SetIssuerDN(CN);
        gen.SetNotAfter(DateTime.MaxValue);
        gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
        gen.SetSignatureAlgorithm("MD5WithRSA");
        gen.SetPublicKey(keypair.Public);

        gen.AddExtension(X509Extensions.SubjectKeyIdentifier, false,
                    new SubjectKeyIdentifierStructure(keypair.Public));        

        var newCert = gen.Generate(keypair.Private);

        return new X509Certificate2(DotNetUtilities.ToX509Certificate((Org.BouncyCastle.X509.X509Certificate)newCert));
    }

当我启动服务器时,它会崩溃并出现以下异常:

ArgumentException: It is likely that certificate 'CN=MyCert' may not 
have a private key that is capable of key exchange or the process may not have 
access rights for the private key. Please see inner exception for detail.

内部异常为空。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

需要为此目的明确创建用于证书交换的密钥对。我认为您只需要在证书生成器中添加另一个扩展名,如下所示:

gen.AddExtension(
    X509Extensions.KeyUsage, 
    true,
    new KeyUsage(KeyUsage.keyCertSign));

不确定该语法是否完全正确,但这是个想法:您需要将证书中的密钥用作证书签名,如果存在,那么这是一个“关键”扩展。