2010-01-11 12 views
7

C'est probablement une question n00b, mais je n'ai pas vraiment d'expérience dans ce domaine.Comment créer un fichier PKCS12 .p12 en C#?

Je dois créer un ensemble p12 contenant un certificat X509 et la clé privée. J'ai actuellement deux objets, le X509Certificate2, et l'objet RSAParameters qui contient des informations clés. Comment puis-je les combiner dans un fichier p12?

Je ne trouve aucune information à ce sujet.

J'ai également un RSACryptoServiceProvider objet qui a les paramètres de l'RSAParameters importés dans si cela aide.

Un arrière-plan supplémentaire. Je reçois mon certificat d'une autorité d'enregistrement VeriSign que nous avons installée ici. Ceci est fait en créant une demande de certificat PCKS # 10. Je crée mon objet de certificat en lisant dans un tableau d'octets de données que l'AE met dans une base de données.

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); 

génération de PKCS10 (en utilisant la bibliothèque 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 demande de CERT (moins les en-têtes HTTP POST). Le paramètre public_key est le CSR formaté en base64, formaté en pkcs10. (Je l'ai mis les sauts de ligne après chaque paramètre seulement il est donc plus facile à lire ici, ils ne sont pas là dans le poste réel http)

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 

Ceci est la sortie de Certificate.GetRawCertDataString()

3082036F30820257A003020102021034914BB0AF5A48704B56C89DE8B1BBFD300D06092A864886F70D0101050500304D310B3009060355040613024E5A31283026060355040A131F4669727374204D6F727467616765205365727669636573204C696D69746564311430120603550403130B464D5320526F6F74204341301E170D3130303132313030303030305A170D3131303132313233353935395A305B31243022060355040A141B4669727374204D6F727467616765205365727669636573204C7464311F301D060355040B1416466F72205465737420507572706F736573204F6E6C79311230100603550403140953696D6F6E20446F6530819F300D06092A864886F70D010101050003818D0030818902818100D643F0CEE08D4AB5BC15AAE30DB9C7748D85EB784FEB8257779B9C0079C2CF5FD9841EBDDF507927E83D6C3FA7227F9894436432E36331BADD5414CEB5F2071DCF661996A966831020184ACB0E6137D33163E7B34B11B328357F7E5FE2687465789E88F61DBFCAFD0958C6F70A1AD792C0D5C608D1BF776A533FCFE3A830BC4D0203010001A381C03081BD30090603551D1304023000300E0603551D0F0101FF0404030205A030600603551D1F0101FF045630543052A050A04E864C687474703A2F2F6F6E7369746563726C2E766572697369676E2E636F6D2F46697273744D6F72746761676553657276696365734C746450726F70656C6C632F4C617465737443524C2E63726C301F0603551D230418301680148B2A2C583903B2619F16E73D3DF1704DB1F3D4E2301D0603551D0E0416041411A6D5EBC14D7C226502EC340F70237D23431D0B300D06092A864886F70D010105050003820101008EFD93EF777F2D196FC8633C5A8347CA886320E59AF8AF8D3AA901AEF0ADF75EDD2D3C4495CF70F1E4516AA224F3731B6EE66DCB332FD88C03255DA9D12202DD3DF619EE55443F53773FD03C808B5B66AEEB39A3E20B866DC22D92010785A2729C269E35ED6B2036014628850B8E8A40A501F3C7EECA49A4B7E957B496ECD8A27702D7230C40580F94C69E83A0AEFD9347625B529E3ACDD2A5FEB7B946BEE9BE9DA9AA52E14AEC790C66E8A670AA1D53518DEFB66FE6BC33A57BB6A59C75C6DFADE5E961A9A03C3FFDC559FC9ADD565D345975B99BEF5F973D331E60A3FEFEF713C6C630D80222AD9541BC12F1E92379EF5CBECE81CA5E327FD32FDC28AB52D7 

c'est le contenu du tableau de byte [] array1 = certKey.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 

Ceci est le contenu du tableau 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

Bienvenue dans le SO Family DangerMice! Petite astuce cependant: vous pouvez éditer votre réponse en cliquant sur le petit lien gris "modifier" ci-dessous votre question. – RCIX

+0

Merci RCIX, fait :) – DangerMice

Répondre

5

Essayez ceci:

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

X509Certificate2 cert = ... 

cert.PrivateKey = rsaKey; 

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

Puisque vous obtenez toujours le décalage, mais ne peut pas trouver une différence entre les touches, essayez d'insérer cette vérification (il doit reproduire ce que le framework .NET fait en interne):

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"); 
    } 
} 

Il semble que quelque chose ne va pas avec vos clés. Générez-vous peut-être une nouvelle clé RSA entre l'émission de la demande de certificat et la réception du certificat?

Voici une décharge de votre certificat demande:

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 
      : } 

et voici une décharge de votre certificat:

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 ] 
      : } 

Les INTEGERs commençant par "00 95 83 2A" dans la demande et avec "00 CD 08 AE" dans le certificat sont les modules RSA de la clé publique.Les valeurs dans la sortie d'ExportCspBlob sont inversées, car Microsoft utilise le format little-endian, mais si vous commencez à la fin de certKey.ExportCspBlob(false), vous devez reconnaître: 205 = 0xCD, 8 = 0x08, 174 = 0xAE. D'autre part, rsaKey.ExportCspBlob(false) contient 166 = 0xA6, 154 = 0x9A, 180 = 0xB4, qui est encore un autre module RSA. Êtes-vous sûr que toutes vos valeurs sous-évaluées proviennent du même processus d'émission de certificat?

+0

est-ce différent de faire Certificat.Export (X509ContentType.Pkcs12, mot de passe)? Les exemples que j'ai examinés pour cela ne montrent pas comment inclure la clé privée. Notez que ma propriété certificate.HasPrivateKey est Null. – DangerMice

+0

Je suis en train d'utiliser la méthode que vous aviez précédemment dans cette réponse (PFXExportCertStoreEx) en utilisant la classe je trouve ici http://blogs.msdn.com/dcook/attachment/9143036.ashx Cependant, il est tomber le cert amical nom et l'autre nom de sujet que j'ai ajouté dans les extensions de cert. Quelqu'un pourrait-il me diriger sur la façon de modifier la classe ci-dessus pour les inclure? Je ne sais pas assez C++ pour être en mesure de traduire en C# http://msdn.microsoft.com/en-us/library/aa376039(VS.85).aspx Merci – DangerMice

+0

Salut Rasmus, oui je essayé la méthode cert.Export en premier, comme vous le décrivez ci-dessus, cependant sur cert.PrivateKey = rsaKey J'ai l'erreur "La clé publique du certificat ne correspond pas à la valeur spécifiée." Voir le code que j'ai ajouté à la question. L'objet RsaPrivateCrtKeyParameters provient de la bibliothèque BouncyCastle et j'ai utilisé pour créer mes clés et les inclure dans ma demande de certificat. – DangerMice