using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
/// Methods and data types found in Crypt32.dll.
public static partial class Crypt32
{
/// The CRYPT_ENUM_KEYID_PROP callback function is used with the CryptEnumKeyIdentifierProperties function.
///
/// Reserved for future use and must be zero.
///
///
/// Count of elements in the array of rgdwPropId
///
///
///
/// Returns TRUE if the function succeeds, FALSE if it fails.
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nc-wincrypt-pfn_crypt_enum_keyid_prop PFN_CRYPT_ENUM_KEYID_PROP
// PfnCryptEnumKeyidProp; BOOL PfnCryptEnumKeyidProp( const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwFlags, void *pvReserved, void
// *pvArg, DWORD cProp, DWORD *rgdwPropId, void **rgpvData, DWORD *rgcbData ) {...}
[PInvokeData("wincrypt.h", MSDNShortId = "c4461b79-d216-4d4a-bd5d-9260ec897c14")]
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool PFN_CRYPT_ENUM_KEYID_PROP([In, Optional] IntPtr pKeyIdentifier, [Optional] uint dwFlags, [Optional] IntPtr pvReserved, [Optional] IntPtr pvArg, uint cProp, [In] uint[] rgdwPropId, [In] IntPtr[] rgpvData, [In] uint[] rgcbData);
/// Blob type specifier for PUBLICKEYSTRUC.
[PInvokeData("wincrypt.h", MSDNShortId = "99d41222-b4ca-40f3-a240-52b0a9b3a9aa")]
public enum BlobType : uint
{
/// The BLOB is a key state BLOB.
KEYSTATEBLOB = 0xC,
/// The key is a session key.
OPAQUEKEYBLOB = 0x9,
/// The key is a session key.
PLAINTEXTKEYBLOB = 0x8,
/// The key is a public/private key pair.
PRIVATEKEYBLOB = 0x7,
/// The key is a public key.
PUBLICKEYBLOB = 0x6,
/// The key is a public key.
PUBLICKEYBLOBEX = 0xA,
/// The key is a session key.
SIMPLEBLOB = 0x1,
/// The key is a session key.
SYMMETRICWRAPKEYBLOB = 0xB,
}
/// Flags for CertFindUsage functions.
[PInvokeData("wincrypt.h", MSDNShortId = "eda6d875-df62-4f40-8734-a91666dba289")]
[Flags]
public enum CertFindUsageFlags : uint
{
///
/// When this flag is set, in addition to usual matches, any certificate that has neither the enhanced key usage extension nor
/// the enhanced key usage property meets the search criteria.
///
CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG = 0x1,
///
/// When this flag is set, the matching process involves only the extension usage identifiers. If pvFindPara is NULL or the
/// cUsageIdentifier member of the CERT_ENHKEY_USAGE structure pointed to by pvFindPara is zero, any certificate having an
/// enhanced key usage extension is a match. If CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG is also set, any certificate without the
/// enhanced key usage extension is also a match. If CERT_FIND_NO_ENHKEY_USAGE_FLAG is also set, only certificates without the
/// enhanced key usage extension are matches.
///
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = 0x2,
///
/// When this flag is set, the matching process involves only usage identifiers that are properties. If pvFindPara is NULL or
/// cUsageIdentifier is set to zero, any certificate having an enhanced key usage property is a match. If
/// CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG is also set, any certificate without the enhanced key usage property is also a match.
/// If CERT_FIND_NO_ENHKEY_USAGE_FLAG is set, only certificates without the enhanced key usage property are matches.
///
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = 0x4,
///
/// When this flag is set, only those certificates that have neither an enhanced key usage nor the enhanced key usage property
/// are matches. This flag setting takes precedence over pvFindPara being NULL.
///
CERT_FIND_NO_ENHKEY_USAGE_FLAG = 0x8,
///
/// The search criteria can be altered by setting one or more flags. By default, if the pszUsageIdentifier member of the
/// CERT_ENHKEY_USAGE structure pointed to by pvFindPara is to be matched, each identifier must be matched to satisfy the search
/// criteria. However, if CERT_FIND_OR_ENHKEY_USAGE_FLAG is set, a match can be made to all identifiers combined by using a
/// bitwise-OR operation; thus, matching any one of the identifiers is sufficient.
///
CERT_FIND_OR_ENHKEY_USAGE_FLAG = 0x10,
///
/// When this flag is set, the function only matches those certificates that are valid for the specified usage. By default, in
/// order to match, a certificate must be valid for all usages.
///
/// CERT_FIND_OR_ENHKEY_USAGE_FLAG can also be set if the certificate only needs to be valid for one of the specified usages.
/// Note that CertGetValidUsages is called to get the list of valid uses for the certificate. Only
/// CERT_FIND_OR_ENHKEY_USAGE_FLAG can also apply when CERT_FIND_VALID_ENHKEY_USAGE_FLAG is set.
///
///
CERT_FIND_VALID_ENHKEY_USAGE_FLAG = 0x20,
}
/// Flags for .
[PInvokeData("wincrypt.h", MSDNShortId = "6e57d935-4cfb-44af-b1c6-6c399c959452")]
[Flags]
public enum CryptKeyIdFlags
{
///
/// The list of key identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if
/// pwszComputerName is not NULL) is searched.
///
CRYPT_KEYID_MACHINE_FLAG = 0x00000020,
///
/// When set, pvData is updated with a pointer to allocated memory. LocalFree() must be called to free the allocated memory.
///
CRYPT_KEYID_ALLOC_FLAG = 0x00008000,
/// The key identifier and all of its properties are deleted.
CRYPT_KEYID_DELETE_FLAG = 0x00000010,
///
/// Sets a new key identifier property. If the property already exists, the attempt fails, and FALSE is returned with the last
/// error code set to CRYPT_E_EXISTS.
///
CRYPT_KEYID_SET_NEW_FLAG = 0x00002000,
}
///
/// The CertAddEnhancedKeyUsageIdentifier function adds a usage identifier object identifier (OID) to the enhanced key usage
/// (EKU) extended property of the certificate.
///
/// A pointer to the CERT_CONTEXT of the certificate for which the usage identifier is to be added.
/// Specifies the usage identifier OID to add.
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certaddenhancedkeyusageidentifier BOOL
// CertAddEnhancedKeyUsageIdentifier( PCCERT_CONTEXT pCertContext, LPCSTR pszUsageIdentifier );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "1bec8d2f-aa43-4a8b-9414-c3a4e5fcb470")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CertAddEnhancedKeyUsageIdentifier([In] PCCERT_CONTEXT pCertContext, SafeOID pszUsageIdentifier);
///
/// The CertGetEnhancedKeyUsage function returns information from the enhanced key usage (EKU) extension or the EKU extended
/// property of a certificate. EKUs indicate valid uses of the certificate.
///
/// A pointer to a CERT_CONTEXT certificate context.
///
///
/// Indicates whether the function will report on extensions of a certificate, its extended properties, or both. If set to zero, the
/// function returns the valid uses of a certificate based on both the EKU extension and the EKU extended property value of the certificate.
///
/// To return only the EKU extension or EKU property value, set the following flags.
///
///
/// Value
/// Meaning
///
/// -
/// CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
/// Get only the extension.
///
/// -
/// CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
/// Get only the extended property value.
///
///
///
///
///
/// A pointer to a CERT_ENHKEY_USAGE structure ( CERT_ENHKEY_USAGE is an alternate typedef name for the CTL_USAGE
/// structure) that receives the valid uses of the certificate.
///
///
/// This parameter can be NULL to set the size of the key usage for memory allocation purposes. For more information, see
/// Retrieving Data of Unknown Length.
///
///
///
/// A pointer to a DWORD that specifies the size, in bytes, of the structure pointed to by pUsage. When the function returns,
/// the DWORD contains the size, in bytes, of the structure.
///
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE).
///
///
///
/// If a certificate has an EKU extension, that extension lists object identifiers (OIDs) for valid uses of that certificate. In a
/// Microsoft environment, a certificate might also have EKU extended properties that specify valid uses for the certificate.
///
///
/// -
/// If a certificate has neither an EKU extension nor EKU extended properties, it is assumed to be valid for all uses.
///
/// -
///
/// If it has either an EKU extension or EKU extended properties but not both, it is valid only for the uses indicated in the
/// extension or extended properties that it has.
///
///
/// -
///
/// If a certificate has both an EKU extension and EKU extended properties, it is valid only for the uses that are on both lists.
///
///
///
///
/// If dwFlags is set to zero, the cUsageIdentifier member of the CERT_ENHKEY_USAGE structure is set to the number of
/// valid uses of the certificate determined by the value of both the EKU extension and the EKU extended property value.
///
///
/// If the cUsageIdentifier member is zero, the certificate might be valid for all uses or the certificate might have no
/// valid uses. The return from a call to GetLastError can be used to determine whether the certificate is good for all uses or for
/// none. If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is good for all uses. If it returns zero, the
/// certificate has no valid uses.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetenhancedkeyusage BOOL CertGetEnhancedKeyUsage(
// PCCERT_CONTEXT pCertContext, DWORD dwFlags, PCERT_ENHKEY_USAGE pUsage, DWORD *pcbUsage );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "eda6d875-df62-4f40-8734-a91666dba289")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CertGetEnhancedKeyUsage(PCCERT_CONTEXT pCertContext, CertFindUsageFlags dwFlags, [Out] IntPtr pUsage, ref uint pcbUsage);
///
/// The CertRemoveEnhancedKeyUsageIdentifier function removes a usage identifier object identifier (OID) from the enhanced
/// key usage (EKU) extended property of the certificate.
///
/// A pointer to a CERT_CONTEXT of the certificate for which the usage identifier OID is to be removed.
/// A pointer to the usage identifier OID to remove.
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certremoveenhancedkeyusageidentifier BOOL
// CertRemoveEnhancedKeyUsageIdentifier( PCCERT_CONTEXT pCertContext, LPCSTR pszUsageIdentifier );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "4fb27073-674c-4bac-9a62-6e33e1a5785e")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CertRemoveEnhancedKeyUsageIdentifier(PCCERT_CONTEXT pCertContext, SafeOID pszUsageIdentifier);
///
/// The CertSetEnhancedKeyUsage function sets the enhanced key usage (EKU) property for the certificate. Use of this function
/// replaces any EKUs associated with the certificate. To add a single EKU usage without changing existing usages, use
/// CertAddEnhancedKeyUsageIdentifier. To delete a single EKU usage, use CertRemoveEnhancedKeyUsageIdentifier.
///
/// A pointer to the CERT_CONTEXT of the specified certificate.
///
/// Pointer to a CERT_ENHKEY_USAGE structure (equivalent to a CTL_USAGE structure) that contains an array of EKU object
/// identifiers (OIDs) to be set as extended properties of the certificate.
///
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certsetenhancedkeyusage BOOL CertSetEnhancedKeyUsage(
// PCCERT_CONTEXT pCertContext, PCERT_ENHKEY_USAGE pUsage );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "423b0232-846e-4e40-bc42-d30c48c548da")]
[return: MarshalAs(UnmanagedType.Bool)] public static extern bool CertSetEnhancedKeyUsage(PCCERT_CONTEXT pCertContext, in CTL_USAGE pUsage);
///
/// This function converts a PUBLICKEYSTRUC of a CSP into an X.509 CERT_PUBLIC_KEY_INFO structure and encodes it. The encoded
/// structure is then hashed with the SHA1 algorithm to obtain the key identifier.
///
///
///
/// Specifies the encoding type used. It is always acceptable to specify both the certificate and message encoding types by
/// combining them with a bitwise- OR operation as shown in the following example:
///
/// X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
/// Currently defined encoding types are:
///
/// -
/// X509_ASN_ENCODING
///
/// -
/// PKCS_7_ASN_ENCODING
///
///
///
///
/// A pointer to the public key object identifier (OID). A value that is not NULL overrides the default OID obtained from the
/// aiKeyAlg member of the structure pointed to by pPubKeyStruc. To use the default OID, set pszPubKeyOID to NULL.
///
///
/// A pointer to a PUBLICKEYSTRUC structure. In the default case, the aiKeyAlg member of the structure pointed to by
/// pPubKeyStruc is used to find the public key OID. When the value of pszPubKeyOID is not NULL, it overrides the default.
///
/// The size, in bytes, of the PUBLICKEYSTRUC.
/// Reserved for future use and must be zero.
/// Reserved for future use and must be NULL.
///
/// A pointer to a buffer to receive the hash of the public key and the key identifier.
///
/// To get the size of this information for memory allocation purposes, set this parameter to NULL. For more information, see
/// Retrieving Data of Unknown Length.
///
///
///
/// A pointer to a DWORD that specifies the size, in bytes, of the buffer pointed to by the pbHash parameter. When the
/// function returns, the DWORD contains the number of bytes stored in the buffer. Using SHA1 hashing, the length of the
/// required buffer is twenty.
///
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptcreatekeyidentifierfromcsp BOOL
// CryptCreateKeyIdentifierFromCSP( DWORD dwCertEncodingType, LPCSTR pszPubKeyOID, const PUBLICKEYSTRUC *pPubKeyStruc, DWORD
// cbPubKeyStruc, DWORD dwFlags, void *pvReserved, BYTE *pbHash, DWORD *pcbHash );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "628e1995-8207-4daa-a445-cb21a755ffa6")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptCreateKeyIdentifierFromCSP(CertEncodingType dwCertEncodingType, [Optional] SafeOID pszPubKeyOID,
in PUBLICKEYSTRUC pPubKeyStruc, uint cbPubKeyStruc, uint dwFlags, [Optional] IntPtr pvReserved, [Out] IntPtr pbHash, ref uint pcbHash);
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to data to be passed to the callback function. The type is a void that allows the application to declare, define, and
/// initialize a structure or argument to hold any information.
///
///
/// A pointer to an application-defined callback function that is executed for each key identifier entry that matches the input
/// parameters. For details about the callback functions parameters, see CRYPT_ENUM_KEYID_PROP.
///
///
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
///
///
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to data to be passed to the callback function. The type is a void that allows the application to declare, define, and
/// initialize a structure or argument to hold any information.
///
///
/// A pointer to an application-defined callback function that is executed for each key identifier entry that matches the input
/// parameters. For details about the callback functions parameters, see CRYPT_ENUM_KEYID_PROP.
///
///
///
/// The CryptEnumKeyIdentifierProperties function repeatedly calls the CRYPT_ENUM_KEYID_PROP callback function until the last
/// key identifier is enumerated or the callback function returns FALSE.
///
/// If the main function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
/// To continue enumeration, the function returns TRUE.
/// To stop enumeration, the function returns FALSE and sets the last error code.
///
///
/// A key identifier can have the same properties as a certificate context.
/// Examples
/// For an example that uses this function, see Example C Program: Working with Key Identifiers.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptenumkeyidentifierproperties BOOL
// CryptEnumKeyIdentifierProperties( const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwPropId, DWORD dwFlags, LPCWSTR pwszComputerName,
// void *pvReserved, void *pvArg, PFN_CRYPT_ENUM_KEYID_PROP pfnEnum );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "6e57d935-4cfb-44af-b1c6-6c399c959452")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptEnumKeyIdentifierProperties(in CRYPTOAPI_BLOB pKeyIdentifier, [In, Optional] uint dwPropId, CryptKeyIdFlags dwFlags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string pwszComputerName, [In, Optional] IntPtr pvReserved, [In, Optional] IntPtr pvArg,
[MarshalAs(UnmanagedType.FunctionPtr)] PFN_CRYPT_ENUM_KEYID_PROP pfnEnum);
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to data to be passed to the callback function. The type is a void that allows the application to declare, define, and
/// initialize a structure or argument to hold any information.
///
///
/// A pointer to an application-defined callback function that is executed for each key identifier entry that matches the input
/// parameters. For details about the callback functions parameters, see CRYPT_ENUM_KEYID_PROP.
///
///
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
///
///
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to data to be passed to the callback function. The type is a void that allows the application to declare, define, and
/// initialize a structure or argument to hold any information.
///
///
/// A pointer to an application-defined callback function that is executed for each key identifier entry that matches the input
/// parameters. For details about the callback functions parameters, see CRYPT_ENUM_KEYID_PROP.
///
///
///
/// The CryptEnumKeyIdentifierProperties function repeatedly calls the CRYPT_ENUM_KEYID_PROP callback function until the last
/// key identifier is enumerated or the callback function returns FALSE.
///
/// If the main function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
/// To continue enumeration, the function returns TRUE.
/// To stop enumeration, the function returns FALSE and sets the last error code.
///
///
/// A key identifier can have the same properties as a certificate context.
/// Examples
/// For an example that uses this function, see Example C Program: Working with Key Identifiers.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptenumkeyidentifierproperties BOOL
// CryptEnumKeyIdentifierProperties( const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwPropId, DWORD dwFlags, LPCWSTR pwszComputerName,
// void *pvReserved, void *pvArg, PFN_CRYPT_ENUM_KEYID_PROP pfnEnum );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "6e57d935-4cfb-44af-b1c6-6c399c959452")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptEnumKeyIdentifierProperties([In, Optional] IntPtr pKeyIdentifier, [In, Optional] uint dwPropId, CryptKeyIdFlags dwFlags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string pwszComputerName, [In, Optional] IntPtr pvReserved, [In, Optional] IntPtr pvArg,
[MarshalAs(UnmanagedType.FunctionPtr)] PFN_CRYPT_ENUM_KEYID_PROP pfnEnum);
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to data to be passed to the callback function. The type is a void that allows the application to declare, define, and
/// initialize a structure or argument to hold any information.
///
///
/// A pointer to an application-defined callback function that is executed for each key identifier entry that matches the input
/// parameters. For details about the callback functions parameters, see CRYPT_ENUM_KEYID_PROP.
///
///
///
/// A pointer to a CRYPT_HASH_BLOB structure that contains the key identifier.
/// If pKeyIdentifier is NULL, the function enumerates all key identifiers.
/// If pKeyIdentifier is not NULL, the callback function pfnEnum is only called for the specified key identifier.
///
///
/// Indicates the property identifier to be listed.
/// If dwPropId is set to zero, this function calls the callback function with all the properties.
///
/// If dwPropId is not zero and pKeyIdentifier is NULL, the callback function is called only for those key identifiers that
/// have the specified property (sets the cProp parameter of pfnEnum to one). All key identifiers that do not have the property are skipped.
///
/// Any certificate property identifier can be used.
///
///
/// By default, the list of key identifiers for the CurrentUser is searched. If CRYPT_KEYID_MACHINE_FLAG is set, the list of key
/// identifiers of the LocalMachine (if pwszComputerName is NULL) or of a remote computer (if pwszComputerName is not
/// NULL) is searched. For more information, see pwszComputerName.
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG is set in dwFlags, the remote computer is
/// searched for a list of key identifiers. If the local computer is to be searched and not a remote computer, pwszComputerName is
/// set to NULL.
///
/// A sequence of tuples containing the key identifier and an array of property identifiers and values as byte arrays.
public static IEnumerable<(byte[] keyId, (uint propId, byte[] data)[] props)> CryptEnumKeyIdentifierProperties(CRYPTOAPI_BLOB? pKeyIdentifier = null,
uint dwPropId = 0, CryptKeyIdFlags dwFlags = CryptKeyIdFlags.CRYPT_KEYID_MACHINE_FLAG, string pwszComputerName = null)
{
List<(byte[] keyId, (uint propId, byte[] data)[] props)> output = new();
using SafeCoTaskMemStruct pKeyId = pKeyIdentifier.HasValue ? new(pKeyIdentifier.Value) : SafeCoTaskMemStruct.Null;
Win32Error.ThrowLastErrorIfFalse(CryptEnumKeyIdentifierProperties(pKeyId, dwPropId, dwFlags, pwszComputerName, default, default, fn));
return output;
unsafe bool fn(IntPtr pKeyIdentifier, uint dwFlags, IntPtr pvReserved, IntPtr pvArg, uint cProp, uint[] rgdwPropId, IntPtr[] rgpvData, uint[] rgcbData)
{
try
{
var id = pKeyIdentifier == IntPtr.Zero ? null : ((CRYPTOAPI_BLOB*)(void*)pKeyIdentifier)->GetBytes();
var props = new (uint propId, byte[] data)[(int)cProp];
for (uint i = 0; i < cProp; i++)
props[i] = (rgdwPropId[i], rgpvData[i].AsReadOnlySpan((int)rgcbData[i]).ToArray());
output.Add((id, props));
return true;
}
catch { }
return false;
}
}
///
/// A pointer to the CRYPT_HASH_BLOB that contains the key identifier.
///
/// Identifies the property to retrieve. The value of dwPropId determines the type and content of the pvData parameter. Any
/// certificate property ID can be used.
///
/// The following flags can be used. They can be combined with a bitwise- OR operation.
///
///
/// Value
/// Meaning
///
/// -
/// CRYPT_KEYID_MACHINE_FLAG
///
/// Search the list of key identifiers of the LocalMachine (if pwszComputerName is NULL) or remote computer (if pwszComputerName is
/// not NULL). For more information, see pwszComputerName.
///
///
/// -
/// CRYPT_KEYID_ALLOC_FLAG
///
/// The LocalAlloc() function is called to allocate memory for pvData. *pvData is updated with a pointer to the allocated memory.
/// LocalFree() must be called to free the allocated memory.
///
///
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG flag is set, searches the remote computer
/// for a list of key identifiers. If the local computer is to be searched and not a remote computer, set pwszComputerName to NULL.
///
/// Reserved for future use and must be NULL.
///
/// A pointer to a buffer to receive the data as determined by dwPropId. Elements pointed to by fields in the pvData structure
/// follow the structure. Therefore, the size contained in pcbData can exceed the size of the structure.
///
///
/// If dwPropId is CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_KEY_PROV_INFO structure that contains the property of the
/// key identifier.
///
///
/// If dwPropId is not CERT_KEY_PROV_INFO_PROP_ID, pvData points to an array of bytes that contains the property of the key identifier.
///
///
/// To get the size of this information for memory allocation purposes, this parameter can be NULL when the
/// CRYPT_KEYID_ALLOC_FLAG is not set. For more information, see Retrieving Data of Unknown Length.
///
///
/// When the CRYPT_KEYID_ALLOC_FLAG is set, pvData is the address of a pointer to the buffer that will be updated. Because memory is
/// allocated and its pointer is stored at *pvData, pvData must not be NULL.
///
///
/// A pointer to a DWORD that contains the size, in bytes, of the buffer pointed to by the pvData parameter. When the
/// function returns, the DWORD contains the number of bytes stored in the buffer. The size contained in the variable pointed
/// to by pcbData can indicate a size larger than the CRYPT_KEY_PROV_INFO structure because the structure can contain pointers to
/// auxiliary data. This size is the sum of the size needed by the structure and all auxiliary data.
///
/// When the CRYPT_KEYID_ALLOC_FLAG is set, pcbData is the address of a pointer to the DWORD that will be updated.
///
/// Note When processing the data returned in the buffer, applications need to use the actual size of the data returned. The
/// actual size can be slightly smaller than the size of the buffer specified on input. On input, buffer sizes are usually specified
/// large enough to ensure that the largest possible output data fits in the buffer. On output, the variable pointed to by this
/// parameter is updated to reflect the actual size of the data copied to the buffer.
///
///
/// A pointer to the CRYPT_HASH_BLOB that contains the key identifier.
///
/// Identifies the property to retrieve. The value of dwPropId determines the type and content of the pvData parameter. Any
/// certificate property ID can be used.
///
///
/// The following flags can be used. They can be combined with a bitwise- OR operation.
///
///
/// Value
/// Meaning
///
/// -
/// CRYPT_KEYID_MACHINE_FLAG
///
/// Search the list of key identifiers of the LocalMachine (if pwszComputerName is NULL) or remote computer (if pwszComputerName is
/// not NULL). For more information, see pwszComputerName.
///
///
/// -
/// CRYPT_KEYID_ALLOC_FLAG
///
/// The LocalAlloc() function is called to allocate memory for pvData. *pvData is updated with a pointer to the allocated memory.
/// LocalFree() must be called to free the allocated memory.
///
///
///
///
///
/// A pointer to the name of a remote computer to be searched. If CRYPT_KEYID_MACHINE_FLAG flag is set, searches the remote computer
/// for a list of key identifiers. If the local computer is to be searched and not a remote computer, set pwszComputerName to NULL.
///
/// Reserved for future use and must be NULL.
///
///
/// A pointer to a buffer to receive the data as determined by dwPropId. Elements pointed to by fields in the pvData structure
/// follow the structure. Therefore, the size contained in pcbData can exceed the size of the structure.
///
///
/// If dwPropId is CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_KEY_PROV_INFO structure that contains the property of the
/// key identifier.
///
///
/// If dwPropId is not CERT_KEY_PROV_INFO_PROP_ID, pvData points to an array of bytes that contains the property of the key identifier.
///
///
/// To get the size of this information for memory allocation purposes, this parameter can be NULL when the
/// CRYPT_KEYID_ALLOC_FLAG is not set. For more information, see Retrieving Data of Unknown Length.
///
///
/// When the CRYPT_KEYID_ALLOC_FLAG is set, pvData is the address of a pointer to the buffer that will be updated. Because memory is
/// allocated and its pointer is stored at *pvData, pvData must not be NULL.
///
///
///
///
/// A pointer to a DWORD that contains the size, in bytes, of the buffer pointed to by the pvData parameter. When the
/// function returns, the DWORD contains the number of bytes stored in the buffer. The size contained in the variable pointed
/// to by pcbData can indicate a size larger than the CRYPT_KEY_PROV_INFO structure because the structure can contain pointers to
/// auxiliary data. This size is the sum of the size needed by the structure and all auxiliary data.
///
/// When the CRYPT_KEYID_ALLOC_FLAG is set, pcbData is the address of a pointer to the DWORD that will be updated.
///
/// Note When processing the data returned in the buffer, applications need to use the actual size of the data returned. The
/// actual size can be slightly smaller than the size of the buffer specified on input. On input, buffer sizes are usually specified
/// large enough to ensure that the largest possible output data fits in the buffer. On output, the variable pointed to by this
/// parameter is updated to reflect the actual size of the data copied to the buffer.
///
///
///
/// If the function succeeds, the function returns nonzero ( TRUE).
/// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError.
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgetkeyidentifierproperty BOOL
// CryptGetKeyIdentifierProperty( const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwPropId, DWORD dwFlags, LPCWSTR pwszComputerName,
// void *pvReserved, void *pvData, DWORD *pcbData );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "bc0511c1-0699-4959-afd7-a838c91c77d5")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetKeyIdentifierProperty(in CRYPTOAPI_BLOB pKeyIdentifier, uint dwPropId, CryptKeyIdFlags dwFlags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string pwszComputerName, [Optional] IntPtr pvReserved, [Out, Optional] IntPtr pvData, ref uint pcbData);
///
/// A pointer to a CRYPT_HASH_BLOB containing the key identifier.
///
/// Identifies the property to be set. The value of dwPropId determines the type and content of the pvData parameter. Any
/// certificate property ID can be used. CERT_KEY_PROV_INFO_PROP_ID is the property of most interest.
///
/// The following flags can be set. They can be combined with a bitwise- OR operation.
///
///
/// Value
/// Meaning
///
/// -
/// CRYPT_KEYID_MACHINE_FLAG
///
/// Sets the property of the LocalMachine (if pwszComputerName is NULL) or remote computer (if pwszComputerName is not NULL). For
/// more information, see pwszComputerName.
///
///
/// -
/// CRYPT_KEYID_DELETE_FLAG
/// The key identifier and all of its properties are deleted.
///
/// -
/// CRYPT_KEYID_SET_NEW_FLAG
///
/// Sets a new key identifier property. If the property already exists, the attempt fails, and FALSE is returned with the last error
/// code set to CRYPT_E_EXISTS.
///
///
///
///
/// A pointer to a null-terminated string that contains the name of a remote computer that has the key identifier where the
/// properties are set. If CRYPT_KEYID_MACHINE_FLAG flag is set, searches the remote computer for a list of key identifiers. If the
/// local computer is to be set and not a remote computer, set pwszComputerName to NULL.
///
/// Reserved for future use and must be NULL.
///
/// If dwPropId is CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_KEY_PROV_INFO structure containing the property of the key identifier.
///
///
/// If dwPropId is not CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_DATA_BLOB structure containing the property of the key identifier.
///
/// Setting pvData to NULL deletes the property.
///
/// A pointer to a CRYPT_HASH_BLOB containing the key identifier.
///
/// Identifies the property to be set. The value of dwPropId determines the type and content of the pvData parameter. Any
/// certificate property ID can be used. CERT_KEY_PROV_INFO_PROP_ID is the property of most interest.
///
///
/// The following flags can be set. They can be combined with a bitwise- OR operation.
///
///
/// Value
/// Meaning
///
/// -
/// CRYPT_KEYID_MACHINE_FLAG
///
/// Sets the property of the LocalMachine (if pwszComputerName is NULL) or remote computer (if pwszComputerName is not NULL). For
/// more information, see pwszComputerName.
///
///
/// -
/// CRYPT_KEYID_DELETE_FLAG
/// The key identifier and all of its properties are deleted.
///
/// -
/// CRYPT_KEYID_SET_NEW_FLAG
///
/// Sets a new key identifier property. If the property already exists, the attempt fails, and FALSE is returned with the last error
/// code set to CRYPT_E_EXISTS.
///
///
///
///
///
/// A pointer to a null-terminated string that contains the name of a remote computer that has the key identifier where the
/// properties are set. If CRYPT_KEYID_MACHINE_FLAG flag is set, searches the remote computer for a list of key identifiers. If the
/// local computer is to be set and not a remote computer, set pwszComputerName to NULL.
///
/// Reserved for future use and must be NULL.
///
///
/// If dwPropId is CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_KEY_PROV_INFO structure containing the property of the key identifier.
///
///
/// If dwPropId is not CERT_KEY_PROV_INFO_PROP_ID, pvData points to a CRYPT_DATA_BLOB structure containing the property of the key identifier.
///
/// Setting pvData to NULL deletes the property.
///
///
/// If the function succeeds, the return value is nonzero (TRUE).
/// If the function fails, the return value is zero ( FALSE). For extended error information, call GetLastError.
///
/// Note If CRYPT_KEYID_SET_NEW_FLAG is set and the property already exists, FALSE is returned with the last error
/// code set to CRYPT_E_EXISTS.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptsetkeyidentifierproperty BOOL
// CryptSetKeyIdentifierProperty( const CRYPT_HASH_BLOB *pKeyIdentifier, DWORD dwPropId, DWORD dwFlags, LPCWSTR pwszComputerName,
// void *pvReserved, const void *pvData );
[DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincrypt.h", MSDNShortId = "0970aaaa-3f9a-4471-bd21-5de8746f94a2")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptSetKeyIdentifierProperty(in CRYPTOAPI_BLOB pKeyIdentifier, uint dwPropId, CryptKeyIdFlags dwFlags,
[Optional, MarshalAs(UnmanagedType.LPWStr)] string pwszComputerName, [Optional] IntPtr pvReserved, [In, Optional] IntPtr pvData);
///
///
/// The PUBLICKEYSTRUC structure, also known as the BLOBHEADER structure, indicates a key's BLOB type and the
/// algorithm that the key uses. One of these structures is located at the beginning of the pbData member of every key BLOB.
///
///
/// This structure is not limited to the key BLOBs generated by the PROV_RSA_BASE and PROV_RSA_SIG provider types. The pbData
/// member of any new key BLOB type must begin with this structure.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-publickeystruc typedef struct _PUBLICKEYSTRUC { BYTE
// bType; BYTE bVersion; WORD reserved; ALG_ID aiKeyAlg; } BLOBHEADER, PUBLICKEYSTRUC;
[PInvokeData("wincrypt.h", MSDNShortId = "99d41222-b4ca-40f3-a240-52b0a9b3a9aa")]
[StructLayout(LayoutKind.Sequential)]
public struct PUBLICKEYSTRUC
{
private byte _bType;
///
/// Contains the key BLOB type.
///
/// The following are the predefined values for this member. Cryptographic service providers (CSPs) can use other type
/// identifiers as needed.
///
///
///
/// Value
/// Meaning
///
/// -
/// KEYSTATEBLOB 0xC
/// The BLOB is a key state BLOB.
///
/// -
/// OPAQUEKEYBLOB 0x9
/// The key is a session key.
///
/// -
/// PLAINTEXTKEYBLOB 0x8
/// The key is a session key.
///
/// -
/// PRIVATEKEYBLOB 0x7
/// The key is a public/private key pair.
///
/// -
/// PUBLICKEYBLOB 0x6
/// The key is a public key.
///
/// -
/// PUBLICKEYBLOBEX 0xA
/// The key is a public key.
///
/// -
/// SIMPLEBLOB 0x1
/// The key is a session key.
///
/// -
/// SYMMETRICWRAPKEYBLOB 0xB
/// The key is a symmetric key.
///
///
///
public BlobType bType { get => (BlobType)_bType; set => _bType = (byte)bType; }
///
/// Contains the version number of the key BLOB format. For example, if the BLOB is a Digital Signature Standard (DSS) version 3
/// key, this member will contain 3. The minimum value for this member is defined by the CUR_BLOB_VERSION (2) identifier.
///
public byte bVersion;
/// This member is reserved for future use and must be set to zero.
public ushort reserved;
///
/// Contains one of the ALG_ID values that identifies the algorithm of the key contained by the key BLOB.
///
/// Not all algorithm identifiers are valid with all BLOB types. For example, since an RC4 key is a session key, it cannot be
/// exported into a PUBLICKEYBLOB.
///
///
/// PLAINTEXTBLOBs can be used with any algorithm or type of key combination supported by the CSP in use. Note that a 3DES key
/// cannot be imported when the Microsoft Base Provider is in use.
///
///
public ALG_ID aiKeyAlg;
}
}
}