开发者

How do I create a PKCS12 .p12 file in C#?

this is probably a n00b question, but I don't really have any experience in this area.

I need to create a p12 bundle containing an X509 certificate and the private key. I currently have two objects, the X509Certificate2, and the RSAParameters object which contains key information. How do I combine these into a p12 file?

I just cannot find any information regarding this.

I also have a RSACryptoServiceProvider object that has the parameters from the RSAParameters imported into it if that helps.

Some additional background. I am getting my certificate from a VeriSign Registration Authority we have installed here. This is done by creating a PCKS#10 certificate request. I create my certificate object by reading in a byte array of data the RA puts into a database.

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 generation (using the bouncycastle library)

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

The cert request (minus the http post headers). the public_key parameter is the base64 encoded, pkcs10 formatted CSR. (I've put the line breaks after each parameter just so it's easier to read here, they are not there in the actual http post)

operation=AutoAuthOSUserSubmit&
form_file=..%2ffdf%2fclient%2fuserEnrollMS.fdf&
authenticate=NO&
public_key_format=pkcs10&
country=NZ&
mail_firstName=Daniel&
mail_lastName=Mapletoft&
mail_email=daniel.mapletoft@nz.firstms.com&
challenge=1234&
public_key=MIIBTzCBuwIBADAUMRIwEAYDVQQDDAlTaW1vbiBEb2UwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANZD8M7gjUq1vBWq4w25x3SNhet4T+uCV3ebnAB5ws9f2YQevd9QeSfoPWw/pyJ/mJRDZDLjYzG63VQUzrXyBx3PZhmWqWaDECAYSssOYTfTMWPns0sRsyg1f35f4mh0ZXieiPYdv8r9CVjG9woa15LA1cYI0b93alM/z+OoMLxNAgMBAAEwCwYJKoZIhvcNAQEFA4GBAIB9buu5sycjdAgyV+UMAlzYKlENrQmI2/36ZZ4q3sx5bIyLm9tOEexbNzkk86kcGQhL2w/0oA5UpUCUU4IIf9u+lhpMoUlbHKH4tosswMwVEiFpfIWrL4M9X7+TW4Lj1aGf2T+xgKhWeo+cBSGexxvHo27OaH9d1NVDozEJ6c7i

This is the output from Certificate.GetRawCertDataString()

3082036F30820257A003020102021034914BB0AF5A48704B56C89DE8B1BBFD300D06092A864886F70D0101050500304D310B300906035504061302开发者_开发问答4E5A31283026060355040A131F4669727374204D6F727467616765205365727669636573204C696D69746564311430120603550403130B464D5320526F6F74204341301E170D3130303132313030303030305A170D3131303132313233353935395A305B31243022060355040A141B4669727374204D6F727467616765205365727669636573204C7464311F301D060355040B1416466F72205465737420507572706F736573204F6E6C79311230100603550403140953696D6F6E20446F6530819F300D06092A864886F70D010101050003818D0030818902818100D643F0CEE08D4AB5BC15AAE30DB9C7748D85EB784FEB8257779B9C0079C2CF5FD9841EBDDF507927E83D6C3FA7227F9894436432E36331BADD5414CEB5F2071DCF661996A966831020184ACB0E6137D33163E7B34B11B328357F7E5FE2687465789E88F61DBFCAFD0958C6F70A1AD792C0D5C608D1BF776A533FCFE3A830BC4D0203010001A381C03081BD30090603551D1304023000300E0603551D0F0101FF0404030205A030600603551D1F0101FF045630543052A050A04E864C687474703A2F2F6F6E7369746563726C2E766572697369676E2E636F6D2F46697273744D6F72746761676553657276696365734C746450726F70656C6C632F4C617465737443524C2E63726C301F0603551D230418301680148B2A2C583903B2619F16E73D3DF1704DB1F3D4E2301D0603551D0E0416041411A6D5EBC14D7C226502EC340F70237D23431D0B300D06092A864886F70D010105050003820101008EFD93EF777F2D196FC8633C5A8347CA886320E59AF8AF8D3AA901AEF0ADF75EDD2D3C4495CF70F1E4516AA224F3731B6EE66DCB332FD88C03255DA9D12202DD3DF619EE55443F53773FD03C808B5B66AEEB39A3E20B866DC22D92010785A2729C269E35ED6B2036014628850B8E8A40A501F3C7EECA49A4B7E957B496ECD8A27702D7230C40580F94C69E83A0AEFD9347625B529E3ACDD2A5FEB7B946BEE9BE9DA9AA52E14AEC790C66E8A670AA1D53518DEFB66FE6BC33A57BB6A59C75C6DFADE5E961A9A03C3FFDC559FC9ADD565D345975B99BEF5F973D331E60A3FEFEF713C6C630D80222AD9541BC12F1E92379EF5CBECE81CA5E327FD32FDC28AB52D7

this is the contents of array from 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

this is the contents of the array from 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


Try this:

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

X509Certificate2 cert = ...

cert.PrivateKey = rsaKey;

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

Since you still get the mismatch, but cannot find any difference between the keys, try to insert this check (it should replicate what the .NET framework does internally):

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

It looks like something is going wrong with your keys. Are you perhaps generating a new RSA key between issuing the certificate-request and receiving the certificate?

Here is a dump of your certificate-request:

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

and here is a dump of your certificate:

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

The INTEGERs starting with "00 95 83 2A" in the request and with "00 CD 08 AE" in the certificate are the RSA moduluses of the public key.

The values in the output from ExportCspBlob are reversed, since Microsoft uses little-endian format, but if you start from the end of certKey.ExportCspBlob(false), you should recognize: 205=0xCD, 8=0x08, 174=0xAE. rsaKey.ExportCspBlob(false) on the other hand contains 166=0xA6, 154=0x9A, 180=0xB4, which is yet another RSA modulus.

Are you sure that all of your dumped values were from the same certificate-issuing-process?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜