CryptoSys PKI Toolkit Manual

PFX_MakeFile

Creates a simple PFX (PKCS-12) file from an X.509 certificate and (optional) encrypted private key file.

VB6/VBA Syntax

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)

Parameters

strOutputFile
[in] String with name of output file to be created.
strCertFile
[in] String (required) specifies the filename of the subject's X.509 certificate (or a string containing the data in base64 representation).
strKeyFile
[in] String specifies the filename of the subject's pkcs-8 encrypted private key (or a string containing the data in PEM format).
strPassword
[in] String containing the password for the encrypted private key.
strFriendlyName
[in] String containing a friendly name identification for the subject (optional).
nOptions
[in] Long option flags:
PKI_DEFAULT (0) for default options
PKI_KEY_FORMAT_PEM to create the output file in PEM format (default is DER-encoded binary)
PKI_PFX_PLAIN_CERT to store the certificate in unencrypted form (default is encrypted)
PKI_PFX_CLONE_KEY to store the private key in the exact form of the pkcs-8 input file (default is to re-encrypt)
PKI_PFX_ALT_FORMAT to create a PFX file with the exact peculiarities used by Microsoft (default is OpenSSL)

C/C++ Syntax

long _stdcall PFX_MakeFile(const char *szFileOut, const char *szCertFile, const char *szKeyFile, const char *szPassword, const char *szFriendlyName, long options);

Returns (VB6/C)

Long: If successful, the return value is zero; otherwise it returns a nonzero error code.

.NET Equivalent

Pfx.MakeFile Method (String, String, String, String, String, Pfx.Options)
Pfx.MakeFile Method (String, String, String, String, String, Boolean) - deprecated

Remarks

[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.

Example

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

See Also

PFX_VerifySig RSA_GetPrivateKeyFromPFX RSA_ReadPrivateKeyFromPFX

[Contents] [Index]

[HOME]   [NEXT: PFX_VerifySig...]

Copyright © 2004-12 D.I. Management Services Pty Ltd. All rights reserved.