2012-02-12 3 views
1

Вот мой код WCF службы:Как использовать BouncyCastle для генерации X509Certificate2, который может использоваться для аутентификации 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. 

Внутреннее исключение - null.

Что я сделал не так?

ответ

2

Для этой цели необходимо явно указать пары ключей, используемые для обмена сертификатами. Я думаю, вам просто нужно добавить еще одно расширение для вашего генератора сертификатов, как это:

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

Не уверен, что синтаксис точно правильно, но вот идея: вам нужно сделать ключ в сертификате как для подписания сертификата , и это «критическое» расширение, если оно присутствует.

+0

добавлен параметр. служба по-прежнему не начнет с нее. Я экспериментировал с созданием работоспособного сертификата с makecert, и правильная последовательность команд: makecert -n "CN = mfcertificate" -cy авторитет -a sha1 -sv "nick_ca.pvk" -r "nick_ca.cer" makecert -pe -n "CN = my Dev" -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -ic "nick_ca.cer" -iv "nick_ca.pvk" -sp "Microsoft RSA SChannel Cryptographic Провайдер "-sy 12 -sv" nick_dev.pvk "" nick_dev.cer " pvk2pfx -pvk" nick_dev.pvk "-spc" nick_dev.cer "-pfx" nick_dev.pfx " Я понятия не имею, как сделать это в BouncyCastle, хотя –

+0

Ошибка, которую вы получаете, будет решена с помощью makecert с параметром «-sky exchange», я просто не знаю API BouncyCastle, чтобы знать, как это сделать. Сожалею. –

+0

на самом деле, это не решено этим, я пробовал)) –