Creates a simple PFX (PKCS-12) file from an X.509 certificate and (optional) encrypted private key file.
Public Declare Function PFX_MakeFile Lib "diCrPKI.dll"
(ByVal strOutputFile As String, ByVal strCertFile As String,
ByVal strKeyFile As String, ByVal strPassword As String,
ByVal strFriendlyName As String, ByVal nOptions As Long) As Long
nRet = PFX_MakeFile(strOutputFile, strCertFile, strKeyFile, strPassword, strFriendlyName, nOptions)
String with name of output file to be created.String (required) specifies the filename of the subject's X.509 certificate
(or a string containing the data in base64 representation).String specifies the filename of the subject's pkcs-8 encrypted private key
(or a string containing the data in PEM format).String containing the password for the encrypted private key.String containing a friendly name identification for the subject (optional).Long option flags:
long _stdcall PFX_MakeFile(const char *szFileOut, const char *szCertFile, const char *szKeyFile, const char *szPassword,
const char *szFriendlyName, long options);
Long: If successful, the return value is zero;
otherwise it returns a nonzero error code.
Pfx.MakeFile Method (String, String, String, String, String, Pfx.Options)
Pfx.MakeFile Method (String, String, String, String, String, Boolean)
- deprecated
[New in v3.8]
This function has been completely updated in v3.8 due to popular demand.
The default behaviour is now to save the certificate encrypted using the "standard" weak 40-bit
RC2 encryption (pbeWithSHAAnd40BitRC2-CBC) as used by Windows Certificate Manager and OpenSSL,
and the private key is re-encrypted using the "standard" strong Triple DES
algorithm (pbeWithSHAAnd3-KeyTripleDES-CBC).
The strFriendlyName parameter is now optional
and the obsolete PKI_PFX_NO_PRIVKEY option is no longer needed.
If you don't want to include the private key then just pass an empty strKeyFile parameter.
[New in v3.8:] To help users of a certain brain-dead web service in Mexico which cannot cope with anything else,
the default file format is now the exact format as would be created by OpenSSL.
If you really need Microsoft's peculiarities†, then
add the PKI_PFX_ALT_FORMAT option flag.
Any form of PKCS-12 file created by this function should be importable into
Windows Certificate Manager/Outlook (use a .pfx extension for the output file) and Mozilla/Firefox (use a .p12 extension).
The PKCS-12 standard is notorious for its peculiarities - see
PFX - How Not to Design a Crypto Protocol/Standard
[GUTPFX].
If you do not have success with your target application, try changing the options.
In particular, using the PKI_PFX_CLONE_KEY option may cause problems if the target application cannot
decrypt the super-secure algorithm you've used to protect your private key
(error messages about a missing cryptographic provider are a clue here).
That's why the default behaviour now is to re-encrypt using the "standard" algorithm.
The resulting PKCS-12 file will contain exactly one certificate and one encrypted private key,
or, if no private key is specified, then it will just contain the one certificate.
There is currently no facility to include more than one certificate or a certificate chain (.p7c) file.
If you specify both a certificate and a private key,
their RSA keys must match or a PKI_NO_MATCH_ERROR error will occur.
The PKCS-12 file will be protected using the specified strPassword, which must match the password
for the encrypted private key file, if included.
The password is optional for the case where there is just a certificate, but is required
if you need the certificate to be encrypted.
If you don't use a password for a cert-only file, just enter an empty password
when importing the PFX into Windows.
If you use the PKI_KEY_FORMAT_PEM option, the output file will be in PEM format with the
first line -----BEGIN PKCS12-----,
but, be warned, Windows does not recognise such a file as a valid PFX/PKCS-12 format!
† The only differences between the OpenSSL and Microsoft forms are the addition of a "preferredAbsent" NULL parameter to the message digest object for "sha1" and using 8 instead of 20 bytes for the MacData salt. Both combinations are perfectly valid according to the PKCS12 specification.
This example uses Bob's X.509 certificate and encrypted private key file to create a pkcs-12 file and then verifies the signature. The resulting file should be importable into Windows Certficate Manager or Mozilla with an exportable private key.
Dim strOutputFile As String Dim strCertFile As String Dim strKeyFile As String Dim strPassword As String Dim nRet As Long strOutputFile = "C:\Test\Bob1.pfx" strCertFile = "C:\Test\BobRSASignByCarl.cer" strKeyFile = "C:\Test\BobPrivRSAEncrypt.epk" strPassword = "password" ' Given Bob's certificate and encrypted private key file (with password "password"), ' create a PKCS-12 (pfx/p12) file. nRet = PFX_MakeFile(strOutputFile, strCertFile, strKeyFile, strPassword, "Bob's ID", 0) Debug.Print "PFX_MakeFile returns " & nRet ' Now verify that the signature is OK nRet = PFX_VerifySig(strOutputFile, strPassword, 0) Debug.Print "PFX_VerifySig returns " & nRet ' Clean up Call WIPE_String(strPassword, Len(strPassword))
Both functions should return zero.
The next example uses Carl's X.509 certificate to create a "certificate-only" pkcs-12 file. This is useful for importing the certificate into Mozilla/Firefox. Enter a blank password when importing.
Dim strOutputFile As String Dim strCertFile As String Dim strKeyFile As String Dim nRet As Long strOutputFile = "C:\Test\CarlNoKey.p12" strCertFile = "C:\Test\CarlRSASelf.cer" ' Given Carl's certificate only, ' create a PKCS-12 (pfx/p12) file with no private key. nRet = PFX_MakeFile(strOutputFile, strCertFile, "", "", "Carl's ID", 0) Debug.Print "PFX_MakeFile returns " & nRet
The next example in C/C++ creates a pkcs-12 file in PEM format, using key and certificate data passed as strings.
long nRet; char *outfile = "bob-pemfull.p12"; char *pfile; char *password = "password"; char *epkstr = /* From BobPrivRSAEncrypt.epk */ "-----BEGIN ENCRYPTED PRIVATE KEY-----""\n" "MIICojAcBgoqhkiG9w0BDAEDMA4ECFolTdEnFcG+AgIH0ASCAoBUZJEzzH//" "TRl5ieAHPo9q1eoMlYQu6j/eF8iIMNQ/eUp41iQIXqt9gcO2YdU5ah+ooMu4" "ef1+yMN0buWUKFLgyUTyoYdg3O8XrCB6GhCCPeTXYvt6vYs4w85HHaXMZdfz" "6dXAq3ratOVGq0PYg9dF0nI5T6Yd8S29TX4ceWyhNVG9yXAQhsRO1mMlS1tw" "aTtxME7OSsQXe4mFgqGiCTwmNA183VqXdXP+1D2IrpI2zN+JfmTvOQIQ0iU8" "ZuqBDMDRm8M/60uh2RlrfLqaIXKlF1V9PddijM6ORu8FFyPfaXkwZ7VsuvRS" "Iijpf9PNDh4J+E0Vy1lsc6r4RrZWHdc4kKwKpYalE45wME14sbvh+WCZmFfd" "D/pLZM8Or/IVHGYPFbpoAZwy+bmsjjOH/dBg6q1CY8mme9dnCBVLfXoZXTTk" "o9TOSFw4Tmd/YEH2yPylT78hw+ThNsNmG2PwUX+5yTFoI7PQA8oBg6sN4kbP" "tuRSo1fcB9RqJEO5hhqo+xAoMdhlHWdbIXOcEa1S8zLisJmgVrdAHJz6PPBl" "3LVe1LHZ/oOD8rxeal8GTTCLk4onhjr7IT+DipMJendcjIgyok5I14DiKmjt" "UPL10bt+0XkRVCIM0jma80YIGs4OMgRdW4u4n4lzJ0c1pxbvQvz8LY65OLcI" "M+6VqJCH360iN1CSLRbVBg6HqjMNEthEXExKh/b95u+sVd4qPINmsnD1DwTd" "4vkWx1zM4T+sKdz2GnBrjNRu2nJ4Nqe/krxDEKvcowh0eNllS/J86LhLYFFg" "z/JKcqq20+GPSaQALvVXK7mVKljZcKEI6YQKQMgt5+amnDixhbvppSn/my1o" "0kG3" "-----END ENCRYPTED PRIVATE KEY-----"; char *certstr = /* From BobRSASignByCarl.cer */ "-----BEGIN CERTIFICATE-----""\n" "MIICJzCCAZCgAwIBAgIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQUFADAS" "MRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDkwMloXDTM5MTIzMTIzNTk1" "OVowETEPMA0GA1UEAxMGQm9iUlNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB" "gQCp4WeYPznVX/Kgk0FepnmJhcg1XZqRW/sdAdoZcCYXD72lItA1hW16mGYUQVzP" "t7cIOwnJkbgZaTdt+WUee9mpMySjfzu7r0YBhjY0MssHA1lS/IWLMQS4zBgIFEjm" "Txz7XWDE4FwfU9N/U9hpAfEF+Hpw0b6Dxl84zxwsqmqn6wIDAQABo38wfTAMBgNV" "HRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFIDAfBgNVHSMEGDAWgBTp4JAnrHggeprT" "TPJCN04irp44uzAdBgNVHQ4EFgQU6PS4Z9izlqQq8xGqKdOVWoYWtCQwHQYDVR0R" "BBYwFIESQm9iUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4GBAHuOZsXx" "ED8QIEyIcat7QGshM/pKld6dDltrlCEFwPLhfirNnJOIh/uLt359QWHh5NZt+eIE" "VWFFvGQnRMChvVl52R1kPCHWRbBdaDOS6qzxV+WBfZjmNZGjOd539OgcOyncf1EH" "l/M28FAK3Zvetl44ESv7V+qJba3JiNiPzyvT" "-----END CERTIFICATE-----"; nRet = PFX_MakeFile(outfile, certstr, epkstr, password, "Bob's friendly ID", PKI_KEY_FORMAT_PEM); if (nRet != 0) disp_error(nRet); assert(nRet == 0); printf("Created file '%s'\n", outfile); pfile = outfile; nRet = PFX_VerifySig(pfile, password, 0); if (nRet != 0) disp_error(nRet); assert(nRet == 0); printf("Verified file '%s'\n", pfile);
PFX_VerifySig RSA_GetPrivateKeyFromPFX RSA_ReadPrivateKeyFromPFX