using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { /// Methods and data types found in Crypt32.dll. public static partial class Crypt32 { /// Flags for and [PInvokeData("wincrypt.h", MSDNShortId = "003602c6-d6c9-4695-9c60-ffaf0aa02266")] [Flags] public enum PFXExportFlags : uint { /// /// If a certificate is encountered that has no associated private key, the function returns FALSE with the last error set to /// either CRYPT_E_NOT_FOUND or NTE_NO_KEY. /// REPORT_NO_PRIVATE_KEY = 0x0001, /// /// If a certificate is encountered that has a non-exportable private key, the function returns FALSE and the last error set to /// NTE_BAD_KEY, NTE_BAD_KEY_STATE, or NTE_PERM. /// REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY = 0x0002, /// Private keys are exported as well as the certificates. EXPORT_PRIVATE_KEYS = 0x0004, /// /// Export all extended properties on the certificate. /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x0010, /// /// The PFX BLOB contains an embedded password that will be protected to the Active Directory (AD) protection descriptor pointed /// to by the pvPara parameter. If the szPassword parameter is not NULL or empty, the specified password is protected. If, /// however, the szPassword parameter is NULL or an empty string, a random forty (40) character password is created and protected. /// /// PFXImportCertStore uses the specified protection descriptor to decrypt the embedded password, whether specified by the user /// or randomly generated, and then uses the password to decrypt the PFX BLOB. /// /// Windows 8 and Windows Server 2012: Support for this flag begins. /// PKCS12_PROTECT_TO_DOMAIN_SIDS = 0x0020, /// PKCS12_EXPORT_SILENT = 0x0040, /// PKCS12_EXPORT_PBES2_PARAMS = 0x0080, /// PKCS12_DISABLE_ENCRYPT_CERTIFICATES = 0x0100, /// PKCS12_ENCRYPT_CERTIFICATES = 0x0200, /// PKCS12_EXPORT_ECC_CURVE_PARAMETERS = 0x1000, /// PKCS12_EXPORT_ECC_CURVE_OID = 0x2000, /// PKCS12_EXPORT_RESERVED_MASK = 0xffff0000, } /// Flags for . [PInvokeData("wincrypt.h", MSDNShortId = "2c83774a-f2df-4d28-9abd-e39aa507ba88")] [Flags] public enum PFXImportFlags : uint { /// /// Imported keys are marked as exportable. If this flag is not used, calls to the CryptExportKey function with the key handle fail. /// CRYPT_EXPORTABLE = 0x00000001, /// /// The user is to be notified through a dialog box or other method when certain attempts to use this key are made. The precise /// behavior is specified by the cryptographic service provider (CSP) being used. /// /// Prior to Internet Explorer 4.0, Microsoft cryptographic service providers ignored this flag. Starting with Internet Explorer /// 4.0, Microsoft providers support this flag. /// /// /// If the provider context was opened with the CRYPT_SILENT flag set, using this flag causes a failure and the last error is /// set to NTE_SILENT_CONTEXT. /// /// CRYPT_USER_PROTECTED = 0x00000002, /// The private keys are stored under the local computer and not under the current user. CRYPT_MACHINE_KEYSET = 0x00000020, /// /// The private keys are stored under the current user and not under the local computer even if the PFX BLOB specifies that they /// should go into the local computer. /// CRYPT_USER_KEYSET = 0x00001000, /// /// Indicates that the CNG key storage provider (KSP) is preferred. If the CSP is specified in the PFX file, then the CSP is /// used, otherwise the KSP is preferred. If the CNG KSP is unavailable, the PFXImportCertStore function will fail. /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_PREFER_CNG_KSP = 0x00000100, /// /// Indicates that the CNG KSP is always used. When specified, PFXImportCertStore attempts to use the CNG KSP irrespective of /// provider information in the PFX file. If the CNG KSP is unavailable, the import will not fail. /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_ALWAYS_CNG_KSP = 0x00000200, /// /// Allow overwrite of the existing key. Specify this flag when you encounter a scenario in which you must import a PFX file /// that contains a key name that already exists. For example, when you import a PFX file, it is possible that a container of /// the same name is already present because there is no unique namespace for key containers. If you have created a "TestKey" on /// your computer, and then you import a PFX file that also has "TestKey" as the key container, the PKCS12_ALLOW_OVERWRITE_KEY /// setting allows the key to be overwritten. /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_ALLOW_OVERWRITE_KEY = 0x00004000, /// /// Do not persist the key. Specify this flag when you do not want to persist the key. For example, if it is not necessary to /// store the key after verification, then instead of creating a container and then deleting it, you can specify this flag to /// dispose of the key immediately. /// /// Note If the PKCS12_NO_PERSIST_KEY flag is not set, keys are persisted on disk. If you do not want to persist the keys beyond /// their usage, you must delete them by calling the CryptAcquireContext function with the CRYPT_DELETEKEYSET flag set in the /// dwFlags parameter. /// /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_NO_PERSIST_KEY = 0x00008000, /// /// Import all extended properties on the certificate that were saved on the certificate when it was exported. /// Windows Server 2003 and Windows XP: This value is not supported. /// PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x0010, /// Unpack but do not persist the results. PKCS12_UNPACK_RESULTS_ONLY = 0x10000000, /// CRYPT_USER_PROTECTED_STRONG = 0x00100000, /// PKCS12_IMPORT_SILENT = 0x00000040, /// PKCS12_ONLY_CERTIFICATES = 0x00000400, /// PKCS12_ONLY_NOT_ENCRYPTED_CERTIFICATES = 0x00000800, /// PKCS12_VIRTUAL_ISOLATION_KEY = 0x00010000, /// PKCS12_IMPORT_RESERVED_MASK = 0xffff0000, /// PKCS12_OBJECT_LOCATOR_ALL_IMPORT_FLAGS = (PKCS12_ALWAYS_CNG_KSP | PKCS12_NO_PERSIST_KEY | PKCS12_IMPORT_SILENT | PKCS12_INCLUDE_EXTENDED_PROPERTIES), } /// /// The PFXExportCertStore function exports the certificates and, if available, the associated private keys from the /// referenced certificate store. This is an old function kept for compatibility with Internet Explorer 4.0 clients. New /// applications should use the PfxExportCertStoreEx function that provides enhanced private key security. /// /// Handle of the certificate store containing the certificates to be exported. /// /// A pointer to a CRYPT_DATA_BLOB structure to contain the PFX packet with the exported certificates and keys. If pPFX->pbData /// is NULL, the function calculates the number of bytes needed for the encoded BLOB and returns this in pPFX->cbData. /// When the function is called with pPFX->pbData pointing to an allocated buffer of the needed size, the function copies the /// encoded bytes into the buffer and updates pPFX->cbData with the encode byte length. /// /// /// String password used to encrypt and verify the PFX packet. When you have finished using the password, clear the password from /// memory by calling the SecureZeroMemory function. For more information about protecting passwords, see Handling Passwords. /// /// /// Flag values can be set to any combination of the following. /// /// /// Value /// Meaning /// /// /// EXPORT_PRIVATE_KEYS /// Private keys are exported as well as the certificates. /// /// /// REPORT_NO_PRIVATE_KEY /// /// If a certificate is encountered that has no associated private key, the function returns FALSE with the last error set to either /// CRYPT_E_NOT_FOUND or NTE_NO_KEY. /// /// /// /// REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY /// /// If a certificate is encountered that has a non-exportable private key, the function returns FALSE and the last error set to /// NTE_BAD_KEY, NTE_BAD_KEY_STATE, or NTE_PERM. /// /// /// /// /// /// Returns TRUE (nonzero) if the function succeeds, and FALSE (zero) if the function fails. For extended error /// information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfxexportcertstore BOOL PFXExportCertStore( HCERTSTORE // hStore, CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "003602c6-d6c9-4695-9c60-ffaf0aa02266")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PFXExportCertStore([In] HCERTSTORE hStore, ref CRYPTOAPI_BLOB pPFX, [MarshalAs(UnmanagedType.LPWStr)] string szPassword, PFXExportFlags dwFlags); /// /// The PFXExportCertStoreEx function exports the certificates and, if available, their associated private keys from the /// referenced certificate store. This function replaces the older PfxExportCertStore function. It should be used for its enhanced /// private key security. The PFX BLOB created by this function is protected by a password. /// /// Handle of the certificate store containing the certificates to be exported. /// /// A pointer to a CRYPT_DATA_BLOB structure to contain the PFX packet with the exported certificates and keys. If pPFX->pbData /// is NULL, the function calculates the number of bytes needed for the encoded BLOB and returns this in pPFX->cbData. /// When the function is called with pPFX->pbData pointing to an allocated buffer of the needed size, the function copies the /// encoded bytes into the buffer and updates pPFX->cbData with the encode byte length. /// /// /// String password used to encrypt and verify the PFX packet. When you have finished using the password, clear the password from /// memory by calling the SecureZeroMemory function. For more information about protecting passwords, see Handling Passwords. /// /// /// /// This parameter must be NULL if the dwFlags parameter does not contain PKCS12_PROTECT_TO_DOMAIN_SIDS. Prior to /// Windows 8 and Windows Server 2012, therefore, this parameter must be NULL. /// /// /// Beginning with Windows 8 and Windows Server 2012, if the dwFlags parameter contains PKCS12_PROTECT_TO_DOMAIN_SIDS, you /// can set the pvPara parameter to point to an NCRYPT_DESCRIPTOR_HANDLE value to identify which Active Directory principal /// the PFX password will be protected to inside of the PFX BLOB. Currently, the password can be protected to an Active Directory /// user, computer, or group. For more information about protection descriptors, see NCryptCreateProtectionDescriptor. /// /// /// /// Flag values can be set to any combination of the following. /// /// /// Value /// Meaning /// /// /// EXPORT_PRIVATE_KEYS 0x0004 /// Private keys are exported as well as the certificates. /// /// /// REPORT_NO_PRIVATE_KEY 0x0001 /// /// If a certificate is encountered that has no associated private key, the function returns FALSE with the last error set to either /// CRYPT_E_NOT_FOUND or NTE_NO_KEY. /// /// /// /// REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY 0x0002 /// /// If a certificate is encountered that has a non-exportable private key, the function returns FALSE and the last error set to /// NTE_BAD_KEY, NTE_BAD_KEY_STATE, or NTE_PERM. /// /// /// /// PKCS12_INCLUDE_EXTENDED_PROPERTIES 0x0010 /// Export all extended properties on the certificate. Windows Server 2003 and Windows XP: This value is not supported. /// /// /// PKCS12_PROTECT_TO_DOMAIN_SIDS 0x0020 /// /// The PFX BLOB contains an embedded password that will be protected to the Active Directory (AD) protection descriptor pointed to /// by the pvPara parameter. If the szPassword parameter is not NULL or empty, the specified password is protected. If, however, the /// szPassword parameter is NULL or an empty string, a random forty (40) character password is created and protected. /// PFXImportCertStore uses the specified protection descriptor to decrypt the embedded password, whether specified by the user or /// randomly generated, and then uses the password to decrypt the PFX BLOB. Windows 8 and Windows Server 2012: Support for this flag begins. /// /// /// /// /// /// Returns TRUE (nonzero) if the function succeeds, and FALSE (zero) if the function fails. For extended error /// information, call GetLastError. /// /// /// Beginning with Windows 8 and Windows Server 2012, you can protect the PFX password to an Active Directory user, computer, or /// group. If you choose to do so but do not create a password, a temporary password will be randomly selected. The password is /// encrypted by using the Active Directory principal and then embedded in the PFX BLOB. For more information, see the pvPara /// parameter and the PKCS12_PROTECT_TO_DOMAIN_SIDS flag. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfxexportcertstoreex BOOL PFXExportCertStoreEx( // HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, void *pvPara, DWORD dwFlags ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "e8bd54b1-946f-4c65-8a86-96f0dbec07ff")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PFXExportCertStoreEx([In] HCERTSTORE hStore, ref CRYPTOAPI_BLOB pPFX, [MarshalAs(UnmanagedType.LPWStr)] string szPassword, [In] IntPtr pvPara, PFXExportFlags dwFlags); /// /// The PFXImportCertStore function imports a PFX BLOB and returns the handle of a store that contains certificates and any /// associated private keys. /// /// /// A pointer to a CRYPT_DATA_BLOB structure that contains a PFX packet with the exported and encrypted certificates and keys. /// /// /// /// A string password used to decrypt and verify the PFX packet. Whether set to a string of length greater than zero or set to an /// empty string or to NULL, this value must be exactly the same as the value that was used to encrypt the packet. /// /// /// Beginning with Windows 8 and Windows Server 2012, if the PFX packet was created in the PFXExportCertStoreEx function by using /// the PKCS12_PROTECT_TO_DOMAIN_SIDS flag, the PFXImportCertStore function attempts to decrypt the password by using /// the Active Directory (AD) principal that was used to encrypt it. The AD principal is specified in the pvPara parameter. If the /// szPassword parameter in the PFXExportCertStoreEx function was an empty string or NULL and the dwFlags parameter /// was set to PKCS12_PROTECT_TO_DOMAIN_SIDS, that function randomly generated a password and encrypted it to the AD /// principal specified in the pvPara parameter. In that case you should set the password to the value, empty string or NULL, /// that was used when the PFX packet was created. The PFXImportCertStore function will use the AD principal to decrypt the /// random password, and the randomly generated password will be used to decrypt the PFX certificate. /// /// /// When you have finished using the password, clear it from memory by calling the SecureZeroMemory function. For more information /// about protecting passwords, see Handling Passwords. /// /// /// /// This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// CRYPT_EXPORTABLE 0x00000001 /// /// Imported keys are marked as exportable. If this flag is not used, calls to the CryptExportKey function with the key handle fail. /// /// /// /// CRYPT_USER_PROTECTED 0x00000002 /// /// The user is to be notified through a dialog box or other method when certain attempts to use this key are made. The precise /// behavior is specified by the cryptographic service provider (CSP) being used. Prior to Internet Explorer 4.0, Microsoft /// cryptographic service providers ignored this flag. Starting with Internet Explorer 4.0, Microsoft providers support this flag. /// If the provider context was opened with the CRYPT_SILENT flag set, using this flag causes a failure and the last error is set to NTE_SILENT_CONTEXT. /// /// /// /// CRYPT_MACHINE_KEYSET 0x00000020 /// The private keys are stored under the local computer and not under the current user. /// /// /// CRYPT_USER_KEYSET 0x00001000 /// /// The private keys are stored under the current user and not under the local computer even if the PFX BLOB specifies that they /// should go into the local computer. /// /// /// /// PKCS12_PREFER_CNG_KSP 0x00000100 /// /// Indicates that the CNG key storage provider (KSP) is preferred. If the CSP is specified in the PFX file, then the CSP is used, /// otherwise the KSP is preferred. If the CNG KSP is unavailable, the PFXImportCertStore function will fail. Windows Server 2003 /// and Windows XP: This value is not supported. /// /// /// /// PKCS12_ALWAYS_CNG_KSP 0x00000200 /// /// Indicates that the CNG KSP is always used. When specified, PFXImportCertStore attempts to use the CNG KSP irrespective of /// provider information in the PFX file. If the CNG KSP is unavailable, the import will not fail. Windows Server 2003 and Windows /// XP: This value is not supported. /// /// /// /// PKCS12_ALLOW_OVERWRITE_KEY 0x00004000 /// /// Allow overwrite of the existing key. Specify this flag when you encounter a scenario in which you must import a PFX file that /// contains a key name that already exists. For example, when you import a PFX file, it is possible that a container of the same /// name is already present because there is no unique namespace for key containers. If you have created a "TestKey" on your /// computer, and then you import a PFX file that also has "TestKey" as the key container, the PKCS12_ALLOW_OVERWRITE_KEY setting /// allows the key to be overwritten. Windows Server 2003 and Windows XP: This value is not supported. /// /// /// /// PKCS12_NO_PERSIST_KEY 0x00008000 /// /// Do not persist the key. Specify this flag when you do not want to persist the key. For example, if it is not necessary to store /// the key after verification, then instead of creating a container and then deleting it, you can specify this flag to dispose of /// the key immediately. Windows Server 2003 and Windows XP: This value is not supported. /// /// /// /// PKCS12_INCLUDE_EXTENDED_PROPERTIES 0x0010 /// /// Import all extended properties on the certificate that were saved on the certificate when it was exported. Windows Server 2003 /// and Windows XP: This value is not supported. /// /// /// /// 0x10000000 /// Unpack but do not persist the results. /// /// /// /// /// /// If the function succeeds, the function returns a handle to a certificate store that contains the imported certificates, /// including available private keys. /// /// /// If the function fails, that is, if the password parameter does not contain an exact match with the password used to encrypt the /// exported packet or if there were any other problems decoding the PFX BLOB, the function returns NULL, and an error code /// can be found by calling the GetLastError function. /// /// /// /// /// The PFXImportCertStore function opens a temporary store. If the function succeeds, you should close the handle to the /// store by calling the CertCloseStore function. /// /// /// When you import a certificate from the PFX packet, the CSP/KSP container name is determined by using the AttributeId with OID /// 1.3.6.1.4.1.311.17.1 of the PKCS8ShroudedKeyBag SafeBag [bagId: 1.2.840.113549.1.12.10.1.2] (see PKCS #12 for details about the /// ASN.1 structure of this). /// /// /// If the AttributeId is not present and the PREFER_CNG flag is passed, MS_KEY_STORAGE_PROVIDER is picked. If the AttributeId is /// not present and the PREFER_CNG flag is not passed, the provider name is determined based on the public key algorithm (that is, /// the public key algorithm is determined by the AlgorithmIdentifier in PKCS #8): /// /// Similarly, the key specification is determined by using the AttributeId with OID 2.5.29.15 (szOID_KEY_USAGE) as follows: /// /// If the AttributeId is not present, then the CAPI key value is set to AT_KEYEXCHANGE for RSA or DH and the algorithm is /// determined by the AlgorithmIdentifier in PKCS #8; otherwise, the algorithm is set to AT_SIGNATURE. For the CNG key value, all /// ncrypt key usage is set. /// /// /// Note If an invalid provider name is present in the PFX packet, or the base or enhanced cryptography provider is not /// present in this registry key: HKEY_LOCAL_MACHINE\ SOFTWARE\ Microsoft\ Cryptography\ /// Defaults\ Provider, then a provider lookup is performed by the provider type using this registry subkey: /// HKEY_LOCAL_MACHINE\ SOFTWARE\ Microsoft\ Cryptography\ Defaults\ Provider Types. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfximportcertstore HCERTSTORE PFXImportCertStore( // CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "2c83774a-f2df-4d28-9abd-e39aa507ba88")] public static extern HCERTSTORE PFXImportCertStore(in CRYPTOAPI_BLOB pPFX, [MarshalAs(UnmanagedType.LPWStr)] string szPassword, PFXImportFlags dwFlags); /// The PFXIsPFXBlob function attempts to decode the outer layer of a BLOB as a PFX packet. /// A pointer to a CRYPT_DATA_BLOB structure that the function will attempt to decode as a PFX packet. /// /// The function returns TRUE if the BLOB can be decoded as a PFX packet. If the outer layer of the BLOB cannot be decoded as /// a PFX packet, the function returns FALSE. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfxispfxblob BOOL PFXIsPFXBlob( CRYPT_DATA_BLOB *pPFX ); [DllImport(Lib.Crypt32, SetLastError = false, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "28984407-0a28-48e1-9d67-37a6e9db7601")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PFXIsPFXBlob(in CRYPTOAPI_BLOB pPFX); /// /// /// The PFXVerifyPassword function attempts to decode the outer layer of a BLOB as a Personal Information Exchange (PFX) /// packet and to decrypt it with the given password. No data from the BLOB is imported. /// /// The PFX format is also known as the Public-Key Cryptography Standards #12 (PKCS #12) format. /// /// A pointer to a CRYPT_DATA_BLOB structure that the function will attempt to decode as a PFX packet. /// /// /// String password to be checked. For this function to succeed, this password must be exactly the same as the password used to /// encrypt the packet. /// /// /// If you set this value to an empty string or NULL, this function typically attempts to decrypt the password embedded in /// the PFX BLOB by using the empty string or NULL. /// /// /// However, beginning with Windows 8 and Windows Server 2012, if a NULL or empty password was specified when the PFX BLOB /// was created and the application also specified that the password should be protected to an Active Directory (AD) principal, the /// Cryptography API (CAPI) randomly generates a password, encrypts it to the AD principal and embeds it in the PFX BLOB. The /// PFXVerifyPassword function will then try to use the specified AD principal (current user, computer, or AD group member) /// to decrypt the password. For more information about protecting PFX to an AD principal, see the pvPara parameter and the /// PKCS12_PROTECT_TO_DOMAIN_SIDS flag of the PFXExportCertStoreEx function. /// /// /// When you have finished using the password, clear the password from memory by calling the SecureZeroMemory function. For more /// information about protecting passwords, see Handling Passwords. /// /// /// Reserved for future use. /// The function return TRUE if the password appears correct; otherwise, it returns FALSE. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfxverifypassword BOOL PFXVerifyPassword( CRYPT_DATA_BLOB // *pPFX, LPCWSTR szPassword, DWORD dwFlags ); [DllImport(Lib.Crypt32, SetLastError = false, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "47560192-547e-4440-9f10-43327355e1a0")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PFXVerifyPassword(in CRYPTOAPI_BLOB pPFX, [MarshalAs(UnmanagedType.LPWStr)] string szPassword, uint dwFlags = 0); } }