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