2012-03-06 49 views
6

Tenemos una Solicitud de Certificado PKCS # 10 válida generada en el Cliente usando CertEnroll..Net Programmatically Sign PKCS # 10 Solicitud con Bouncy Castle

Ahora tenemos que firmarlo y devolver el resultado al Cliente, donde CertEnroll manejará las cosas del Almacén de Certificados local.

Esta es una aplicación B2B y el certificado de firma raíz se autogenerará o podemos usar nuestro certificado Thawte SSL existente.

El servidor (2008) no tiene Active Directory ejecutándose y no queremos crear una infraestructura/servicio de firma independiente para esto a menos que sea absolutamente necesario. No hay necesidad de revocación, etc., queremos hacerlo de forma programática.

Estaría encantado de utilizar la Biblioteca BouncyCastle, sin embargo, la biblioteca C# carece de documentación significativa y, aunque los documentos Java originales son ciertamente similares, la implementación de C# es lo suficientemente diferente como para dejarme un poco confundido.

¿Alguien conoce (o tiene) el código de muestra C# (o VB) o un enlace conocido-posible al mismo, usando BouncyCastle o para el caso las clases .Net nativas?

¡Cualquier ayuda para hacer esto será muy apreciada!

+0

Sin respuestas, así que voy a abordar este problema a la vez y publicar preguntas más detalladas a medida que avanzamos/necesitamos. Cuando finalmente lo logremos (¡por favor!) Publicaré las respuestas/enlaces aquí. – Serexx

+0

Estoy enfrentando una situación similar ahora. Mi pregunta es http://stackoverflow.com/q/10697321/481656. ¿Fue capaz de descubrir el X509? – DoomerDGR8

Respuesta

9

Esto resultó ser un ejercicio interesante para decir lo menos :-)

Se utilizó tanto los objetos Certificado de .Net y BouncyCastle. La solución todavía tiene! Mucho! espacio para mejorar, pero de hecho funciona.

Las agallas (Cert Gen) están a continuación. Cuando llegamos aquí, el CSR ya se generó en el cliente y cuando lo dejamos, el certificado resultante se instala por código del lado del cliente (ver this blog para el funcionamiento del cliente).

Nuevamente, no estoy ofreciendo esto como un Producto Terminado pero con un poco de valor para aquellos que enfrentan la misma tarea. Happy Encrypting :-)

 // Jul 10, 2012 see 
     // http://social.technet.microsoft.com/Forums/en-NZ/winserversecurity/thread/45781b46-3eb7-4715-b877-883bf0dc2ae7 
     // instaed of CX509CertificateRequestPkcs10 csr = new CX509CertificateRequestPkcs10(); use: 
     IX509CertificateRequestPkcs10 csr = (IX509CertificateRequestPkcs10)Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509CertificateRequestPkcs10")); 
     csr.InitializeDecode(csrText, EncodingType.XCN_CRYPT_STRING_BASE64); 
     csr.CheckSignature(Pkcs10AllowedSignatureTypes.AllowedKeySignature); 

     //get Bouncy CSRInfo Object 
     Trace.Write("get Bouncy CSRInfo Object"); 
     Byte[] csrBytes = Convert.FromBase64String(csrText); 
     CertificationRequestInfo csrInfo = CertificateTools.GetCsrInfo(csrBytes); 
     SubjectPublicKeyInfo pki = csrInfo.SubjectPublicKeyInfo; 

     //pub key for the signed cert 
     Trace.Write("pub key for the signed cert"); 
     AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(pki); 

     // Build a Version1 (No Extensions) Certificate 
     DateTime startDate = DateTime.Now; 
     DateTime expiryDate = startDate.AddYears(100); 
     BigInteger serialNumber = new BigInteger(32, new Random()); 

     Trace.Write("Build a Version1 (No Extensions) Certificate"); 
     X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); 
     string signerCN = ConfigurationManager.AppSettings["signerCN"].ToString(); 
     X509Name dnName = new X509Name(String.Format("CN={0}", signerCN)); 
     X509Name cName = new X509Name(csr.Subject.Name); 
     certGen.SetSerialNumber(serialNumber); 
     certGen.SetIssuerDN(dnName); 
     certGen.SetNotBefore(startDate); 
     certGen.SetNotAfter(expiryDate); 
     certGen.SetSubjectDN(cName); 
     certGen.SetSignatureAlgorithm("SHA1withRSA"); 
     certGen.SetPublicKey(publicKey); 

     //get our Private Key to Sign with 
     Trace.Write("get our Private Key to Sign with"); 
     X509Store store = new X509Store(StoreLocation.LocalMachine); 
     store.Open(OpenFlags.ReadOnly); 
     string signerThumbprint = ConfigurationManager.AppSettings["signerThumbprint"].ToString(); 
     X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates; 
     X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByThumbprint, signerThumbprint, false); 
     X509Certificate2 caCert = fcollection[0]; 

     Trace.Write("Found:" + caCert.FriendlyName); 
     Trace.Write("Has Private " + caCert.HasPrivateKey.ToString()); 
     Trace.Write("Key Size " + caCert.PrivateKey.KeySize.ToString()); 

     //Get our Signing Key as a Bouncy object 
     Trace.Write("Get our Signing Key as a Bouncy object from key "); 
     AsymmetricCipherKeyPair caPair = DotNetUtilities.GetKeyPair(caCert.PrivateKey); 

     //gen BouncyCastle object 
     Trace.Write("gen BouncyCastle object"); 
     Org.BouncyCastle.X509.X509Certificate cert = certGen.Generate(caPair.Private); 

     //convert to windows type 2 and get Base64 String 
     Trace.Write("convert to windows type 2 and get Base64 String"); 
     X509Certificate2 cert2 = new X509Certificate2(DotNetUtilities.ToX509Certificate(cert)); 
     byte[] encoded = cert2.GetRawCertData(); 
     string certOutString = Convert.ToBase64String(encoded); 

     //output to the page (hidden) 
     Certificate.Value = certOutString; 
Cuestiones relacionadas