@@ -75,9 +75,7 @@ public void MoveTo(X509Certificate2Collection collection)
7575 }
7676
7777 case X509ContentType . Pkcs12 :
78- byte [ ] pkcs12 = ExportPkcs12 ( false , password , out bool aes256Sha256 ) ;
79- Debug . Assert ( ! aes256Sha256 ) ;
80- return pkcs12 ;
78+ return ExportPkcs12Core ( null , password ) ;
8179
8280 case X509ContentType . SerializedStore :
8381 return SaveToMemoryStore ( Interop . Crypt32 . CertStoreSaveAs . CERT_STORE_SAVE_AS_STORE ) ;
@@ -92,55 +90,54 @@ public void MoveTo(X509Certificate2Collection collection)
9290
9391 public byte [ ] ExportPkcs12 ( Pkcs12ExportPbeParameters exportParameters , SafePasswordHandle password )
9492 {
95- bool tryAes256sha256 = exportParameters is
96- Pkcs12ExportPbeParameters . Default or
97- Pkcs12ExportPbeParameters . Pbes2Aes256Sha256 ;
98-
99- byte [ ] exported = ExportPkcs12 ( tryAes256sha256 , password , out bool aes256Sha256 ) ;
100-
101- // What we asked for and what we got are the same - so return it as-is.
102- if ( tryAes256sha256 == aes256Sha256 )
103- {
104- return exported ;
105- }
106-
107- if ( ! tryAes256sha256 )
108- {
109- Debug . Fail ( "3DES PKCS12 export failed." ) ;
110- throw new CryptographicException ( ) ;
111- }
112-
113- return ReEncryptAndSealPkcs12 ( exported , password , Helpers . WindowsAesPbe ) ;
93+ return ExportPkcs12Core ( exportParameters , password ) ;
11494 }
11595
11696 public byte [ ] ExportPkcs12 ( PbeParameters exportParameters , SafePasswordHandle password )
11797 {
118- byte [ ] exported = ExportPkcs12 ( preferAes256Sha256 : true , password , out _ ) ;
98+ byte [ ] exported = ExportPkcs12Core ( null , password ) ;
11999 return ReEncryptAndSealPkcs12 ( exported , password , exportParameters ) ;
120100 }
121101
122- private unsafe byte [ ] ExportPkcs12 ( bool preferAes256Sha256 , SafePasswordHandle password , out bool aes256Sha256 )
102+ private unsafe byte [ ] ExportPkcs12Core ( Pkcs12ExportPbeParameters ? exportParameters , SafePasswordHandle password )
123103 {
124104 Interop . Crypt32 . DATA_BLOB dataBlob = new Interop . Crypt32 . DATA_BLOB ( IntPtr . Zero , 0 ) ;
125105 Interop . Crypt32 . PFXExportFlags flags =
126106 Interop . Crypt32 . PFXExportFlags . EXPORT_PRIVATE_KEYS |
127107 Interop . Crypt32 . PFXExportFlags . REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY ;
128108
129109 Interop . Crypt32 . PKCS12_PBES2_EXPORT_PARAMS * exportParams = null ;
130- aes256Sha256 = preferAes256Sha256 && s_supportsAes256Sha256 ;
110+ PbeParameters ? reEncodeParameters = null ;
131111
132- if ( aes256Sha256 )
112+ if ( exportParameters is Pkcs12ExportPbeParameters . Pbes2Aes256Sha256 or Pkcs12ExportPbeParameters . Default )
133113 {
134- flags |= Interop . Crypt32 . PFXExportFlags . PKCS12_EXPORT_PBES2_PARAMS ;
135- // PKCS12_PBES2_ALG_AES256_SHA256
136- char * algStr = stackalloc char [ ] { 'A' , 'E' , 'S' , '2' , '5' , '6' , '-' , 'S' , 'H' , 'A' , '2' , '5' , '6' , '\0 ' } ;
137- Interop . Crypt32 . PKCS12_PBES2_EXPORT_PARAMS p = new ( )
114+ if ( s_supportsAes256Sha256 )
138115 {
139- dwSize = ( uint ) Marshal . SizeOf < Interop . Crypt32 . PKCS12_PBES2_EXPORT_PARAMS > ( ) ,
140- hNcryptDescriptor = 0 ,
141- pwszPbes2Alg = algStr ,
142- } ;
143- exportParams = & p ;
116+ flags |= Interop . Crypt32 . PFXExportFlags . PKCS12_EXPORT_PBES2_PARAMS ;
117+ // PKCS12_PBES2_ALG_AES256_SHA256
118+ char * algStr = stackalloc char [ ] { 'A' , 'E' , 'S' , '2' , '5' , '6' , '-' , 'S' , 'H' , 'A' , '2' , '5' , '6' , '\0 ' } ;
119+ Interop . Crypt32 . PKCS12_PBES2_EXPORT_PARAMS p = new ( )
120+ {
121+ dwSize = ( uint ) Marshal . SizeOf < Interop . Crypt32 . PKCS12_PBES2_EXPORT_PARAMS > ( ) ,
122+ hNcryptDescriptor = 0 ,
123+ pwszPbes2Alg = algStr ,
124+ } ;
125+ exportParams = & p ;
126+ }
127+ else
128+ {
129+ reEncodeParameters = Helpers . WindowsAesPbe ;
130+ }
131+ }
132+ else if ( exportParameters == Pkcs12ExportPbeParameters . Pkcs12TripleDesSha1 )
133+ {
134+ // Older Windows is not guaranteed to export in 3DES. If 3DES was asked for explicitly, then re-encode
135+ // it as 3DES.
136+ reEncodeParameters = Helpers . Windows3desPbe ;
137+ }
138+ else
139+ {
140+ Debug . Assert ( exportParameters is null ) ;
144141 }
145142
146143 if ( ! Interop . Crypt32 . PFXExportCertStoreEx ( _certStore , ref dataBlob , password , exportParams , flags ) )
@@ -160,7 +157,9 @@ private unsafe byte[] ExportPkcs12(bool preferAes256Sha256, SafePasswordHandle p
160157 }
161158 }
162159
163- return pbEncoded ;
160+ return reEncodeParameters is not null ?
161+ ReEncryptAndSealPkcs12 ( pbEncoded , password , reEncodeParameters ) :
162+ pbEncoded ;
164163 }
165164
166165 private static byte [ ] ReEncryptAndSealPkcs12 ( byte [ ] pkcs12 , SafePasswordHandle password , PbeParameters newPbeParameters )
0 commit comments