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 strCertList As String,
ByVal strKeyFile As String, ByVal strPassword As String,
ByVal strFriendlyName As String, ByVal nOptions As Long) As Long
nRet = PFX_MakeFile(strOutputFile, strCertList, strKeyFile, strPassword, strFriendlyName, nOptions)
long __stdcall PFX_MakeFile(const char *szFileOut, const char *szCertList, const char *szEpkFile, const char *szPassword, const char *szFriendlyName, long nOptions);
;
).""
to exclude the private key.
If successful, the return value is zero; otherwise it returns a nonzero error code.
Public Function pfxMakeFile
(szFileOut As String, szCertList As String, Optional szKeyFile As String = "", Optional szPassword As String = "", Optional szFriendlyName As String = "", Optional nOptions As Long = 0) As Long
static int dipki::Pfx::MakeFile (const std::string &fileToMake, const std::string &certList, const std::string &privateKeyFile="", const std::string &password="", const std::string &friendlyName="", Opts opts=Opts::Default)
static Pfx.make_file(outputfile, certlist, prikeyfile="", password="", friendlyname="", opts=0)
At least one certificate must be specified in the szCertList argument. Add additional certificate names (or base64 representations)
separated by a semicolon (;
).
The first certificate in the list must be the matching certificate for the private key, if included.
The default behaviour is to save the certificate(s) encrypted using the "standard" weak 40-bit
RC2 encryption (pbeWithSHAAnd40BitRC2-CBC
) as used (until recently) by Windows Certificate Manager and OpenSSL,
and the private key is re-encrypted using the "standard" TripleDES-SHA1 algorithm (pbeWithSHAAnd3-KeyTripleDES-CBC
).
[New in v12.3] Use the PKI_PFX_STRONG_CERT option to encrypt the certificate with "stronger" Triple DES, the same as the default key encryption algorithm. The PKI_PFX_PLAIN_CERT option takes precedence.
[New in v20.5] Use the PKI_PFX_AES256_SHA256 option to encrypt both the private key and certificate using "AES256-SHA256".
The szFriendlyName parameter is optional. To exclude the private key just pass an empty szKeyFile parameter.
To help users of a certain brain-dead web service in Mexico which cannot cope with anything else,
the default file format is the exact format that 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 is to re-encrypt using the "standard" algorithm.
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 szPassword, 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-----"
.
Be warned, Windows does not recognise such a file as a valid PFX/PKCS-12 format!
† The difference between the OpenSSL and Microsoft forms is that the Microsoft form has a "preferredAbsent" NULL parameter added to the message digest object for "sha1" and uses 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 = "Bob1.pfx" strCertFile = "BobRSASignByCarl.cer" strKeyFile = "BobPrivRSAEncrypt.p8e" 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 = "CarlNoKey.p12" strCertFile = "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.p8e */ "-----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