2010-01-11 24 views
7

esta es probablemente una pregunta n00b, pero realmente no tengo ninguna experiencia en esta área.¿Cómo creo un archivo PKCS12 .p12 en C#?

Necesito crear un paquete p12 que contenga un certificado X509 y la clave privada. Actualmente tengo dos objetos, el X509Certificate2 y el objeto RSAParameters que contiene información clave. ¿Cómo los combino en un archivo p12?

No puedo encontrar ninguna información al respecto.

También tengo un objeto RSACryptoServiceProvider que tiene los parámetros de los RSAParameters importados si eso ayuda.

Algunos antecedentes. Estoy obteniendo mi certificado de una Autoridad de Registro de VeriSign que hemos instalado aquí. Esto se hace creando una solicitud de certificado PCKS n. ° 10. Creo mi objeto de certificado leyendo en una matriz de bytes de datos que RA coloca en una base de datos.

RsaPrivateCrtKeyParameters KeyParams = (RsaPrivateCrtKeyParameters)this.KeyPair.Private; 
RSAParameters rsaParameters = new RSAParameters(); 

rsaParameters.Modulus = KeyParams.Modulus.ToByteArrayUnsigned(); 
rsaParameters.P = KeyParams.P.ToByteArrayUnsigned(); 
rsaParameters.Q = KeyParams.Q.ToByteArrayUnsigned(); 
rsaParameters.DP = KeyParams.DP.ToByteArrayUnsigned(); 
rsaParameters.DQ = KeyParams.DQ.ToByteArrayUnsigned(); 
rsaParameters.InverseQ = KeyParams.QInv.ToByteArrayUnsigned(); 
rsaParameters.D = KeyParams.Exponent.ToByteArrayUnsigned(); 
rsaParameters.Exponent = KeyParams.PublicExponent.ToByteArrayUnsigned(); 

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(); 
rsaKey.ImportParameters(rsaParameters); 

this.Certificate.PrivateKey = rsaKey; 

byte[] p12 = this.Certificate.Export(X509ContentType.Pkcs12, "password"); 

File.WriteAllBytes(fileName, p12); 

generación PKCS10 (usando la biblioteca BouncyCastle)

509Name name = new X509Name(String.Concat(SubjectCommonName, "=", firstName, " ", lastName)); 
RsaKeyPairGenerator rkpg = new RsaKeyPairGenerator(); 
rkpg.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); 
this.KeyPair = rkpg.GenerateKeyPair(); 

// PKCS #10 Certificate Signing Request 
Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest("SHA1WITHRSA", name, this.KeyPair.Public, null, this.KeyPair.Private); 
byte[] request = Base64.Encode(csr.GetEncoded()); 
ASCIIEncoding encoder = new ASCIIEncoding(); 
return encoder.GetString(request); 

La solicitud cert (menos las cabeceras HTTP POST). el parámetro public_key es el CSR con formato base64 codificado, pkcs10. (He puesto los saltos de línea después de cada parámetro simplemente por lo que es más fácil de leer aquí, no están allí en el post http real)

operation=AutoAuthOSUserSubmit& 
form_file=..%2ffdf%2fclient%2fuserEnrollMS.fdf& 
authenticate=NO& 
public_key_format=pkcs10& 
country=NZ& 
mail_firstName=Daniel& 
mail_lastName=Mapletoft& 
[email protected]& 
challenge=1234& 
public_key=MIIBTzCBuwIBADAUMRIwEAYDVQQDDAlTaW1vbiBEb2UwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANZD8M7gjUq1vBWq4w25x3SNhet4T+uCV3ebnAB5ws9f2YQevd9QeSfoPWw/pyJ/mJRDZDLjYzG63VQUzrXyBx3PZhmWqWaDECAYSssOYTfTMWPns0sRsyg1f35f4mh0ZXieiPYdv8r9CVjG9woa15LA1cYI0b93alM/z+OoMLxNAgMBAAEwCwYJKoZIhvcNAQEFA4GBAIB9buu5sycjdAgyV+UMAlzYKlENrQmI2/36ZZ4q3sx5bIyLm9tOEexbNzkk86kcGQhL2w/0oA5UpUCUU4IIf9u+lhpMoUlbHKH4tosswMwVEiFpfIWrL4M9X7+TW4Lj1aGf2T+xgKhWeo+cBSGexxvHo27OaH9d1NVDozEJ6c7i 

Ésta es la salida de Certificate.GetRawCertDataString()

3082036F30820257A003020102021034914BB0AF5A48704B56C89DE8B1BBFD300D06092A864886F70D0101050500304D310B3009060355040613024E5A31283026060355040A131F4669727374204D6F727467616765205365727669636573204C696D69746564311430120603550403130B464D5320526F6F74204341301E170D3130303132313030303030305A170D3131303132313233353935395A305B31243022060355040A141B4669727374204D6F727467616765205365727669636573204C7464311F301D060355040B1416466F72205465737420507572706F736573204F6E6C79311230100603550403140953696D6F6E20446F6530819F300D06092A864886F70D010101050003818D0030818902818100D643F0CEE08D4AB5BC15AAE30DB9C7748D85EB784FEB8257779B9C0079C2CF5FD9841EBDDF507927E83D6C3FA7227F9894436432E36331BADD5414CEB5F2071DCF661996A966831020184ACB0E6137D33163E7B34B11B328357F7E5FE2687465789E88F61DBFCAFD0958C6F70A1AD792C0D5C608D1BF776A533FCFE3A830BC4D0203010001A381C03081BD30090603551D1304023000300E0603551D0F0101FF0404030205A030600603551D1F0101FF045630543052A050A04E864C687474703A2F2F6F6E7369746563726C2E766572697369676E2E636F6D2F46697273744D6F72746761676553657276696365734C746450726F70656C6C632F4C617465737443524C2E63726C301F0603551D230418301680148B2A2C583903B2619F16E73D3DF1704DB1F3D4E2301D0603551D0E0416041411A6D5EBC14D7C226502EC340F70237D23431D0B300D06092A864886F70D010105050003820101008EFD93EF777F2D196FC8633C5A8347CA886320E59AF8AF8D3AA901AEF0ADF75EDD2D3C4495CF70F1E4516AA224F3731B6EE66DCB332FD88C03255DA9D12202DD3DF619EE55443F53773FD03C808B5B66AEEB39A3E20B866DC22D92010785A2729C269E35ED6B2036014628850B8E8A40A501F3C7EECA49A4B7E957B496ECD8A27702D7230C40580F94C69E83A0AEFD9347625B529E3ACDD2A5FEB7B946BEE9BE9DA9AA52E14AEC790C66E8A670AA1D53518DEFB66FE6BC33A57BB6A59C75C6DFADE5E961A9A03C3FFDC559FC9ADD565D345975B99BEF5F973D331E60A3FEFEF713C6C630D80222AD9541BC12F1E92379EF5CBECE81CA5E327FD32FDC28AB52D7 

este es el contenido de la matriz de byte [] matriz1 = certKey.ExportCspBlob (falso);

6,2,0,0,0,164,0,0,82,83,65,49,0,4,0,0,1,0,1,0,77,188,48,168,227,207,63,83,106,119,191,209,8,198,213,192,146,215,26,10,247,198,88,9,253,202,191,29,246,136,158,120,101,116,104,226,95,126,127,53,40,179,17,75,179,231,99,49,211,55,97,14,203,74,24,32,16,131,102,169,150,25,102,207,29,7,242,181,206,20,84,221,186,49,99,227,50,100,67,148,152,127,34,167,63,108,61,232,39,121,80,223,189,30,132,217,95,207,194,121,0,156,155,119,87,130,235,79,120,235,133,141,116,199,185,13,227,170,21,188,181,74,141,224,206,240,67,214 

Este es el contenido de la matriz de byte [] array2 = rsaKey.ExportCspBlob (false);

6,2,0,0,0,164,0,0,82,83,65,49,0,4,0,0,1,0,1,0,77,188,48,168,227,207,63,83,106,119,191,209,8,198,213,192,146,215,26,10,247,198,88,9,253,202,191,29,246,136,158,120,101,116,104,226,95,126,127,53,40,179,17,75,179,231,99,49,211,55,97,14,203,74,24,32,16,131,102,169,150,25,102,207,29,7,242,181,206,20,84,221,186,49,99,227,50,100,67,148,152,127,34,167,63,108,61,232,39,121,80,223,189,30,132,217,95,207,194,121,0,156,155,119,87,130,235,79,120,235,133,141,116,199,185,13,227,170,21,188,181,74,141,224,206,240,67,214 
+0

¡Bienvenido a SO Family DangerMice! Un pequeño consejo: puede editar su respuesta haciendo clic en el pequeño enlace gris "editar" debajo de su pregunta. – RCIX

+0

Gracias RCIX, hecho :) – DangerMice

Respuesta

5

Prueba esto:

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(); 
rsaKey.ImportParameters(rsaParameters); 

X509Certificate2 cert = ... 

cert.PrivateKey = rsaKey; 

cert.Export(X509ContentType.Pkcs12, "password"); 

Puesto que usted todavía consigue el desajuste, pero no puede encontrar ninguna diferencia entre las teclas, intente insertar esta comprobación (debe reproducir lo que el marco .NET hace internamente):

RSACryptoServiceProvider certKey = (RSACryptoServiceProvider) cert.PublicKey.Key; 
byte[] array1 = certKey.ExportCspBlob(false); 
byte[] array2 = rsaKey.ExportCspBlob(false); 
if(array1.Length!=array2.Length) 
    throw new Exception("key mismatch"); 
for (int i = 8; i < array1.Length; i++){ // skip blobheader 
    if (array1[i] != array2[i]){ 
    throw new Exception("key mismatch"); 
    } 
} 

Parece que algo va mal con tus llaves. ¿Está generando una nueva clave RSA entre emitir la solicitud de certificado y recibir el certificado?

Aquí es un volcado de su certificado de solicitud de:

0 30 342: SEQUENCE { 
    4 30 194: SEQUENCE { 
    7 02 1:  INTEGER 0 
    10 30 27:  SEQUENCE { 
    12 31 25:  SET { 
    14 30 23:   SEQUENCE { 
    16 06 3:   OBJECT IDENTIFIER commonName (2 5 4 3) 
    21 0C 16:   UTF8String 'Daniel Mapletoft' 
      :   } 
      :   } 
      :  } 
    39 30 159:  SEQUENCE { 
    42 30 13:  SEQUENCE { 
    44 06 9:   OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) 
    55 05 0:   NULL 
      :   } 
    57 03 141:  BIT STRING 0 unused bits, encapsulates { 
    61 30 137:   SEQUENCE { 
    64 02 129:    INTEGER 
      :    00 95 83 2A AB 16 9D 7F 16 87 40 A4 09 74 5F 9D 
      :    81 04 B0 41 C1 75 9C C9 CD D0 52 EF 61 09 EF F5 
      :    9B 40 1D D4 79 E0 4B 17 6C 1E 62 73 38 D8 69 92 
      :    31 C4 E0 84 07 4B 2E FD 53 6D 24 95 59 12 43 8E 
      :    82 35 1D 62 79 89 C2 88 38 57 3D 1F 15 8D B9 CC 
      :    FA F4 41 23 BA FD ED 51 69 F7 7A E7 03 72 A2 DA 
      :    A9 08 65 17 DA 90 E3 7B C4 2C 85 6A 3F AF 83 AC 
      :    E5 00 37 7A 98 14 03 EE 68 37 CB E7 0A 1A 49 5F 
      :      [ Another 1 bytes skipped ] 
196 02 3:    INTEGER 65537 
      :    } 
      :   } 
      :  } 
      :  } 
201 30 11: SEQUENCE { 
203 06 9:  OBJECT IDENTIFIER 
      :  sha1withRSAEncryption (1 2 840 113549 1 1 5) 
      :  } 
214 03 129: BIT STRING 0 unused bits 
      :  70 D5 29 EB F3 2A 34 13 3F E6 DE 78 35 FB 79 BD 
      :  6D ED 8E 89 D9 B0 8F C1 7C 7D 42 37 B8 3E 5B 00 
      :  C2 26 A4 E5 77 26 01 86 63 E1 BB 4D 9C CE 7A 10 
      :  FF 8E BF 77 1B 0E F9 EE 38 1F 1F A1 04 24 D7 6A 
      :  B6 28 3A 88 F5 54 D0 88 46 92 6E 5D 7E 7C CE 87 
      :  99 F9 DC 85 99 33 8C 9D BD 73 E2 23 8A 9A 97 B0 
      :  3A 9B 36 51 58 FD B7 0F 60 3D FB 5F 4F 06 A0 CE 
      :  30 7F 56 B6 53 5E FE 64 7D 8A 30 92 FB BA A4 C6 
      : } 

y aquí es un vertedero de su certificado:

0 30 886: SEQUENCE { 
    4 30 606: SEQUENCE { 
    8 A0 3:  [0] { 
    10 02 1:  INTEGER 2 
      :  } 
    13 02 16:  INTEGER 
      :  6E F0 A9 78 7D 3C D4 05 4E 90 13 DC 9D 34 77 2C 
    31 30 13:  SEQUENCE { 
    33 06 9:  OBJECT IDENTIFIER 
      :   sha1withRSAEncryption (1 2 840 113549 1 1 5) 
    44 05 0:  NULL 
      :  } 
    46 30 77:  SEQUENCE { 
    48 31 11:  SET { 
    50 30 9:   SEQUENCE { 
    52 06 3:   OBJECT IDENTIFIER countryName (2 5 4 6) 
    57 13 2:   PrintableString 'NZ' 
      :   } 
      :   } 
    61 31 40:  SET { 
    63 30 38:   SEQUENCE { 
    65 06 3:   OBJECT IDENTIFIER organizationName (2 5 4 10) 
    70 13 31:   PrintableString 'First Mortgage Services Limited' 
      :   } 
      :   } 
103 31 20:  SET { 
105 30 18:   SEQUENCE { 
107 06 3:   OBJECT IDENTIFIER commonName (2 5 4 3) 
112 13 11:   PrintableString 'FMS Root CA' 
      :   } 
      :   } 
      :  } 
125 30 30:  SEQUENCE { 
127 17 13:  UTCTime '091222000000Z' 
142 17 13:  UTCTime '101222235959Z' 
      :  } 
157 30 98:  SEQUENCE { 
159 31 36:  SET { 
161 30 34:   SEQUENCE { 
163 06 3:   OBJECT IDENTIFIER organizationName (2 5 4 10) 
168 14 27:   TeletexString 'First Mortgage Services Ltd' 
      :   } 
      :   } 
197 31 31:  SET { 
199 30 29:   SEQUENCE { 
201 06 3:   OBJECT IDENTIFIER organizationalUnitName (2 5 4 11) 
206 14 22:   TeletexString 'For Test Purposes Only' 
      :   } 
      :   } 
230 31 25:  SET { 
232 30 23:   SEQUENCE { 
234 06 3:   OBJECT IDENTIFIER commonName (2 5 4 3) 
239 14 16:   TeletexString 'Daniel Mapletoft' 
      :   } 
      :   } 
      :  } 
257 30 159:  SEQUENCE { 
260 30 13:  SEQUENCE { 
262 06 9:   OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) 
273 05 0:   NULL 
      :   } 
275 03 141:  BIT STRING 0 unused bits, encapsulates { 
279 30 137:   SEQUENCE { 
282 02 129:    INTEGER 
      :    00 CD 08 AE 3E E3 5A E4 5E 50 28 29 5E 65 05 DA 
      :    1A E1 9C 50 44 4A F0 06 AA 75 1A 8F F0 75 4C AA 
      :    47 4B D5 8F 04 B5 CE 98 C5 0D 99 54 36 E9 EF 2E 
      :    7D CD DF FA 46 B2 7D 76 E5 74 19 AD 3E F0 52 52 
      :    C7 F8 86 E6 78 32 90 EB 2F 12 3F 7A 31 4B 15 E9 
      :    2A 9D 75 91 EA 31 9F 4E 98 A6 06 81 DD 98 1B 1A 
      :    DB FE 1F 2E BD 2E 32 60 5A 54 7C 0E 48 6A AB 6C 
      :    C6 F6 E2 F2 FD 4A BE 5A BD E0 DF 0C 21 B6 4C 9E 
      :      [ Another 1 bytes skipped ] 
414 02 3:    INTEGER 65537 
      :    } 
      :   } 
      :  } 
419 A3 192:  [3] { 
422 30 189:  SEQUENCE { 
425 30 9:   SEQUENCE { 
427 06 3:   OBJECT IDENTIFIER basicConstraints (2 5 29 19) 
432 04 2:   OCTET STRING, encapsulates { 
434 30 0:    SEQUENCE {} 
      :    } 
      :   } 
436 30 14:   SEQUENCE { 
438 06 3:   OBJECT IDENTIFIER keyUsage (2 5 29 15) 
443 01 1:   BOOLEAN TRUE 
446 04 4:   OCTET STRING, encapsulates { 
448 03 2:    BIT STRING 5 unused bits 
      :     '101'B 
      :    } 
      :   } 
452 30 96:   SEQUENCE { 
454 06 3:   OBJECT IDENTIFIER cRLDistributionPoints (2 5 29 31) 
459 01 1:   BOOLEAN TRUE 
462 04 86:   OCTET STRING, encapsulates { 
464 30 84:    SEQUENCE { 
466 30 82:     SEQUENCE { 
468 A0 80:     [0] { 
470 A0 78:      [0] { 
472 86 76:      [6] 
      :     'http://onsitecrl.verisign.com/FirstMortgageServi' 
      :     'cesLtdPropellc/LatestCRL.crl' 
      :      } 
      :      } 
      :     } 
      :     } 
      :    } 
      :   } 
550 30 31:   SEQUENCE { 
552 06 3:   OBJECT IDENTIFIER authorityKeyIdentifier (2 5 29 35) 
557 04 24:   OCTET STRING, encapsulates { 
559 30 22:    SEQUENCE { 
561 80 20:     [0] 
      :     8B 2A 2C 58 39 03 B2 61 9F 16 E7 3D 3D F1 70 4D 
      :     B1 F3 D4 E2 
      :     } 
      :    } 
      :   } 
583 30 29:   SEQUENCE { 
585 06 3:   OBJECT IDENTIFIER subjectKeyIdentifier (2 5 29 14) 
590 04 22:   OCTET STRING, encapsulates { 
592 04 20:    OCTET STRING 
      :     3E 91 DB A0 9C B4 A1 CB 68 CC 70 D0 0A 29 D6 BF 
      :     4E 68 10 AB 
      :    } 
      :   } 
      :   } 
      :  } 
      :  } 
614 30 13: SEQUENCE { 
616 06 9:  OBJECT IDENTIFIER 
      :  sha1withRSAEncryption (1 2 840 113549 1 1 5) 
627 05 0:  NULL 
      :  } 
629 03 257: BIT STRING 0 unused bits 
      :  3E C3 A3 F3 5F 3E 29 37 4D 33 E3 F5 F2 89 42 78 
      :  AC CD 59 14 E9 CC FF 20 8F 98 34 7B F0 F4 D2 96 
      :  EC 58 53 61 E4 3E D0 02 CF FF 30 C8 77 D0 6F 94 
      :  37 72 3C B7 90 6E 38 10 59 8C F8 06 B0 61 55 65 
      :  58 96 30 7B 9A 58 FF DB 15 7C FA F9 1F 64 5E DC 
      :  E8 63 EE EE 90 B1 18 3C 6A 11 62 73 91 CF DE DB 
      :  34 F5 67 4F C9 89 77 5C 36 71 FC 11 27 07 C5 76 
      :  BB 79 B8 8E 19 E8 E2 5B D7 A5 23 BA D8 19 7C 74 
      :    [ Another 128 bytes skipped ] 
      : } 

los enteros que comienzan con "00 95 83 2A" en la solicitud y con "00 CD 08 AE" en el certificado están los módulos RSA de la clave pública.

Los valores en la salida de ExportCspBlob están invertidos, ya que Microsoft usa el formato little-endian, pero si comienza desde el final de certKey.ExportCspBlob(false), debe reconocer: 205 = 0xCD, 8 = 0x08, 174 = 0xAE. rsaKey.ExportCspBlob(false) por otro lado contiene 166 = 0xA6, 154 = 0x9A, 180 = 0xB4, que es otro módulo más de RSA.

¿Está seguro de que todos sus valores objeto de dumping proceden del mismo proceso emisor de certificado?

+0

¿Esto es diferente de hacer Certificate.Export (X509ContentType.Pkcs12, password)? Los ejemplos que he examinado para esto no muestran cómo incluir la clave privada. Nota mi propiedad certificate.HasPrivateKey es Null. – DangerMice

+0

Estoy tratando de usar el método que tenía anteriormente en esta respuesta (PFXExportCertStoreEx) usando la clase que encontré aquí http://blogs.msdn.com/dcook/attachment/9143036.ashx Sin embargo, está dejando caer el certificado amistoso nombre y el nombre alternativo del sujeto que agregué a las extensiones de cert. ¿Alguien podría indicarme cómo modificar la clase anterior para incluir estos? No sé lo suficiente C++ para poder traducir esto en C# http://msdn.microsoft.com/en-us/library/aa376039(VS.85).aspx Gracias – DangerMice

+0

Hola Rasmus, sí, yo intenté el método cert.Export primero, como usted describe arriba, sin embargo en cert.PrivateKey = rsaKey obtengo el error "La clave pública del certificado no coincide con el valor especificado". Ver el código que agregué a la pregunta. El objeto RsaPrivateCrtKeyParameters es de la biblioteca BouncyCastle que utilicé para crear mis claves e incluirlas en mi solicitud de certificado. – DangerMice

Cuestiones relacionadas