2010-01-11 86 views
7

這可能是一個n00b問題,但我在這方面並沒有任何經驗。如何在C#中創建PKCS12 .p12文件?

我需要創建一個包含X509證書和私鑰的p12包。我目前有兩個對象,X509Certificate2和包含關鍵信息的RSAParameters對象。我如何將這些結合到一個p12文件中?

我只是找不到任何有關這方面的信息。

我也有一個RSACryptoServiceProvider對象,它具有從RSAParameters導入到它的參數(如果有幫助的話)。

一些額外的背景。我從我們在這裏安裝的VeriSign註冊中心獲得我的證書。這是通過創建PCKS#10證書請求完成的。我通過讀取RA放入數據庫的數據的字節數組來創建我的證書對象。

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

PKCS10代(使用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); 

的證書請求(減去HTTP POST標頭)。 public_key參數是base64編碼的,pkcs10格式的CSR。 (我已經把換行符只是所以它更容易讀到這裏每個參數後,它們不存在實際HTTP POST)

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 

這是Certificate.GetRawCertDataString()

3082036F30820257A003020102021034914BB0AF5A48704B56C89DE8B1BBFD300D06092A864886F70D0101050500304D310B3009060355040613024E5A31283026060355040A131F4669727374204D6F727467616765205365727669636573204C696D69746564311430120603550403130B464D5320526F6F74204341301E170D3130303132313030303030305A170D3131303132313233353935395A305B31243022060355040A141B4669727374204D6F727467616765205365727669636573204C7464311F301D060355040B1416466F72205465737420507572706F736573204F6E6C79311230100603550403140953696D6F6E20446F6530819F300D06092A864886F70D010101050003818D0030818902818100D643F0CEE08D4AB5BC15AAE30DB9C7748D85EB784FEB8257779B9C0079C2CF5FD9841EBDDF507927E83D6C3FA7227F9894436432E36331BADD5414CEB5F2071DCF661996A966831020184ACB0E6137D33163E7B34B11B328357F7E5FE2687465789E88F61DBFCAFD0958C6F70A1AD792C0D5C608D1BF776A533FCFE3A830BC4D0203010001A381C03081BD30090603551D1304023000300E0603551D0F0101FF0404030205A030600603551D1F0101FF045630543052A050A04E864C687474703A2F2F6F6E7369746563726C2E766572697369676E2E636F6D2F46697273744D6F72746761676553657276696365734C746450726F70656C6C632F4C617465737443524C2E63726C301F0603551D230418301680148B2A2C583903B2619F16E73D3DF1704DB1F3D4E2301D0603551D0E0416041411A6D5EBC14D7C226502EC340F70237D23431D0B300D06092A864886F70D010105050003820101008EFD93EF777F2D196FC8633C5A8347CA886320E59AF8AF8D3AA901AEF0ADF75EDD2D3C4495CF70F1E4516AA224F3731B6EE66DCB332FD88C03255DA9D12202DD3DF619EE55443F53773FD03C808B5B66AEEB39A3E20B866DC22D92010785A2729C269E35ED6B2036014628850B8E8A40A501F3C7EECA49A4B7E957B496ECD8A27702D7230C40580F94C69E83A0AEFD9347625B529E3ACDD2A5FEB7B946BEE9BE9DA9AA52E14AEC790C66E8A670AA1D53518DEFB66FE6BC33A57BB6A59C75C6DFADE5E961A9A03C3FFDC559FC9ADD565D345975B99BEF5F973D331E60A3FEFEF713C6C630D80222AD9541BC12F1E92379EF5CBECE81CA5E327FD32FDC28AB52D7 
輸出

這是數組的內容 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 

這是陣列的從 字節[]數組2 = rsaKey.ExportCspBlob(假)的內容;

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

歡迎來到SO家庭DangerMice!小提示:您可以通過點擊問題下方的小灰色「編輯」鏈接來編輯您的答案。 – RCIX 2010-01-12 09:17:09

+0

謝謝RCIX,完成:) – DangerMice 2010-01-12 23:33:48

回答

5

試試這個:

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

X509Certificate2 cert = ... 

cert.PrivateKey = rsaKey; 

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

既然你仍然可以得到的不匹配,但無法找到鑰匙之間的任何差別,嘗試插入這個檢查(它應該複製什麼.NET框架內部一樣):

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

它看起來像你的鑰匙出問題了。您是否可能在頒發證書請求和接收證書之間生成新的RSA密鑰?

這是你的證書請求的轉儲:

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

,這裏是你的證書轉儲:

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

整數在請求開始以「00 95 83 2A」並且證書中的「00 CD 08 AE」是公鑰的RSA模塊。

由於Microsoft使用little-endian格式,ExportCspBlob的輸出值相反,但如果從certKey.ExportCspBlob(false)的末尾開始,則應該識別:205 = 0xCD,8 = 0x08,174 = 0xAE。另一方面, rsaKey.ExportCspBlob(false)包含166 = 0xA6,154 = 0x9A,180 = 0xB4,這是又一個RSA模量。

您確定所有轉儲的值都來自相同的證書頒發過程嗎?

+0

這是否與做Certificate.Export(X509ContentType.Pkcs12,密碼)不同?我看過的示例沒有顯示如何包含私鑰。 請注意我的certificate.HasPrivateKey屬性爲空。 – DangerMice 2010-01-11 22:12:15

+0

我試圖使用你以前在這個答案(PFXExportCertStoreEx)中使用我在這裏發現的類的方法 http://blogs.msdn.com/dcook/attachment/9143036.ashx 但是,它正在放棄證書友好名稱和我添加到證書擴展中的主題替代名稱。 任何人都可以指導我如何改變上面的類來包含這些? 我不知道足夠的C++能夠將此翻譯成C# http://msdn.microsoft.com/en-us/library/aa376039(VS.85).aspx 謝謝 – DangerMice 2010-01-13 02:35:45

+0

嗨Rasmus,是的我首先嚐試使用cert.Export方法,如上所述,但是在cert.PrivateKey = rsaKey上出現錯誤「證書的公鑰與指定的值不匹配」。 查看我添加到問題中的代碼。 RsaPrivateCrtKeyParameters對象來自BouncyCastle庫,用於創建我的密鑰並將其包含在我的證書請求中。 – DangerMice 2010-01-13 02:47:35