using System; using System.Runtime.InteropServices; using Vanara.InteropServices; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace Vanara.PInvoke { /// Methods and data types found in Crypt32.dll. public static partial class Crypt32 { /// A callback function used to read from and write data to a disk when processing large messages. /// The arguments specified by CMSG_STREAM_INFO. /// A pointer to a block of processed data that is available to the application. /// The size, in bytes, of the block of processed data at pbData. /// /// Specifies that the last block of data is being processed and that this is the last time the callback will be executed. /// /// on success; on failure. [PInvokeData("wincrypt.h", MSDNShortId = "a4e7f6e8-351f-4981-b223-50b65f503394")] public delegate bool PFN_CMSG_STREAM_OUTPUT([In] IntPtr pvArg, [In] IntPtr pbData, uint cbData, [MarshalAs(UnmanagedType.Bool)] bool fFinal); /// /// The CryptGetSignerCertificateCallback user supplied callback function is used with the CRYPT_VERIFY_MESSAGE_PARA /// structure to get and verify a message signer's certificate. /// /// /// /// /// Specifies the type of encoding 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 a CERT_INFO structure containing the issuer and serial number. Can be NULL if there is no content or signer. /// /// A handle to the certificate store containing all the certificates and CRLs in the signed message. /// /// If a signer certificate is found, the function returns a pointer to a read-only CERT_CONTEXT. The returned CERT_CONTEXT /// was obtained either from a certificate store or was created using CertCreateCertificateContext. In either case, it must be freed /// using CertFreeCertificateContext. If this function fails, the return value is NULL. /// /// If the message does not contain content or signers, the function is called with pSignerId set to NULL. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nc-wincrypt-pfn_crypt_get_signer_certificate // PFN_CRYPT_GET_SIGNER_CERTIFICATE PfnCryptGetSignerCertificate; PCCERT_CONTEXT PfnCryptGetSignerCertificate( void *pvGetArg, DWORD // dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore ) {...} [PInvokeData("wincrypt.h", MSDNShortId = "557ebb26-cce0-4c41-b49c-769b2831cf35")] public delegate PCCERT_CONTEXT PFN_CRYPT_GET_SIGNER_CERTIFICATE([In, Out] IntPtr pvGetArg, CertEncodingType dwCertEncodingType, in CERT_INFO pSignerId, HCERTSTORE hMsgCertStore); /// Flags for various structure behaviors. [PInvokeData("wincrypt.h", MSDNShortId = "1601d860-6054-4650-a033-ea088655b7e4")] [Flags] public enum CryptMsgActionFlags { /// /// If the encoded output is to be a CMSG_SIGNED inner content of an outer cryptographic message such as a CMSG_ENVELOPED /// message, the CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG must be set. /// CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG = 0x00000001, /// CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG can be set to encapsulate non-data inner content into an OCTET STRING. CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG = 0x00000002, /// /// CRYPT_MESSAGE_KEYID_SIGNER_FLAG can be set to identify signers by their Key Identifier and not their Issuer and Serial Number. /// CRYPT_MESSAGE_KEYID_SIGNER_FLAG = 0x00000004, /// /// CRYPT_MESSAGE_SILENT_KEYSET_FLAG can be set to suppress any UI by the CSP. For more information about the CRYPT_SILENT flag, /// see CryptAcquireContext. /// CRYPT_MESSAGE_SILENT_KEYSET_FLAG = 0x00000040, } /// Message control types. [PInvokeData("wincrypt.h", MSDNShortId = "a990d44d-2993-429f-b817-2a834105ecef")] public enum CryptMsgControlType { /// A BLOB that contains the encoded bytes of attribute certificate. [CorrespondingType(typeof(CRYPTOAPI_BLOB))] CMSG_CTRL_ADD_ATTR_CERT = 14, /// A CRYPT_INTEGER_BLOB structure that contains the encoded bytes of the certificate to be added to the message. [CorrespondingType(typeof(CRYPTOAPI_BLOB))] CMSG_CTRL_ADD_CERT = 10, /// /// A CMSG_CMS_SIGNER_INFO structure that contains signer information. This operation differs from CMSG_CTRL_ADD_SIGNER because /// the signer information contains the signature. /// [CorrespondingType(typeof(CMSG_CMS_SIGNER_INFO))] CMSG_CTRL_ADD_CMS_SIGNER_INFO = 20, /// A BLOB that contains the encoded bytes of the CRL to be added to the message. [CorrespondingType(typeof(CRYPTOAPI_BLOB))] CMSG_CTRL_ADD_CRL = 12, /// A CMSG_SIGNER_ENCODE_INFO structure that contains the signer information to be added to the message. [CorrespondingType(typeof(CMSG_SIGNER_ENCODE_INFO))] CMSG_CTRL_ADD_SIGNER = 6, /// /// A CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA structure that contains the index of the signer and a BLOB that contains the /// unauthenticated attribute information to be added to the message. /// [CorrespondingType(typeof(CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA))] CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR = 8, /// /// A CMSG_CTRL_DECRYPT_PARA structure used to decrypt the message for the specified key transport recipient. This value is /// applicable to RSA recipients. This operation specifies that the CryptMsgControl function search the recipient index to /// obtain the key transport recipient information. If the function fails, GetLastError will return CRYPT_E_INVALID_INDEX if no /// key transport recipient is found. /// [CorrespondingType(typeof(CMSG_CTRL_DECRYPT_PARA))] CMSG_CTRL_DECRYPT = 2, /// The index of the attribute certificate to be removed. [CorrespondingType(typeof(uint))] CMSG_CTRL_DEL_ATTR_CERT = 15, /// The index of the certificate to be deleted from the message. [CorrespondingType(typeof(uint))] CMSG_CTRL_DEL_CERT = 11, /// The index of the CRL to be deleted from the message. [CorrespondingType(typeof(uint))] CMSG_CTRL_DEL_CRL = 13, /// The index of the signer to be deleted. [CorrespondingType(typeof(uint))] CMSG_CTRL_DEL_SIGNER = 7, /// /// A CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA structure that contains an index that specifies the signer and the index that /// specifies the signer's unauthenticated attribute to be deleted. /// [CorrespondingType(typeof(CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA))] CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR = 9, /// /// A CERT_STRONG_SIGN_PARA structure used to perform strong signature checking. /// /// To check for a strong signature, specify this control type before calling CryptMsgGetAndVerifySigner or before calling /// CryptMsgControl with the following control types set: /// /// CMSG_CTRL_VERIFY_SIGNATURE /// CMSG_CTRL_VERIFY_SIGNATURE_EX /// /// After the signature is successfully verified, this function checks for a strong signature. If the signature is not strong, /// the operation will fail and the GetLastError value will be set to NTE_BAD_ALGID. /// /// [CorrespondingType(typeof(CERT_STRONG_SIGN_PARA))] CMSG_CTRL_ENABLE_STRONG_SIGNATURE = 21, /// /// A CMSG_CTRL_KEY_AGREE_DECRYPT_PARA structure used to decrypt the message for the specified key agreement session key. Key /// agreement is used with Diffie-Hellman encryption/decryption. /// [CorrespondingType(typeof(CMSG_CTRL_KEY_AGREE_DECRYPT_PARA))] CMSG_CTRL_KEY_AGREE_DECRYPT = 17, /// /// A CMSG_CTRL_KEY_TRANS_DECRYPT_PARA structure used to decrypt the message for the specified key transport recipient. Key /// transport is used with RSA encryption/decryption. /// [CorrespondingType(typeof(CMSG_CTRL_KEY_TRANS_DECRYPT_PARA))] CMSG_CTRL_KEY_TRANS_DECRYPT = 16, /// /// A CMSG_CTRL_MAIL_LIST_DECRYPT_PARA structure used to decrypt the message for the specified recipient using a previously /// distributed key-encryption key (KEK). /// [CorrespondingType(typeof(CMSG_CTRL_MAIL_LIST_DECRYPT_PARA))] CMSG_CTRL_MAIL_LIST_DECRYPT = 18, /// This value is not used. CMSG_CTRL_VERIFY_HASH = 5, /// A CERT_INFO structure that identifies the signer of the message whose signature is to be verified. [CorrespondingType(typeof(CERT_INFO))] CMSG_CTRL_VERIFY_SIGNATURE = 1, /// /// A CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA structure that specifies the signer index and public key to verify the message /// signature. The signer public key can be a CERT_PUBLIC_KEY_INFO structure, a certificate context, or a certificate chain context. /// [CorrespondingType(typeof(CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA))] CMSG_CTRL_VERIFY_SIGNATURE_EX = 19, } /// Flags for message functions. [PInvokeData("wincrypt.h", MSDNShortId = "1c12003a-c2f3-4069-8bd6-b8f2875b0c98")] [Flags] public enum CryptMsgFlags { /// /// Indicates that streamed output will not have an outer ContentInfo wrapper (as defined by PKCS #7). This makes it suitable to /// be streamed into an enclosing message. /// CMSG_BARE_CONTENT_FLAG = 0x00000001, /// CMSG_LENGTH_ONLY_FLAG = 0x00000002, /// Indicates that there is detached data being supplied for the subsequent calls to CryptMsgUpdate. CMSG_DETACHED_FLAG = 0x00000004, /// /// Authenticated attributes are forced to be included in the SignerInfo (as defined by PKCS #7) in cases where they would not /// otherwise be required. /// CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = 0x00000008, /// /// Used to calculate the size of a DER encoding of a message to be nested inside an enveloped message. This is particularly /// useful when streaming is being performed. /// CMSG_CONTENTS_OCTETS_FLAG = 0x00000010, /// CMSG_MAX_LENGTH_FLAG = 0x00000020, /// /// Non-Data type inner content is encapsulated within an OCTET STRING. This flag is applicable for both Signed and Enveloped messages. /// CMSG_CMS_ENCAPSULATED_CONTENT_FLAG = 0x00000040, /// CMSG_SIGNED_DATA_NO_SIGN_FLAG = 0x00000080, /// /// If set, the hCryptProv that is passed to this function is released on the final CryptMsgUpdate. The handle is not released /// if the function fails. /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG = 0x00008000, } /// Flags used by CMSG_KEY_AGREE_RECIPIENT_INFO. [PInvokeData("wincrypt.h")] public enum CryptMsgKeyOriginator { /// OriginatorCertId CMSG_KEY_AGREE_ORIGINATOR_CERT = 1, /// OriginatorPublicKeyInfo CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY = 2, } /// /// Indicates the parameter types of data to be retrieved. /// /// For an encoded message, only the CMSG_BARE_CONTENT, CMSG_ENCODE_SIGNER, CMSG_CONTENT_PARAM and CMSG_COMPUTED_HASH_PARAM /// dwParamTypes are valid. /// /// [PInvokeData("wincrypt.h", MSDNShortId = "5a05eb09-208f-4e94-abfa-c2f14c0a3164")] public enum CryptMsgParamType { /// /// Returns the message type of a decoded message of unknown type. The retrieved message type can be compared to supported types /// to determine whether processing can continued. For supported message types, see the dwMessageType parameter of CryptMsgOpenToDecode. /// [CorrespondingType(typeof(uint))] CMSG_TYPE_PARAM = 1, /// /// Returns the whole PKCS #7 message from a message opened to encode. Retrieves the inner content of a message opened to /// decode. If the message is enveloped, the inner type is data, and CryptMsgControl has been called to decrypt the message, the /// decrypted content is returned. If the inner type is not data, the encoded BLOB that requires further decoding is returned. /// If the message is not enveloped and the inner content is DATA, the returned data is the octets of the inner content. This /// type is applicable to both encode and decode. /// For decoding, if the type is CMSG_DATA, the content's octets are returned; else, the encoded inner content is returned. /// [CorrespondingType(typeof(byte[]))] [CorrespondingType(typeof(CRYPTOAPI_BLOB))] CMSG_CONTENT_PARAM = 2, /// /// Retrieves the encoded content of an encoded cryptographic message, without the outer layer of the CONTENT_INFO structure. /// That is, only the encoding of the PKCS #7 defined ContentInfo.content field is returned. /// [CorrespondingType(typeof(byte[]))] CMSG_BARE_CONTENT_PARAM = 3, /// Returns the inner content type of a received message. This type is not applicable to messages of type DATA. [CorrespondingType(typeof(byte[]))] CMSG_INNER_CONTENT_TYPE_PARAM = 4, /// Returns the number of signers of a received SIGNED message. [CorrespondingType(typeof(uint))] CMSG_SIGNER_COUNT_PARAM = 5, /// /// Returns information on a message signer. This includes the issuer and serial number of the signer's certificate and /// authenticated and unauthenticated attributes of the signer's certificate. To retrieve signer information on all of the /// signers of a message, call CryptMsgGetParam varying dwIndex from 0 to the number of signers minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_INFO_PARAM = 6, /// /// Returns information on a message signer needed to identify the signer's certificate. A certificate's Issuer and SerialNumber /// can be used to uniquely identify a certificate for retrieval. To retrieve information for all the signers, repetitively call /// CryptMsgGetParam varying dwIndex from 0 to the number of signers minus one. Only the Issuer and SerialNumber fields in the /// CERT_INFO structure returned contain available, valid data. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_CERT_INFO_PARAM = 7, /// /// Returns the hash algorithm used by a signer of the message. To get the hash algorithm for a specified signer, call /// CryptMsgGetParam with dwIndex equal to that signer's index. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_HASH_ALGORITHM_PARAM = 8, /// /// Returns the authenticated attributes of a message signer. To retrieve the authenticated attributes for a specified signer, /// call CryptMsgGetParam with dwIndex equal to that signer's index. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_AUTH_ATTR_PARAM = 9, /// /// Returns a message signer's unauthenticated attributes. To retrieve the unauthenticated attributes for a specified signer, /// call CryptMsgGetParam with dwIndex equal to that signer's index. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_UNAUTH_ATTR_PARAM = 10, /// Returns the number of certificates in a received SIGNED or ENVELOPED message. [CorrespondingType(typeof(uint))] CMSG_CERT_COUNT_PARAM = 11, /// /// Returns a signer's certificate. To get all of the signer's certificates, call CryptMsgGetParam, varying dwIndex from 0 to /// the number of available certificates minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_CERT_PARAM = 12, /// Returns the count of CRLs in a received, SIGNED or ENVELOPED message. [CorrespondingType(typeof(uint))] CMSG_CRL_COUNT_PARAM = 13, /// /// Returns a CRL. To get all the CRLs, call CryptMsgGetParam, varying dwIndex from 0 to the number of available CRLs minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_CRL_PARAM = 14, /// Returns the encryption algorithm used to encrypt an ENVELOPED message. [CorrespondingType(typeof(byte[]))] CMSG_ENVELOPE_ALGORITHM_PARAM = 15, /// Returns the number of key transport recipients of an ENVELOPED received message. [CorrespondingType(typeof(uint))] CMSG_RECIPIENT_COUNT_PARAM = 17, /// /// Returns the index of the key transport recipient used to decrypt an ENVELOPED message. This value is available only after a /// message has been decrypted. /// [CorrespondingType(typeof(uint))] CMSG_RECIPIENT_INDEX_PARAM = 18, /// /// Returns certificate information about a key transport message's recipient. To get certificate information on all key /// transport message's recipients, repetitively call CryptMsgGetParam, varying dwIndex from 0 to the number of recipients minus /// one. Only the Issuer, SerialNumber, and PublicKeyAlgorithm members of the CERT_INFO structure returned are available and valid. /// [CorrespondingType(typeof(byte[]))] CMSG_RECIPIENT_INFO_PARAM = 19, /// Returns the hash algorithm used to hash the message when it was created. [CorrespondingType(typeof(byte[]))] CMSG_HASH_ALGORITHM_PARAM = 20, /// Returns the hash value stored in the message when it was created. [CorrespondingType(typeof(byte[]))] CMSG_HASH_DATA_PARAM = 21, /// Returns the hash calculated of the data in the message. This type is applicable to both encode and decode. [CorrespondingType(typeof(byte[]))] CMSG_COMPUTED_HASH_PARAM = 22, /// Returns the encryption algorithm used to encrypted the message. [CorrespondingType(typeof(byte[]))] CMSG_ENCRYPT_PARAM = 26, /// Returns the encrypted hash of a signature. Typically used for performing time-stamping. [CorrespondingType(typeof(byte[]))] CMSG_ENCRYPTED_DIGEST = 27, /// Returns the encoded CMSG_SIGNER_INFO signer information for a message signer. [CorrespondingType(typeof(byte[]))] CMSG_ENCODED_SIGNER = 28, /// /// Changes the contents of an already encoded message. The message must first be decoded with a call to CryptMsgOpenToDecode. /// Then the change to the message is made through a call to CryptMsgControl, CryptMsgCountersign, or /// CryptMsgCountersignEncoded. The message is then encoded again with a call to CryptMsgGetParam, specifying /// CMSG_ENCODED_MESSAGE to get a new encoding that reflects the changes made. This can be used, for instance, to add a /// time-stamp attribute to a message. /// [CorrespondingType(typeof(byte[]))] CMSG_ENCODED_MESSAGE = 29, /// Returns the version of the decoded message. For more information, see the table in the Remarks section. [CorrespondingType(typeof(uint))] CMSG_VERSION_PARAM = 30, /// Returns the count of the attribute certificates in a SIGNED or ENVELOPED message. [CorrespondingType(typeof(uint))] CMSG_ATTR_CERT_COUNT_PARAM = 31, /// /// Retrieves an attribute certificate. To get all the attribute certificates, call CryptMsgGetParam varying dwIndex set to 0 /// the number of attributes minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_ATTR_CERT_PARAM = 32, /// Returns the total count of all message recipients including key agreement and mail list recipients. [CorrespondingType(typeof(uint))] CMSG_CMS_RECIPIENT_COUNT_PARAM = 33, /// Returns the index of the key transport, key agreement, or mail list recipient used to decrypt an ENVELOPED message. [CorrespondingType(typeof(uint))] CMSG_CMS_RECIPIENT_INDEX_PARAM = 34, /// Returns the index of the encrypted key of a key agreement recipient used to decrypt an ENVELOPED message. [CorrespondingType(typeof(uint))] CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM = 35, /// /// Returns information about a key transport, key agreement, or mail list recipient. It is not limited to key transport message /// recipients. To get information on all of a message's recipients, repetitively call CryptMsgGetParam, varying dwIndex from 0 /// to the number of recipients minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_CMS_RECIPIENT_INFO_PARAM = 36, /// Returns the unprotected attributes in an enveloped message. [CorrespondingType(typeof(byte[]))] CMSG_UNPROTECTED_ATTR_PARAM = 37, /// /// Returns information on a message signer needed to identify the signer's public key. This could be a certificate's Issuer and /// SerialNumber, a KeyID, or a HashId. To retrieve information for all the signers, call CryptMsgGetParam varying dwIndex from /// 0 to the number of signers minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_SIGNER_CERT_ID_PARAM = 38, /// /// Returns information on a message signer. This includes a signerId and authenticated and unauthenticated attributes. To /// retrieve signer information on all of the signers of a message, call CryptMsgGetParam varying dwIndex from 0 to the number /// of signers minus one. /// [CorrespondingType(typeof(byte[]))] CMSG_CMS_SIGNER_INFO_PARAM = 39, } /// Message signer type. [PInvokeData("wincrypt.h", MSDNShortId = "56b73de8-c170-46f6-b488-096475b59c15")] public enum CryptMsgSignerType { /// CERT_PUBLIC_KEY_INFO [CorrespondingType(typeof(CERT_PUBLIC_KEY_INFO))] CMSG_VERIFY_SIGNER_PUBKEY = 1, /// CERT_CONTEXT [CorrespondingType(typeof(CERT_CONTEXT))] CMSG_VERIFY_SIGNER_CERT = 2, /// CERT_CHAIN_CONTEXT [CorrespondingType(typeof(CERT_CHAIN_CONTEXT))] CMSG_VERIFY_SIGNER_CHAIN = 3, /// The CMSG verify signer null CMSG_VERIFY_SIGNER_NULL = 4, } /// Message types. [PInvokeData("wincrypt.h", MSDNShortId = "1c12003a-c2f3-4069-8bd6-b8f2875b0c98")] public enum CryptMsgType { /// An octet (BYTE) string. CMSG_DATA = 1, /// CMSG_SIGNED_ENCODE_INFO CMSG_SIGNED = 2, /// CMSG_ENVELOPED_ENCODE_INFO CMSG_ENVELOPED = 3, /// Not implemented. CMSG_SIGNED_AND_ENVELOPED = 4, /// CMSG_HASHED_ENCODE_INFO CMSG_HASHED = 5, /// Not implemented. CMSG_ENCRYPTED = 6, } /// Flags that modify the function behavior. [PInvokeData("wincrypt.h", MSDNShortId = "da756cd5-1dec-4d88-9c90-76dd263035eb")] public enum CryptMsgVerifyCounterFlags { /// /// Performs a strong signature check after successful signature verification. Set the pvExtra parameter to point to a /// CERT_STRONG_SIGN_PARA structure that contains the parameters needed to check the signature strength.. Windows 8 and Windows /// Server 2012: Support for this flag begins. /// CMSG_VERIFY_COUNTER_SIGN_ENABLE_STRONG_FLAG = 0x00000001 } /// /// The CryptDecodeMessage function decodes, decrypts, and verifies a cryptographic message. /// /// This function can be used when the type of cryptographic message is unknown. The dwMsgTypeFlags constants can be combined with a /// bitwise- OR operation so that the function will try to find one of the types. When one of the types is found, the /// function reports the type found and returns the data appropriate to that type. /// /// /// In each pass, the function cracks only a single level of encryption or encoding. For additional cracking, this function, or one /// of the other Simplified Message Functions, must be called again. /// /// /// /// /// Indicates the message type. Message types can be combined with the bitwise- OR operator. This parameter can be one of the /// following message types: /// /// /// /// CMSG_DATA_FLAG /// /// /// CMSG_SIGNED_FLAG /// /// /// CMSG_ENVELOPED_FLAG /// /// /// CMSG_SIGNED_AND_ENVELOPED_FLAG /// /// /// CMSG_HASHED_FLAG /// /// /// Note After return, the DWORD pointed to by pdwMsgType is set with the type of the message. /// /// A pointer to a CRYPT_DECRYPT_MESSAGE_PARA structure that contains decryption parameters. /// A pointer to a CRYPT_VERIFY_MESSAGE_PARA structure that contains verification parameters. /// /// /// Indicates which signer, among the possible many signers of a message, is to be verified. This index can be changed in multiple /// calls to the function to verify additional signers. /// /// /// dwSignerIndex is set to zero for the first signer. If the function returns FALSE, and GetLastError returns /// CRYPT_E_NO_SIGNER, the previous call returned the last signer of the message. This parameter is used only with messages of types /// CMSG_SIGNED_AND_ENVELOPED or CMSG_SIGNED. For all other message types, it should be set to zero. /// /// /// A pointer to the encoded BLOB that is to be decoded. /// The size, in bytes, of the encoded BLOB. /// /// Only applicable when processing nested cryptographic messages. When processing an outer cryptographic message, it must be set to /// zero. When decoding a nested cryptographic message, it is set to the value returned at pdwInnerContentType by a previous calling /// of CryptDecodeMessage for the outer message. It can be any of the CMSG types listed in pdwMsgType. For backward /// compatibility, set dwPrevInnerContentType to zero. /// /// /// /// A pointer to a DWORD that specifies the message type returned. This parameter can be one of the following message types: /// /// /// /// CMSG_DATA /// /// /// CMSG_SIGNED /// /// /// CMSG_ENVELOPED /// /// /// CMSG_SIGNED_AND_ENVELOPED /// /// /// CMSG_HASHED /// /// /// /// /// /// A pointer to a DWORD that specifies the type of an inner message. The message type codes used for pdwMsgType are used /// here, also. /// /// If there is no cryptographic nesting, CMSG_DATA is returned. /// /// /// A pointer to a buffer to receive the decoded message. /// /// This parameter can be NULL if the decoded message is not required or to set the size of the decoded message for memory /// allocation purposes. A decoded message will not be returned if this parameter is NULL. For more information, see /// Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a variable that specifies the size, in bytes, of the buffer pointed to by the pbDecoded parameter. When the /// function returns, this variable contains the size of the decoded message. /// /// /// Note When processing the data returned in the buffer, applications must 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 will fit 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 a pointer to a CERT_CONTEXT structure with a certificate that corresponds to the private exchange key needed to /// decode the message. This parameter is only set for message types CMSG_ENVELOPED and CMSG_SIGNED_AND_ENVELOPED. /// /// /// A pointer to a pointer to a CERT_CONTEXT structure of the certificate context of the signer. This parameter is only set for /// message types CMSG_SIGNED and CMSG_SIGNED_AND_ENVELOPED. /// /// /// If the function succeeds, the function returns nonzero ( TRUE). /// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError. /// The CryptDecryptMessage, CryptVerifyMessageSignature, or CryptVerifyMessageHash functions can be propagated to this function. /// The following error code is most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecoded parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code and stores the required buffer size, in bytes, in the variable pointed to by pcbDecoded. /// /// /// /// /// /// /// The dwMsgTypeFlags parameter specifies the set of allowable messages. For example, to decode either SIGNED or ENVELOPED /// messages, set dwMsgTypeFlags to CMSG_SIGNED_FLAG | CMSG_ENVELOPED_FLAG. Either or both of the pDecryptPara or pVerifyPara /// parameters must be specified. /// /// /// For a successfully decoded or verified message, the certificate context pointers pointed to by ppXchgCert and ppSignerCert are /// updated. They must be freed by calling CertFreeCertificateContext. If the function fails, they are set to NULL. /// /// /// The ppXchgCert or ppSignerCert parameters can be set to NULL before the function is called, which indicates that the /// caller is not interested in getting the exchange certificate or the signer certificate context. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecodemessage BOOL CryptDecodeMessage( DWORD // dwMsgTypeFlags, PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex, const BYTE // *pbEncodedBlob, DWORD cbEncodedBlob, DWORD dwPrevInnerContentType, DWORD *pdwMsgType, DWORD *pdwInnerContentType, BYTE // *pbDecoded, DWORD *pcbDecoded, PCCERT_CONTEXT *ppXchgCert, PCCERT_CONTEXT *ppSignerCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "25ffd058-8f75-4ba5-b075-e3efc09f5d9d")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptDecodeMessage(CryptMsgType dwMsgTypeFlags, in CRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, in CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, uint dwSignerIndex, [In] IntPtr pbEncodedBlob, uint cbEncodedBlob, CryptMsgType dwPrevInnerContentType, out CryptMsgType pdwMsgType, out CryptMsgType pdwInnerContentType, [Out] IntPtr pbDecoded, ref uint pcbDecoded, out SafePCCERT_CONTEXT ppXchgCert, out SafePCCERT_CONTEXT ppSignerCert); /// The CryptDecryptAndVerifyMessageSignature function decrypts a message and verifies its signature. /// A pointer to a CRYPT_DECRYPT_MESSAGE_PARA structure that contains decryption parameters. /// A pointer to a CRYPT_VERIFY_MESSAGE_PARA structure that contains verification parameters. /// /// Identifies a particular signer of the message. A message can be signed by more than one signer and this function can be called /// multiple times changing this parameter to check for several signers. It is set to zero for the first signer. If the function /// returns FALSE, and GetLastError returns CRYPT_E_NO_SIGNER, the previous call received the last signer of the message. /// /// A pointer to the signed, encoded, and encrypted message to be decrypted and verified. /// The size, in bytes, of the encrypted message. /// /// A pointer to a buffer to receive the decrypted message. /// /// This parameter can be NULL if the decrypted message is not required or to set the size of the decrypted message for /// memory allocation purposes. A decrypted message will not be returned if this parameter is 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 pbDecrypted parameter. When the /// function returns, it contains the size of the decrypted message copied to pbDecrypted. /// /// /// Note When processing the data returned in the pbDecrypted buffer, applications must use the actual size of the data /// returned. The actual size can be slightly smaller than the size of the buffer specified in pcbDecrypted on input. On output, the /// variable pointed to by this parameter is set to reflect the actual size of the data copied to the buffer. /// /// /// /// A pointer to a CERT_CONTEXT structure of the certificate that corresponds to the private exchange key needed to decrypt the message. /// /// A pointer to a CERT_CONTEXT structure of the certificate of the signer. /// /// If the function succeeds, the function returns nonzero ( TRUE). /// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError. /// /// Note Errors from the called functions CryptDecryptMessage and CryptVerifyMessageSignature might be propagated to this function. /// /// The GetLastError function returns the following error code most often. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecrypted parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecrypted. /// /// /// /// /// /// /// For a successfully decrypted and verified message, the certificate context pointers pointed to by ppXchgCert and ppSignerCert /// are updated. They must be freed by calling CertFreeCertificateContext. If the function fails, they are set to NULL. /// /// /// To indicate that the caller is not interested in the exchange certificate or the signer certificate context, set the ppXchgCert /// and ppSignerCert parameters to NULL. /// /// Examples /// For an example that uses this function, see Example C Program: Sending and Receiving a Signed and Encrypted Message. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecryptandverifymessagesignature BOOL // CryptDecryptAndVerifyMessageSignature( PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD // dwSignerIndex, const BYTE *pbEncryptedBlob, DWORD cbEncryptedBlob, BYTE *pbDecrypted, DWORD *pcbDecrypted, PCCERT_CONTEXT // *ppXchgCert, PCCERT_CONTEXT *ppSignerCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "0864a187-617f-4a21-9809-d2dbbc54ab9c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptDecryptAndVerifyMessageSignature(in CRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, in CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, uint dwSignerIndex, [In] IntPtr pbEncryptedBlob, uint cbEncryptedBlob, [Out] IntPtr pbDecrypted, ref uint pcbDecrypted, out SafePCCERT_CONTEXT ppXchgCert, out SafePCCERT_CONTEXT ppSignerCert); /// The CryptDecryptMessage function decodes and decrypts a message. /// A pointer to a CRYPT_DECRYPT_MESSAGE_PARA structure that contains decryption parameters. /// A pointer to a buffer that contains the encoded and encrypted message to be decrypted. /// The size, in bytes, of the encoded and encrypted message. /// /// A pointer to a buffer that receives the decrypted message. /// /// To set the size of this information for memory allocation purposes, this parameter can be NULL. A decrypted message will /// not be returned if this parameter is 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 pbDecrypted parameter. When the /// function returns, this variable contains the size, in bytes, of the decrypted message copied to pbDecrypted. /// /// /// Note When processing the data returned in the pbDecrypted buffer, applications must use the actual size of the data /// returned. The actual size can be slightly smaller than the size of the buffer specified in pcbDecrypted on input. On input, /// buffer sizes are usually specified large enough to ensure that the largest possible output data will fit in the buffer. On /// output, the DWORD is updated to the actual size of the data copied to the buffer. /// /// /// /// A pointer to a CERT_CONTEXT structure of a certificate that corresponds to the private exchange key needed to decrypt the /// message. To indicate that the function should not return the certificate context used to decrypt, set this parameter to NULL. /// /// /// If the function succeeds, the function returns nonzero ( TRUE). /// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError. /// Note Errors from calls to CryptImportKey and CryptDecrypt might be propagated to this function. /// The GetLastError function returns the following error codes most often. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecrypted parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecrypted. /// /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pDecryptPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not an enveloped cryptographic message. /// /// /// NTE_BAD_ALGID /// The message was encrypted by using an unknown or unsupported algorithm. /// /// /// CRYPT_E_NO_DECRYPT_CERT /// No certificate was found having a private key property to use for decrypting. /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// When NULL is passed for pbDecrypted, and pcbDecrypted is not NULL, NULL is returned for the address passed /// in ppXchgCert; otherwise, a pointer to a CERT_CONTEXT is returned. For a successfully decrypted message, this pointer to a /// CERT_CONTEXT points to the certificate context used to decrypt the message. It must be freed by calling /// CertFreeCertificateContext. If the function fails, the value at ppXchgCert is set to NULL. /// /// Examples /// For an example that uses this function, see Example C Program: Using CryptEncryptMessage and CryptDecryptMessage. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecryptmessage BOOL CryptDecryptMessage( // PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, const BYTE *pbEncryptedBlob, DWORD cbEncryptedBlob, BYTE *pbDecrypted, DWORD // *pcbDecrypted, PCCERT_CONTEXT *ppXchgCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "e540b816-64e1-4c78-9020-2b221e813acc")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptDecryptMessage(in CRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, [In] IntPtr pbEncryptedBlob, uint cbEncryptedBlob, [Out] IntPtr pbDecrypted, ref uint pcbDecrypted, out SafePCCERT_CONTEXT ppXchgCert); /// The CryptDecryptMessage function decodes and decrypts a message. /// A pointer to a CRYPT_DECRYPT_MESSAGE_PARA structure that contains decryption parameters. /// A pointer to a buffer that contains the encoded and encrypted message to be decrypted. /// The size, in bytes, of the encoded and encrypted message. /// /// A pointer to a buffer that receives the decrypted message. /// /// To set the size of this information for memory allocation purposes, this parameter can be NULL. A decrypted message will /// not be returned if this parameter is 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 pbDecrypted parameter. When the /// function returns, this variable contains the size, in bytes, of the decrypted message copied to pbDecrypted. /// /// /// Note When processing the data returned in the pbDecrypted buffer, applications must use the actual size of the data /// returned. The actual size can be slightly smaller than the size of the buffer specified in pcbDecrypted on input. On input, /// buffer sizes are usually specified large enough to ensure that the largest possible output data will fit in the buffer. On /// output, the DWORD is updated to the actual size of the data copied to the buffer. /// /// /// /// A pointer to a CERT_CONTEXT structure of a certificate that corresponds to the private exchange key needed to decrypt the /// message. To indicate that the function should not return the certificate context used to decrypt, set this parameter to NULL. /// /// /// If the function succeeds, the function returns nonzero ( TRUE). /// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError. /// Note Errors from calls to CryptImportKey and CryptDecrypt might be propagated to this function. /// The GetLastError function returns the following error codes most often. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecrypted parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecrypted. /// /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pDecryptPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not an enveloped cryptographic message. /// /// /// NTE_BAD_ALGID /// The message was encrypted by using an unknown or unsupported algorithm. /// /// /// CRYPT_E_NO_DECRYPT_CERT /// No certificate was found having a private key property to use for decrypting. /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// When NULL is passed for pbDecrypted, and pcbDecrypted is not NULL, NULL is returned for the address passed /// in ppXchgCert; otherwise, a pointer to a CERT_CONTEXT is returned. For a successfully decrypted message, this pointer to a /// CERT_CONTEXT points to the certificate context used to decrypt the message. It must be freed by calling /// CertFreeCertificateContext. If the function fails, the value at ppXchgCert is set to NULL. /// /// Examples /// For an example that uses this function, see Example C Program: Using CryptEncryptMessage and CryptDecryptMessage. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecryptmessage BOOL CryptDecryptMessage( // PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, const BYTE *pbEncryptedBlob, DWORD cbEncryptedBlob, BYTE *pbDecrypted, DWORD // *pcbDecrypted, PCCERT_CONTEXT *ppXchgCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "e540b816-64e1-4c78-9020-2b221e813acc")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptDecryptMessage(in CRYPT_DECRYPT_MESSAGE_PARA pDecryptPara, [In] IntPtr pbEncryptedBlob, uint cbEncryptedBlob, [Out] IntPtr pbDecrypted, ref uint pcbDecrypted, IntPtr ppXchgCert = default); /// The CryptEncryptMessage function encrypts and encodes a message. /// /// A pointer to a CRYPT_ENCRYPT_MESSAGE_PARA structure that contains the encryption parameters. /// /// The CryptEncryptMessage function does not support the SHA2 OIDs, szOID_DH_SINGLE_PASS_STDDH_SHA256_KDF and szOID_DH_SINGLE_PASS_STDDH_SHA384_KDF. /// /// /// Number of elements in the rgpRecipientCert array. /// /// Array of pointers to CERT_CONTEXT structures that contain the certificates of intended recipients of the message. /// /// A pointer to a buffer that contains the message that is to be encrypted. /// The size, in bytes, of the message that is to be encrypted. /// /// A pointer to BLOB that contains a buffer that receives the encrypted and encoded message. /// /// To set the size of this information for memory allocation purposes, this parameter can be 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 pbEncryptedBlob parameter. When /// the function returns, this variable contains the size, in bytes, of the encrypted and encoded message copied to pbEncryptedBlob. /// /// /// Note When processing the data returned in the buffer of the pbEncryptedBlob, 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 will fit 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. /// /// Note Errors from calls to CryptGenKey, CryptEncrypt, CryptImportKey, and CryptExportKey can be propagated to this function. /// /// The GetLastError function returns the following error codes most often. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbEncryptedBlob parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code and stores the required buffer size, in bytes, in the variable pointed to by pcbEncryptedBlob. /// /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pEncryptPara is not valid. /// /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptencryptmessage BOOL CryptEncryptMessage( // PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, DWORD cRecipientCert, PCCERT_CONTEXT [] rgpRecipientCert, const BYTE *pbToBeEncrypted, // DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob, DWORD *pcbEncryptedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "927f2e9a-96cf-4744-bd57-420b5034d28d")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptEncryptMessage(in CRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, uint cRecipientCert, [In, MarshalAs(UnmanagedType.LPArray)] PCCERT_CONTEXT[] rgpRecipientCert, [In] IntPtr pbToBeEncrypted, uint cbToBeEncrypted, [Out] IntPtr pbEncryptedBlob, ref uint pcbEncryptedBlob); /// /// The CryptGetMessageCertificates function returns the handle of an open certificate store containing the message's /// certificates and CRLs. This function calls CertOpenStore using provider type CERT_STORE_PROV_PKCS7 as its lpszStoreProvider parameter. /// /// /// /// 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 /// /// /// /// /// This parameter is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: Handle of the CSP passed to CertOpenStore. For more information, see /// CertOpenStore.Unless there is a strong reason for passing a specific cryptographic provider in hCryptProv, pass zero to cause /// the default RSA or DSS provider to be acquired. /// /// This parameter's data type is HCRYPTPROV. /// /// Flags passed to CertOpenStore. For more information, see CertOpenStore. /// A pointer to a buffered CRYPT_INTEGER_BLOB structure that contains the signed message. /// The size, in bytes, of the signed message. /// /// Returns the certificate store containing the message's certificates and CRLs. For an error, NULL is returned. /// The following lists the error code most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING are supported. /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// Use GetLastError to determine the reason for any errors. /// Examples /// For an example that uses this function, see Example C Program: Setting and Getting Certificate Store Properties. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgetmessagecertificates HCERTSTORE // CryptGetMessageCertificates( DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE // *pbSignedBlob, DWORD cbSignedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d890f91f-bb45-463b-b7c0-56acc9367571")] public static extern SafeHCERTSTORE CryptGetMessageCertificates(CertEncodingType dwMsgAndCertEncodingType, [Optional] HCRYPTPROV hCryptProv, CertStoreFlags dwFlags, [In] IntPtr pbSignedBlob, uint cbSignedBlob); /// The CryptGetMessageSignerCount function returns the number of signers of a signed message. /// /// /// 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 a buffer containing the signed message. /// The size, in bytes, of the signed message. /// /// Returns the number of signers of a signed message, zero when there are no signers, and minus one (–1) for an error. /// For extended error information, call GetLastError. The following error code is most commonly returned. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// Invalid message encoding type. Currently only PKCS_7_ASN_ENCODING is supported. /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgetmessagesignercount LONG // CryptGetMessageSignerCount( DWORD dwMsgEncodingType, const BYTE *pbSignedBlob, DWORD cbSignedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d18bda8b-b333-4b1e-8ed5-f8eff04b3168")] public static extern int CryptGetMessageSignerCount(CertEncodingType dwMsgEncodingType, [In] IntPtr pbSignedBlob, uint cbSignedBlob); /// The CryptHashMessage function creates a hash of the message. /// A pointer to a CRYPT_HASH_MESSAGE_PARA structure that contains the hash parameters. /// /// If this parameter is set to TRUE, only pbComputedHash is encoded in pbHashedBlob. Otherwise, both rgpbToBeHashed and /// pbComputedHash are encoded. /// /// /// The number of array elements in rgpbToBeHashed and rgcbToBeHashed. This parameter can only be one unless fDetachedHash is set to TRUE. /// /// An array of pointers to buffers that contain the contents to be hashed. /// An array of sizes, in bytes, of the buffers pointed to by rgpbToBeHashed. /// /// A pointer to a buffer to receive the hashed message encoded for transmission. /// /// This parameter can be NULL if the hashed message is not needed for additional processing or to set the size of the hashed /// message for memory allocation purposes. A hashed message will not be returned if this parameter is 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 pbHashedBlob parameter. When the /// function returns, this variable contains the size, in bytes, of the decrypted message copied to pbHashedBlob. This parameter /// must be the address of a DWORD and not NULL or the length of the buffer will not be returned. /// /// /// Note When processing the data returned, applications must 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 will fit 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 a buffer to receive the newly created hash value. This parameter can be NULL if the newly created hash is /// not needed for additional processing, or to set the size of the hash 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 buffer pointed to by the pbComputedHash parameter. When /// the function returns, this DWORD contains the size, in bytes, of the newly created hash that was copied to pbComputedHash. /// /// /// Note When processing the data returned, applications must 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 will fit 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. /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, and CryptGetHashParam might be propagated to this function. /// /// The GetLastError function returns the following error codes most often. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pHashPara is not valid. /// /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbHashedBlob parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code and stores the required buffer size, in bytes, into the variable pointed to by pbHashedBlob. /// /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-crypthashmessage BOOL CryptHashMessage( // PCRYPT_HASH_MESSAGE_PARA pHashPara, BOOL fDetachedHash, DWORD cToBeHashed, const BYTE * [] rgpbToBeHashed, DWORD [] // rgcbToBeHashed, BYTE *pbHashedBlob, DWORD *pcbHashedBlob, BYTE *pbComputedHash, DWORD *pcbComputedHash ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "85a04c01-fd7c-4d87-b6e1-a0f2aea45d16")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptHashMessage(in CRYPT_HASH_MESSAGE_PARA pHashPara, [MarshalAs(UnmanagedType.Bool)] bool fDetachedHash, uint cToBeHashed, [In] IntPtr[] rgpbToBeHashed, [In] uint[] rgcbToBeHashed, [Out] IntPtr pbHashedBlob, ref uint pcbHashedBlob, [Out] IntPtr pbComputedHash, ref uint pcbComputedHash); /// /// The CryptMsgCalculateEncodedLength function calculates the maximum number of bytes needed for an encoded cryptographic /// message given the message type, encoding parameters, and total length of the data to be encoded. Note that the result will /// always be greater than or equal to the actual number of bytes needed. /// /// /// /// 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 /// /// /// /// /// Currently defined flags are shown in the following table. /// /// /// Value /// Meaning /// /// /// CMSG_BARE_CONTENT_FLAG /// /// Indicates that streamed output will not have an outer ContentInfo wrapper (as defined by PKCS #7). This makes it suitable to be /// streamed into an enclosing message. /// /// /// /// CMSG_DETACHED_FLAG /// Indicates that there is detached data being supplied for the subsequent calls to CryptMsgUpdate. /// /// /// CMSG_CONTENTS_OCTETS_FLAG /// /// Used to calculate the size of a DER encoding of a message to be nested inside an enveloped message. This is particularly useful /// when streaming is being performed. /// /// /// /// CMSG_CMS_ENCAPSULATED_CONTENT_FLAG /// /// Non-Data type inner content is encapsulated within an OCTET STRING. This flag is applicable for both Signed and Enveloped messages. /// /// /// /// /// /// Currently defined message types are shown in the following table. /// /// /// Value /// Meaning /// /// /// CMSG_DATA /// An octet (BYTE) string. /// /// /// CMSG_SIGNED /// CMSG_SIGNED_ENCODE_INFO /// /// /// CMSG_ENVELOPED /// CMSG_ENVELOPED_ENCODE_INFO /// /// /// CMSG_SIGNED_AND_ENVELOPED /// Not implemented. /// /// /// CMSG_HASHED /// CMSG_HASHED_ENCODE_INFO /// /// /// CMSG_ENCRYPTED /// Not implemented. /// /// /// /// /// A pointer to the data to be encoded. The type of data pointed to depends on the value of dwMsgType. For details, see the /// dwMsgType table. /// /// /// /// When calling CryptMsgCalculateEncodedLength with data provided to CryptMsgUpdate already encoded, the appropriate object /// identifier is passed in pszInnerContentObjID. If pszInnerContentObjID is NULL, the inner content type is assumed not to /// have been previously encoded, and is encoded as an octet string and given the type CMSG_DATA. /// /// When streaming is being used, pszInnerContentObjID must be either NULL or szOID_RSA_data. /// The following algorithm object identifiers are commonly used: /// /// /// szOID_RSA_data /// /// /// szOID_RSA_signedData /// /// /// szOID_RSA_envelopedData /// /// /// szOID_RSA_signEnvData /// /// /// szOID_RSA_digestedData /// /// /// szOID_RSA_encryptedData /// /// /// SPC_INDIRECT_DATA_OBJID /// /// /// /// A user can define new inner content usage. The user must ensure that the sender and receiver of the message agree upon the /// semantics associated with the object identifier. /// /// /// The size, in bytes, of the content. /// /// /// Returns the required length for an encoded cryptographic message. This length might not be the exact length but it will not be /// less than the required length. Zero is returned if the function fails. /// /// /// To retrieve extended error information, use the GetLastError function. The following table lists the error codes most commonly returned. /// /// /// /// Return code /// Description /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgcalculateencodedlength DWORD // CryptMsgCalculateEncodedLength( DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, void const *pvMsgEncodeInfo, LPSTR // pszInnerContentObjID, DWORD cbData ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "1c12003a-c2f3-4069-8bd6-b8f2875b0c98")] public static extern uint CryptMsgCalculateEncodedLength(CertEncodingType dwMsgEncodingType, CryptMsgFlags dwFlags, CryptMsgType dwMsgType, [In] IntPtr pvMsgEncodeInfo, [Optional] SafeOID pszInnerContentObjID, uint cbData); /// /// The CryptMsgClose function closes a cryptographic message handle. At each call to this function, the reference count on /// the message is reduced by one. When the reference count reaches zero, the message is fully released. /// /// Handle of the cryptographic message to be closed. /// /// 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-cryptmsgclose BOOL CryptMsgClose( HCRYPTMSG hCryptMsg ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "2478dd60-233a-4ef3-86e9-62d2a59ab28a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgClose(HCRYPTMSG hCryptMsg); /// /// /// The CryptMsgControl function performs a control operation after a message has been decoded by a final call to the /// CryptMsgUpdate function. The control operations provided by this function are used for decryption, signature and hash /// verification, and the addition and deletion of certificates, certificate revocation lists (CRLs), signers, and unauthenticated attributes. /// /// /// Important changes that affect the handling of enveloped messages have been made to CryptoAPI to support Secure/Multipurpose /// Internet Mail Extensions (S/MIME) email interoperability. For more information, see the Remarks for the CryptMsgOpenToEncode function. /// /// /// A handle of a cryptographic message for which a control is to be applied. /// /// The following value is defined when the dwCtrlType parameter is one of the following: /// /// /// CMSG_CTRL_DECRYPT /// /// /// CMSG_CTRL_KEY_TRANS_DECRYPT /// /// /// CMSG_CTRL_KEY_AGREE_DECRYPT /// /// /// CMSG_CTRL_MAIL_LIST_DECRYPT /// /// /// /// /// Value /// Meaning /// /// /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG /// /// The handle to the cryptographic provider is released on the final call to the CryptMsgClose function. This handle is not /// released if the CryptMsgControl function fails. /// /// /// /// If the dwCtrlType parameter does not specify a decrypt operation, set this value to zero. /// /// /// /// The type of operation to be performed. Currently defined message control types and the type of structure that should be passed /// to the pvCtrlPara parameter are shown in the following table. /// /// /// /// Value /// Meaning /// /// /// CMSG_CTRL_ADD_ATTR_CERT 14 (0xE) /// A BLOB that contains the encoded bytes of attribute certificate. /// /// /// CMSG_CTRL_ADD_CERT 10 (0xA) /// A CRYPT_INTEGER_BLOB structure that contains the encoded bytes of the certificate to be added to the message. /// /// /// CMSG_CTRL_ADD_CMS_SIGNER_INFO 20 (0x14) /// /// A CMSG_CMS_SIGNER_INFO structure that contains signer information. This operation differs from CMSG_CTRL_ADD_SIGNER because the /// signer information contains the signature. /// /// /// /// CMSG_CTRL_ADD_CRL 12 (0xC) /// A BLOB that contains the encoded bytes of the CRL to be added to the message. /// /// /// CMSG_CTRL_ADD_SIGNER 6 (0x6) /// A CMSG_SIGNER_ENCODE_INFO structure that contains the signer information to be added to the message. /// /// /// CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR 8 (0x8) /// /// A CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA structure that contains the index of the signer and a BLOB that contains the /// unauthenticated attribute information to be added to the message. /// /// /// /// CMSG_CTRL_DECRYPT 2 (0x2) /// /// A CMSG_CTRL_DECRYPT_PARA structure used to decrypt the message for the specified key transport recipient. This value is /// applicable to RSA recipients. This operation specifies that the CryptMsgControl function search the recipient index to obtain /// the key transport recipient information. If the function fails, GetLastError will return CRYPT_E_INVALID_INDEX if no key /// transport recipient is found. /// /// /// /// CMSG_CTRL_DEL_ATTR_CERT 15 (0xF) /// The index of the attribute certificate to be removed. /// /// /// CMSG_CTRL_DEL_CERT 11 (0xB) /// The index of the certificate to be deleted from the message. /// /// /// CMSG_CTRL_DEL_CRL 13 (0xD) /// The index of the CRL to be deleted from the message. /// /// /// CMSG_CTRL_DEL_SIGNER 7 (0x7) /// The index of the signer to be deleted. /// /// /// CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR 9 (0x9) /// /// A CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA structure that contains an index that specifies the signer and the index that specifies /// the signer's unauthenticated attribute to be deleted. /// /// /// /// CMSG_CTRL_ENABLE_STRONG_SIGNATURE 21 (0x15) /// /// A CERT_STRONG_SIGN_PARA structure used to perform strong signature checking. To check for a strong signature, specify this /// control type before calling CryptMsgGetAndVerifySigner or before calling CryptMsgControl with the following control types set: /// After the signature is successfully verified, this function checks for a strong signature. If the signature is not strong, the /// operation will fail and the GetLastError value will be set to NTE_BAD_ALGID. /// /// /// /// CMSG_CTRL_KEY_AGREE_DECRYPT 17 (0x11) /// /// A CMSG_CTRL_KEY_AGREE_DECRYPT_PARA structure used to decrypt the message for the specified key agreement session key. Key /// agreement is used with Diffie-Hellman encryption/decryption. /// /// /// /// CMSG_CTRL_KEY_TRANS_DECRYPT 16 (0x10) /// /// A CMSG_CTRL_KEY_TRANS_DECRYPT_PARA structure used to decrypt the message for the specified key transport recipient. Key /// transport is used with RSA encryption/decryption. /// /// /// /// CMSG_CTRL_MAIL_LIST_DECRYPT 18 (0x12) /// /// A CMSG_CTRL_MAIL_LIST_DECRYPT_PARA structure used to decrypt the message for the specified recipient using a previously /// distributed key-encryption key (KEK). /// /// /// /// CMSG_CTRL_VERIFY_HASH 5 (0x5) /// This value is not used. /// /// /// CMSG_CTRL_VERIFY_SIGNATURE 1 (0x1) /// A CERT_INFO structure that identifies the signer of the message whose signature is to be verified. /// /// /// CMSG_CTRL_VERIFY_SIGNATURE_EX 19 (0x13) /// /// A CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA structure that specifies the signer index and public key to verify the message signature. /// The signer public key can be a CERT_PUBLIC_KEY_INFO structure, a certificate context, or a certificate chain context. /// /// /// /// /// /// A pointer to a structure determined by the value of dwCtrlType. /// /// /// dwCtrlType value /// Meaning /// /// /// /// CMSG_CTRL_DECRYPT, CMSG_CTRL_KEY_TRANS_DECRYPT, CMSG_CTRL_KEY_AGREE_DECRYPT, or CMSG_CTRL_MAIL_LIST_DECRYPT, and the streamed /// enveloped message is being decoded /// /// /// Decoding will be done as if the streamed content were being decrypted. If any encrypted streamed content has accumulated prior /// to this call, some or all of the plaintext that results from the decryption of the cipher text is passed back to the application /// through the callback function specified in the call to the CryptMsgOpenToDecode function. /// /// /// /// CMSG_CTRL_VERIFY_HASH /// The hash computed from the content of the message is compared against the hash contained in the message. /// /// /// CMSG_CTRL_ADD_SIGNER /// pvCtrlPara points to a CMSG_SIGNER_ENCODE_INFO structure that contains the signer information to be added to the message. /// /// /// CMSG_CTRL_DEL_SIGNER /// /// After a deletion is made, any other signer indices in use for this message are no longer valid and must be reacquired by calling /// the CryptMsgGetParam function. /// /// /// /// CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR /// /// After a deletion is made, any other unauthenticated attribute indices in use for this signer are no longer valid and must be /// reacquired by calling the CryptMsgGetParam function. /// /// /// /// CMSG_CTRL_DEL_CERT /// /// After a deletion is made, any other certificate indices in use for this message are no longer valid and must be reacquired by /// calling the CryptMsgGetParam function. /// /// /// /// CMSG_CTRL_DEL_CRL /// /// After a deletion is made, any other CRL indices in use for this message are no longer valid and will need to be reacquired by /// calling the CryptMsgGetParam function. /// /// /// /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero and the GetLastError function returns an Abstract Syntax Notation One (ASN.1) /// encoding/decoding error. For information about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// When a streamed, enveloped message is being decoded, errors encountered in the application-defined callback function specified /// by the pStreamInfo parameter of the CryptMsgOpenToDecode function might be propagated to the CryptMsgControl function. If /// this happens, the SetLastError function is not called by the CryptMsgControl function after the callback function /// returns. This preserves any errors encountered under the control of the application. It is the responsibility of the callback /// function (or one of the APIs that it calls) to call the SetLastError function if an error occurs while the application is /// processing the streamed data. /// /// Propagated errors might be encountered from the following functions: /// /// /// CryptCreateHash /// /// /// CryptDecrypt /// /// /// CryptGetHashParam /// /// /// CryptGetUserKey /// /// /// CryptHashData /// /// /// CryptImportKey /// /// /// CryptSignHash /// /// /// CryptVerifySignature /// /// /// The following error codes are most commonly returned. /// /// /// Return code /// Description /// /// /// CRYPT_E_ALREADY_DECRYPTED /// The message content has already been decrypted. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_DECRYPT. /// /// /// CRYPT_E_AUTH_ATTR_MISSING /// /// The message does not contain an expected authenticated attribute. This error can be returned if the dwCtrlType parameter is set /// to CMSG_CTRL_VERIFY_SIGNATURE. /// /// /// /// CRYPT_E_BAD_ENCODE /// /// An error was encountered while encoding or decoding. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_VERIFY_SIGNATURE. /// /// /// /// CRYPT_E_CONTROL_TYPE /// The control type is not valid. /// /// /// CRYPT_E_HASH_VALUE /// The hash value is incorrect. /// /// /// CRYPT_E_INVALID_INDEX /// The index value is not valid. /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_OID_FORMAT /// The object identifier is badly formatted. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_ADD_SIGNER. /// /// /// CRYPT_E_RECIPIENT_NOT_FOUND /// /// The enveloped data message does not contain the specified recipient. This error can be returned if the dwCtrlType parameter is /// set to CMSG_CTRL_DECRYPT. /// /// /// /// CRYPT_E_SIGNER_NOT_FOUND /// The specified signer for the message was not found. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_VERIFY_SIGNATURE. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// CRYPT_E_UNEXPECTED_ENCODING /// The message is not encoded as expected. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_VERIFY_SIGNATURE. /// /// /// E_INVALIDARG /// One or more arguments are not valid. This error can be returned if the dwCtrlType parameter is set to CMSG_CTRL_DECRYPT. /// /// /// E_OUTOFMEMORY /// Not enough memory was available to complete the operation. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgcontrol BOOL CryptMsgControl( HCRYPTMSG // hCryptMsg, DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "a990d44d-2993-429f-b817-2a834105ecef")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgControl(HCRYPTMSG hCryptMsg, CryptMsgFlags dwFlags, CryptMsgControlType dwCtrlType, [In, Optional] IntPtr pvCtrlPara); /// /// The CryptMsgCountersign function countersigns an existing signature in a message. Countersignatures are used to sign an /// existing signature's encrypted hash of the message. Countersignatures can be used for various purposes including time stamping a message. /// /// Cryptographic message handle to be used. /// Zero-based index of the signer in the signed or signed-and-enveloped message to be countersigned. /// Number of countersigners in the rgCountersigners array. /// Array of countersigners' CMSG_SIGNER_ENCODE_INFO structures. /// /// If the function succeeds, the function returns nonzero ( TRUE). /// If the function fails, it returns zero ( FALSE). For extended error information, call GetLastError. /// An error can be propagated from CryptMsgCountersignEncoded. /// The following error codes are returned most often. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// Ran out of memory. /// /// /// ERROR_MORE_DATA /// The specified area is not large enough to hold the returned data. /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgcountersign BOOL CryptMsgCountersign( HCRYPTMSG // hCryptMsg, DWORD dwIndex, DWORD cCountersigners, PCMSG_SIGNER_ENCODE_INFO rgCountersigners ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "ebf76664-bca6-462d-b519-2b60f435d8ef")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgCountersign(HCRYPTMSG hCryptMsg, uint dwIndex, uint cCountersigners, [In, MarshalAs(UnmanagedType.LPArray)] CMSG_SIGNER_ENCODE_INFO[] rgCountersigners); /// /// The CryptMsgCountersignEncoded function countersigns an existing PKCS #7 message signature. The pbCountersignature /// BYTE buffer it creates is a PKCS #7 encoded SignerInfo that can be used as an unauthenticated Countersignature attribute /// of a PKCS #9 signed-data or signed-and-enveloped-data message. /// /// /// /// Specifies the encoding type used. Currently, only X509_ASN_ENCODING and PKCS_7_ASN_ENCODING are being used; however, additional /// encoding types may be added in the future. For either current encoding type, use: /// /// X509_ASN_ENCODING | PKCS_7_ASN_ENCODING. /// /// A pointer to the encoded SignerInfo that is to be countersigned. /// Count, in bytes, of the encoded SignerInfo data. /// Number of countersigners in the rgCountersigners array. /// Array of countersigners' CMSG_SIGNER_ENCODE_INFO structures. /// /// A pointer to a buffer to receive an encoded PKCS #9 countersignature attribute. /// /// On input, this parameter can be NULL to set the size of this information for memory allocation purposes. For more /// information, see Retrieving Data of Unknown Length. /// /// /// /// A pointer to a variable that specifies the size, in bytes, of the buffer pointed to by the pbCountersignature parameter. When /// the function returns, the variable pointed to by the pcbCountersignature parameter contains the number of bytes stored in the buffer. /// /// /// 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. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_OID_FORMAT /// The object identifier is badly formatted. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// Ran out of memory. /// /// /// Propagated errors might be returned from one of the following functions: /// /// /// CryptCreateHash /// /// /// CryptHashData /// /// /// CryptGetHashParam /// /// /// CryptSignHash /// /// /// CryptMsgOpenToEncode /// /// /// CryptMsgUpdate /// /// /// CryptMsgControl /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgcountersignencoded BOOL // CryptMsgCountersignEncoded( DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD cbSignerInfo, DWORD cCountersigners, // PCMSG_SIGNER_ENCODE_INFO rgCountersigners, PBYTE pbCountersignature, PDWORD pcbCountersignature ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d9fd734b-e14d-4392-ac88-5565aefbedb4")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgCountersignEncoded(CertEncodingType dwEncodingType, [In] IntPtr pbSignerInfo, uint cbSignerInfo, uint cCountersigners, [In, MarshalAs(UnmanagedType.LPArray)] CMSG_SIGNER_ENCODE_INFO[] rgCountersigners, [Out] IntPtr pbCountersignature, ref uint pcbCountersignature); /// The CryptMsgDuplicate function duplicates a cryptographic message handle by incrementing its reference count. /// /// Handle of the cryptographic message to be duplicated. Duplication is done by incrementing the reference count of the message. A /// copy of the message is not made. /// /// /// The returned handle is the same as the handle input. A copy of the message is not created. When you have finished using the /// duplicated message handle, decrease the reference count by calling the CryptMsgClose function. /// /// /// /// CryptMsgDuplicate is used to increase the reference count on an HCRYPTMSG handle so that multiple calls to /// CryptMsgClose are required to actually release the handle. /// /// Examples /// For an example that uses this function, see Example C Program: Encoding and Decoding a Hashed Message. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgduplicate HCRYPTMSG CryptMsgDuplicate( HCRYPTMSG // hCryptMsg ); [DllImport(Lib.Crypt32, SetLastError = false, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "9b1142b9-0caa-4304-bfe6-1c27c6a7b782")] public static extern HCRYPTMSG CryptMsgDuplicate(HCRYPTMSG hCryptMsg); /// /// The CryptMsgGetParam function acquires a message parameter after a cryptographic message has been encoded or decoded. /// This function is called after the final CryptMsgUpdate call. /// /// Handle of a cryptographic message. /// /// /// Indicates the parameter types of data to be retrieved. The type of data to be retrieved determines the type of structure to use /// for pvData. /// /// /// For an encoded message, only the CMSG_BARE_CONTENT, CMSG_ENCODE_SIGNER, CMSG_CONTENT_PARAM and CMSG_COMPUTED_HASH_PARAM /// dwParamTypes are valid. /// /// /// /// Value /// Meaning /// /// /// CMSG_ATTR_CERT_COUNT_PARAM /// pvData data type: pointer to a DWORD Returns the count of the attribute certificates in a SIGNED or ENVELOPED message. /// /// /// CMSG_ATTR_CERT_PARAM /// /// pvData data type: pointer to a BYTE array Retrieves an attribute certificate. To get all the attribute certificates, call /// CryptMsgGetParam varying dwIndex set to 0 the number of attributes minus one. /// /// /// /// CMSG_BARE_CONTENT_PARAM /// /// pvData data type: pointer to a BYTE array Retrieves the encoded content of an encoded cryptographic message, without the outer /// layer of the CONTENT_INFO structure. That is, only the encoding of the PKCS #7 defined ContentInfo.content field is returned. /// /// /// /// CMSG_CERT_COUNT_PARAM /// pvData data type: pointer to DWORD Returns the number of certificates in a received SIGNED or ENVELOPED message. /// /// /// CMSG_CERT_PARAM /// /// pvData data type: pointer to a BYTE array Returns a signer's certificate. To get all of the signer's certificates, call /// CryptMsgGetParam, varying dwIndex from 0 to the number of available certificates minus one. /// /// /// /// CMSG_COMPUTED_HASH_PARAM /// /// pvData data type: pointer to a BYTE array Returns the hash calculated of the data in the message. This type is applicable to /// both encode and decode. /// /// /// /// CMSG_CONTENT_PARAM /// /// pvData data type: pointer to a BYTE array Returns the whole PKCS #7 message from a message opened to encode. Retrieves the inner /// content of a message opened to decode. If the message is enveloped, the inner type is data, and CryptMsgControl has been called /// to decrypt the message, the decrypted content is returned. If the inner type is not data, the encoded BLOB that requires further /// decoding is returned. If the message is not enveloped and the inner content is DATA, the returned data is the octets of the /// inner content. This type is applicable to both encode and decode. For decoding, if the type is CMSG_DATA, the content's octets /// are returned; else, the encoded inner content is returned. /// /// /// /// CMSG_CRL_COUNT_PARAM /// pvData data type: pointer to DWORD Returns the count of CRLs in a received, SIGNED or ENVELOPED message. /// /// /// CMSG_CRL_PARAM /// /// pvData data type: pointer to a BYTE array Returns a CRL. To get all the CRLs, call CryptMsgGetParam, varying dwIndex from 0 to /// the number of available CRLs minus one. /// /// /// /// CMSG_ENCODED_MESSAGE /// /// pvData data type: pointer to a BYTE array Changes the contents of an already encoded message. The message must first be decoded /// with a call to CryptMsgOpenToDecode. Then the change to the message is made through a call to CryptMsgControl, /// CryptMsgCountersign, or CryptMsgCountersignEncoded. The message is then encoded again with a call to CryptMsgGetParam, /// specifying CMSG_ENCODED_MESSAGE to get a new encoding that reflects the changes made. This can be used, for instance, to add a /// time-stamp attribute to a message. /// /// /// /// CMSG_ENCODED_SIGNER /// pvData data type: pointer to a BYTE array Returns the encoded CMSG_SIGNER_INFO signer information for a message signer. /// /// /// CMSG_ENCRYPTED_DIGEST /// pvData data type: pointer to a BYTE array Returns the encrypted hash of a signature. Typically used for performing time-stamping. /// /// /// CMSG_ENCRYPT_PARAM /// /// pvData data type: pointer to a BYTE array for a CRYPT_ALGORITHM_IDENTIFIER structure. Returns the encryption algorithm used to /// encrypted the message. /// /// /// /// CMSG_ENVELOPE_ALGORITHM_PARAM /// /// pvData data type: pointer to a BYTE array for a CRYPT_ALGORITHM_IDENTIFIER structure. Returns the encryption algorithm used to /// encrypt an ENVELOPED message. /// /// /// /// CMSG_HASH_ALGORITHM_PARAM /// /// pvData data type: pointer to a BYTE array for a CRYPT_ALGORITHM_IDENTIFIER structure. Returns the hash algorithm used to hash /// the message when it was created. /// /// /// /// CMSG_HASH_DATA_PARAM /// pvData data type: pointer to a BYTE array Returns the hash value stored in the message when it was created. /// /// /// CMSG_INNER_CONTENT_TYPE_PARAM /// /// pvData data type: pointer to a BYTE array to receive a null-terminated object identifier (OID) string. Returns the inner content /// type of a received message. This type is not applicable to messages of type DATA. /// /// /// /// CMSG_RECIPIENT_COUNT_PARAM /// pvData data type: pointer to a DWORD Returns the number of key transport recipients of an ENVELOPED received message. /// /// /// CMSG_CMS_RECIPIENT_COUNT_PARAM /// /// pvData data type: pointer to DWORD Returns the total count of all message recipients including key agreement and mail list recipients. /// /// /// /// CMSG_RECIPIENT_INDEX_PARAM /// /// pvData data type: pointer to a DWORD Returns the index of the key transport recipient used to decrypt an ENVELOPED message. This /// value is available only after a message has been decrypted. /// /// /// /// CMSG_CMS_RECIPIENT_INDEX_PARAM /// /// pvData data type: pointer to a DWORD Returns the index of the key transport, key agreement, or mail list recipient used to /// decrypt an ENVELOPED message. /// /// /// /// CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM /// /// pvData data type: pointer to a DWORD Returns the index of the encrypted key of a key agreement recipient used to decrypt an /// ENVELOPED message. /// /// /// /// CMSG_RECIPIENT_INFO_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CERT_INFO structure. Returns certificate information about a key /// transport message's recipient. To get certificate information on all key transport message's recipients, repetitively call /// CryptMsgGetParam, varying dwIndex from 0 to the number of recipients minus one. Only the Issuer, SerialNumber, and /// PublicKeyAlgorithm members of the CERT_INFO structure returned are available and valid. /// /// /// /// CMSG_CMS_RECIPIENT_INFO_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CMSG_CMS_RECIPIENT_INFO structure. Returns information about a key /// transport, key agreement, or mail list recipient. It is not limited to key transport message recipients. To get information on /// all of a message's recipients, repetitively call CryptMsgGetParam, varying dwIndex from 0 to the number of recipients minus one. /// /// /// /// CMSG_SIGNER_AUTH_ATTR_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CRYPT_ATTRIBUTES structure. Returns the authenticated attributes of a /// message signer. To retrieve the authenticated attributes for a specified signer, call CryptMsgGetParam with dwIndex equal to /// that signer's index. /// /// /// /// CMSG_SIGNER_CERT_INFO_PARAM /// /// pvData data type: pointer to a BYTE array to receive the CERT_INFO structure. Returns information on a message signer needed to /// identify the signer's certificate. A certificate's Issuer and SerialNumber can be used to uniquely identify a certificate for /// retrieval. To retrieve information for all the signers, repetitively call CryptMsgGetParam varying dwIndex from 0 to the number /// of signers minus one. Only the Issuer and SerialNumber fields in the CERT_INFO structure returned contain available, valid data. /// /// /// /// CMSG_SIGNER_CERT_ID_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CERT_ID structure. Returns information on a message signer needed to /// identify the signer's public key. This could be a certificate's Issuer and SerialNumber, a KeyID, or a HashId. To retrieve /// information for all the signers, call CryptMsgGetParam varying dwIndex from 0 to the number of signers minus one. /// /// /// /// CMSG_SIGNER_COUNT_PARAM /// pvData data type: pointer to a DWORD Returns the number of signers of a received SIGNED message. /// /// /// CMSG_SIGNER_HASH_ALGORITHM_PARAM /// /// pvData data type: pointer to a BYTE array to receive the CRYPT_ALGORITHM_IDENTIFIER structure. Returns the hash algorithm used /// by a signer of the message. To get the hash algorithm for a specified signer, call CryptMsgGetParam with dwIndex equal to that /// signer's index. /// /// /// /// CMSG_SIGNER_INFO_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CMSG_SIGNER_INFO structure. Returns information on a message signer. This /// includes the issuer and serial number of the signer's certificate and authenticated and unauthenticated attributes of the /// signer's certificate. To retrieve signer information on all of the signers of a message, call CryptMsgGetParam varying dwIndex /// from 0 to the number of signers minus one. /// /// /// /// CMSG_CMS_SIGNER_INFO_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CMSG_CMS_SIGNER_INFO structure. Returns information on a message signer. /// This includes a signerId and authenticated and unauthenticated attributes. To retrieve signer information on all of the signers /// of a message, call CryptMsgGetParam varying dwIndex from 0 to the number of signers minus one. /// /// /// /// CMSG_SIGNER_UNAUTH_ATTR_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CRYPT_ATTRIBUTES structure. Returns a message signer's unauthenticated /// attributes. To retrieve the unauthenticated attributes for a specified signer, call CryptMsgGetParam with dwIndex equal to that /// signer's index. /// /// /// /// CMSG_TYPE_PARAM /// /// pvData data type: pointer to a DWORD Returns the message type of a decoded message of unknown type. The retrieved message type /// can be compared to supported types to determine whether processing can continued. For supported message types, see the /// dwMessageType parameter of CryptMsgOpenToDecode. /// /// /// /// CMSG_UNPROTECTED_ATTR_PARAM /// /// pvData data type: pointer to a BYTE array to receive a CMSG_ATTR structure. Returns the unprotected attributes in an enveloped message. /// /// /// /// CMSG_VERSION_PARAM /// /// pvData data type: pointer to a DWORD Returns the version of the decoded message. For more information, see the table in the /// Remarks section. /// /// /// /// /// /// Index for the parameter being retrieved, where applicable. When a parameter is not being retrieved, this parameter is ignored /// and is set to zero. /// /// /// /// A pointer to a buffer that receives the data retrieved. The form of this data will vary depending on the value of the /// dwParamType parameter. /// /// /// This parameter can be NULL to set the size of this information for memory allocation purposes. For more information, see /// Retrieving Data of Unknown Length. /// /// /// When processing the data returned in this 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 will fit 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 a variable that specifies the size, in bytes, of the buffer pointed to by the pvData parameter. When the function /// returns, the variable pointed to by the pcbData parameter contains the number of bytes stored in the buffer. /// /// /// 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. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_ATTRIBUTES_MISSING /// The message does not contain the requested attributes. /// /// /// CRYPT_E_INVALID_INDEX /// The index value is not valid. /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_NOT_DECRYPTED /// The message content has not been decrypted yet. /// /// /// CRYPT_E_OID_FORMAT /// The object identifier is badly formatted. /// /// /// CRYPT_E_UNEXPECTED_ENCODING /// The message is not encoded as expected. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// ERROR_MORE_DATA /// The specified buffer is not large enough to hold the returned data. /// /// /// For dwParamType CMSG_COMPUTED_HASH_PARAM, an error can be propagated from CryptGetHashParam. /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// The following version numbers are returned by calls to CryptMsgGetParam with dwParamType set to CMSG_VERSION_PARAM are defined: /// /// /// /// CMSG_SIGNED_DATA_V1 /// /// /// CMSG_SIGNED_DATA_V3 /// /// /// CMSG_SIGNED_DATA_PKCS_1_5_VERSION /// /// /// CMSG_SIGNED_DATA_CMS_VERSION /// /// /// CMSG_SIGNER_INFO_V1 /// /// /// CMSG_SIGNER_INFO_V3 /// /// /// CMSG_SIGNER_INFO_PKCS_1_5_VERSION /// /// /// CMSG_SIGNER_INFO_CMS_VERSION /// /// /// CMSG_HASHED_DATA_V0 /// /// /// CMSG_HASHED_DATA_V2 /// /// /// CMSG_HASHED_DATA_PKCS_1_5_VERSION /// /// /// CMSG_HASHED_DATA_CMS_VERSION /// /// /// CMSG_ENVELOPED_DATA_V0 /// /// /// CMSG_ENVELOPED_DATA_V2 /// /// /// CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION /// /// /// CMSG_ENVELOPED_DATA_CMS_VERSION /// /// /// Examples /// /// For an example that uses this function, see Example C Program: Signing, Encoding, Decoding, and Verifying a Message, Alternate /// Code for Encoding an Enveloped Message, Example C Program: Encoding an Enveloped, Signed Message, and Example C Program: /// Encoding and Decoding a Hashed Message. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsggetparam BOOL CryptMsgGetParam( HCRYPTMSG // hCryptMsg, DWORD dwParamType, DWORD dwIndex, void *pvData, DWORD *pcbData ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "5a05eb09-208f-4e94-abfa-c2f14c0a3164")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgGetParam(HCRYPTMSG hCryptMsg, CryptMsgParamType dwParamType, uint dwIndex, [Out] IntPtr pvData, ref uint pcbData); /// /// /// The CryptMsgOpenToDecode function opens a cryptographic message for decoding and returns a handle of the opened message. /// The message remains open until the CryptMsgClose function is called. /// /// /// Important changes that affect the handling of enveloped messages have been made to CryptoAPI to support Secure/Multipurpose /// Internet Mail Extensions (S/MIME) email interoperability. For details, see the Remarks section of CryptMsgOpenToEncode. /// /// /// /// /// 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 /// /// /// /// /// This parameter can be one of the following flags. /// /// /// Value /// Meaning /// /// /// CMSG_DETACHED_FLAG /// Indicates that the message to be decoded is detached. If this flag is not set, the message is not detached. /// /// /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG /// /// If set, the hCryptProv passed to this function is released on the final CryptMsgUpdate. The handle is not released if the /// function fails. /// /// /// /// /// /// /// Specifies the type of message to decode. In most cases, the message type is determined from the message header and zero is /// passed for this parameter. In some cases, notably with Internet Explorer 3.0, messages do not have headers and the type of /// message to be decoded must be supplied in this function call. If the header is missing and zero is passed for this parameter, /// the function fails. /// /// This parameter can be one of the following predefined message types. /// /// /// Value /// Meaning /// /// /// CMSG_DATA /// The message is encoded data. /// /// /// CMSG_ENVELOPED /// The message is an enveloped message. /// /// /// CMSG_HASHED /// The message is a hashed message. /// /// /// CMSG_SIGNED /// The message is a signed message. /// /// /// CMSG_SIGNED_AND_ENVELOPED /// The message is a signed and enveloped message. /// /// /// /// /// This parameter is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: Specifies a handle for the cryptographic provider to use for hashing the message. For /// signed messages, hCryptProv is used for signature verification.This parameter's data type is HCRYPTPROV. /// /// /// Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, set this parameter to /// NULL. Passing in NULL causes the default RSA or DSS provider to be acquired before performing hash, signature /// verification, or recipient encryption operations. /// /// /// This parameter is reserved for future use and must be NULL. /// /// When streaming is not being used, this parameter must be set to NULL. /// /// Note Streaming is not used with CMSG_HASHED messages. When dealing with hashed data, this parameter must be set to NULL. /// /// /// When streaming is being used, the pStreamInfo parameter is a pointer to a CMSG_STREAM_INFO structure that contains a pointer to /// a callback to be called when CryptMsgUpdate is executed or when CryptMsgControl is executed when decoding a streamed enveloped message. /// /// For a signed message, the callback is passed a block of the decoded bytes from the inner content of the message. /// /// For an enveloped message, after each call to CryptMsgUpdate, you must check to determine whether the /// CMSG_ENVELOPE_ALGORITHM_PARAM property is available by calling the CryptMsgGetParam function. CryptMsgGetParam will fail /// and GetLastError will return CRYPT_E_STREAM_MSG_NOT_READY until CryptMsgUpdate has processed enough of the message to /// make the CMSG_ENVELOPE_ALGORITHM_PARAM property available. When the CMSG_ENVELOPE_ALGORITHM_PARAM property is available, you can /// iterate through the recipients, retrieving a CERT_INFO structure for each recipient by using the CryptMsgGetParam /// function to retrieve the CMSG_RECIPIENT_INFO_PARAM property. To prevent a denial of service attack from an enveloped message /// that has an artificially large header block, you must keep track of the amount of memory that has been passed to the /// CryptMsgUpdate function during this process. If the amount of data exceeds an application defined limit before the /// CMSG_ENVELOPE_ALGORITHM_PARAM property is available, you must stop processing the message and call the CryptMsgClose function to /// cause the operating system to release any memory that has been allocated for the message. A suggested limit is the maximum /// allowable size of a message. For example, if the maximum message size is 10 MB, the limit for this test should be 10 MB. /// /// /// The CERT_INFO structure is used to find a matching certificate in a previously opened certificate store by using the /// CertGetSubjectCertificateFromStore function. When the correct certificate is found, the CertGetCertificateContextProperty /// function with a CERT_KEY_PROV_INFO_PROP_ID parameter is called to retrieve a CRYPT_KEY_PROV_INFO structure. The structure /// contains the information necessary to acquire the recipient's private key by calling CryptAcquireContext, using the /// pwszContainerName, pwszProvName, dwProvType, and dwFlags members of the CRYPT_KEY_PROV_INFO /// structure. The hCryptProv acquired and the dwKeySpec member of the CRYPT_KEY_PROV_INFO structure are passed /// to the CryptMsgControl structure as a member of the CMSG_CTRL_DECRYPT_PARA structure to permit the start of the decryption of /// the inner content. The streaming code will then perform the decryption as the data is input. The resulting blocks of plaintext /// are passed to the callback function specified by the pfnStreamOutput member of the CMSG_STREAM_INFO structure to handle /// the output of the decrypted message. /// /// /// Note Streamed decoding of an enveloped message queues the ciphertext in memory until CryptMsgControl is called to start /// the decryption. The application must initiate decrypting in a timely manner so that the data can be saved to disk or routed /// elsewhere before the accumulated ciphertext becomes too large and the system runs out of memory. /// /// /// In the case of a signed message enclosed in an enveloped message, the plaintext output from the streaming decode of the /// enveloped message can be fed into another streaming decode to process the signed message. /// /// /// /// If the function succeeds, the function returns the handle of the opened message. /// If the function fails, it returns NULL. For extended error information, call GetLastError. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Value /// Description /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// A memory allocation failure occurred. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgopentodecode HCRYPTMSG CryptMsgOpenToDecode( // DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo, // PCMSG_STREAM_INFO pStreamInfo ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b3df6312-c866-4faa-8b89-bda67c697631")] public static extern SafeHCRYPTMSG CryptMsgOpenToDecode(CertEncodingType dwMsgEncodingType, CryptMsgFlags dwFlags, CryptMsgType dwMsgType, [Optional] HCRYPTPROV hCryptProv, [Optional] IntPtr pRecipientInfo, in CMSG_STREAM_INFO pStreamInfo); /// /// /// The CryptMsgOpenToDecode function opens a cryptographic message for decoding and returns a handle of the opened message. /// The message remains open until the CryptMsgClose function is called. /// /// /// Important changes that affect the handling of enveloped messages have been made to CryptoAPI to support Secure/Multipurpose /// Internet Mail Extensions (S/MIME) email interoperability. For details, see the Remarks section of CryptMsgOpenToEncode. /// /// /// /// /// 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 /// /// /// /// /// This parameter can be one of the following flags. /// /// /// Value /// Meaning /// /// /// CMSG_DETACHED_FLAG /// Indicates that the message to be decoded is detached. If this flag is not set, the message is not detached. /// /// /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG /// /// If set, the hCryptProv passed to this function is released on the final CryptMsgUpdate. The handle is not released if the /// function fails. /// /// /// /// /// /// /// Specifies the type of message to decode. In most cases, the message type is determined from the message header and zero is /// passed for this parameter. In some cases, notably with Internet Explorer 3.0, messages do not have headers and the type of /// message to be decoded must be supplied in this function call. If the header is missing and zero is passed for this parameter, /// the function fails. /// /// This parameter can be one of the following predefined message types. /// /// /// Value /// Meaning /// /// /// CMSG_DATA /// The message is encoded data. /// /// /// CMSG_ENVELOPED /// The message is an enveloped message. /// /// /// CMSG_HASHED /// The message is a hashed message. /// /// /// CMSG_SIGNED /// The message is a signed message. /// /// /// CMSG_SIGNED_AND_ENVELOPED /// The message is a signed and enveloped message. /// /// /// /// /// This parameter is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: Specifies a handle for the cryptographic provider to use for hashing the message. For /// signed messages, hCryptProv is used for signature verification.This parameter's data type is HCRYPTPROV. /// /// /// Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, set this parameter to /// NULL. Passing in NULL causes the default RSA or DSS provider to be acquired before performing hash, signature /// verification, or recipient encryption operations. /// /// /// This parameter is reserved for future use and must be NULL. /// /// When streaming is not being used, this parameter must be set to NULL. /// /// Note Streaming is not used with CMSG_HASHED messages. When dealing with hashed data, this parameter must be set to NULL. /// /// /// When streaming is being used, the pStreamInfo parameter is a pointer to a CMSG_STREAM_INFO structure that contains a pointer to /// a callback to be called when CryptMsgUpdate is executed or when CryptMsgControl is executed when decoding a streamed enveloped message. /// /// For a signed message, the callback is passed a block of the decoded bytes from the inner content of the message. /// /// For an enveloped message, after each call to CryptMsgUpdate, you must check to determine whether the /// CMSG_ENVELOPE_ALGORITHM_PARAM property is available by calling the CryptMsgGetParam function. CryptMsgGetParam will fail /// and GetLastError will return CRYPT_E_STREAM_MSG_NOT_READY until CryptMsgUpdate has processed enough of the message to /// make the CMSG_ENVELOPE_ALGORITHM_PARAM property available. When the CMSG_ENVELOPE_ALGORITHM_PARAM property is available, you can /// iterate through the recipients, retrieving a CERT_INFO structure for each recipient by using the CryptMsgGetParam /// function to retrieve the CMSG_RECIPIENT_INFO_PARAM property. To prevent a denial of service attack from an enveloped message /// that has an artificially large header block, you must keep track of the amount of memory that has been passed to the /// CryptMsgUpdate function during this process. If the amount of data exceeds an application defined limit before the /// CMSG_ENVELOPE_ALGORITHM_PARAM property is available, you must stop processing the message and call the CryptMsgClose function to /// cause the operating system to release any memory that has been allocated for the message. A suggested limit is the maximum /// allowable size of a message. For example, if the maximum message size is 10 MB, the limit for this test should be 10 MB. /// /// /// The CERT_INFO structure is used to find a matching certificate in a previously opened certificate store by using the /// CertGetSubjectCertificateFromStore function. When the correct certificate is found, the CertGetCertificateContextProperty /// function with a CERT_KEY_PROV_INFO_PROP_ID parameter is called to retrieve a CRYPT_KEY_PROV_INFO structure. The structure /// contains the information necessary to acquire the recipient's private key by calling CryptAcquireContext, using the /// pwszContainerName, pwszProvName, dwProvType, and dwFlags members of the CRYPT_KEY_PROV_INFO /// structure. The hCryptProv acquired and the dwKeySpec member of the CRYPT_KEY_PROV_INFO structure are passed /// to the CryptMsgControl structure as a member of the CMSG_CTRL_DECRYPT_PARA structure to permit the start of the decryption of /// the inner content. The streaming code will then perform the decryption as the data is input. The resulting blocks of plaintext /// are passed to the callback function specified by the pfnStreamOutput member of the CMSG_STREAM_INFO structure to handle /// the output of the decrypted message. /// /// /// Note Streamed decoding of an enveloped message queues the ciphertext in memory until CryptMsgControl is called to start /// the decryption. The application must initiate decrypting in a timely manner so that the data can be saved to disk or routed /// elsewhere before the accumulated ciphertext becomes too large and the system runs out of memory. /// /// /// In the case of a signed message enclosed in an enveloped message, the plaintext output from the streaming decode of the /// enveloped message can be fed into another streaming decode to process the signed message. /// /// /// /// If the function succeeds, the function returns the handle of the opened message. /// If the function fails, it returns NULL. For extended error information, call GetLastError. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Value /// Description /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// A memory allocation failure occurred. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgopentodecode HCRYPTMSG CryptMsgOpenToDecode( // DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, HCRYPTPROV_LEGACY hCryptProv, PCERT_INFO pRecipientInfo, // PCMSG_STREAM_INFO pStreamInfo ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b3df6312-c866-4faa-8b89-bda67c697631")] public static extern SafeHCRYPTMSG CryptMsgOpenToDecode(CertEncodingType dwMsgEncodingType, CryptMsgFlags dwFlags, CryptMsgType dwMsgType, HCRYPTPROV hCryptProv = default, IntPtr pRecipientInfo = default, IntPtr pStreamInfo = default); /// /// The CryptMsgOpenToEncode function opens a cryptographic message for encoding and returns a handle of the opened message. /// The message remains open until CryptMsgClose is called. /// /// /// /// 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 /// /// /// /// /// Currently defined dwFlags are shown in the following table. /// /// /// Value /// Meaning /// /// /// CMSG_BARE_CONTENT_FLAG /// /// The streamed output will not have an outer ContentInfo wrapper (as defined by PKCS #7). This makes it suitable to be streamed /// into an enclosing message. /// /// /// /// CMSG_DETACHED_FLAG /// There is detached data being supplied for the subsequent calls to CryptMsgUpdate. /// /// /// CMSG_AUTHENTICATED_ATTRIBUTES_FLAG /// /// Authenticated attributes are forced to be included in the SignerInfo (as defined by PKCS #7) in cases where they would not /// otherwise be required. /// /// /// /// CMSG_CONTENTS_OCTETS_FLAG /// /// Used when calculating the size of a message that has been encoded by using Distinguished Encoding Rules (DER) and that is nested /// inside an enveloped message. This is particularly useful when performing streaming. /// /// /// /// CMSG_CMS_ENCAPSULATED_CONTENT_FLAG /// /// When set, non-data type-inner content is encapsulated within an OCTET STRING. Applicable to both signed and enveloped messages. /// /// /// /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG /// /// If set, the hCryptProv that is passed to this function is released on the final CryptMsgUpdate. The handle is not released if /// the function fails. /// /// /// /// /// /// Indicates the message type. This must be one of the following values. /// /// /// Value /// Meaning /// /// /// CMSG_DATA /// This value is not used. /// /// /// CMSG_SIGNED /// The pvMsgEncodeInfo parameter is the address of a CMSG_SIGNED_ENCODE_INFO structure that contains the encoding information. /// /// /// CMSG_ENVELOPED /// The pvMsgEncodeInfo parameter is the address of a CMSG_ENVELOPED_ENCODE_INFO structure that contains the encoding information. /// /// /// CMSG_SIGNED_AND_ENVELOPED /// This value is not currently implemented. /// /// /// CMSG_HASHED /// The pvMsgEncodeInfo parameter is the address of a CMSG_HASHED_ENCODE_INFO structure that contains the encoding information. /// /// /// /// /// The address of a structure that contains the encoding information. The type of data depends on the value of the dwMsgType /// parameter. For details, see dwMsgType. /// /// /// /// If CryptMsgCalculateEncodedLength is called and the data for CryptMsgUpdate has already been message encoded, the appropriate /// object identifier (OID) is passed in pszInnerContentObjID. If pszInnerContentObjID is NULL, then the inner content type /// is assumed not to have been previously encoded and is therefore encoded as an octet string and given the type CMSG_DATA. /// /// Note When streaming is being used, pszInnerContentObjID must be either NULL or szOID_RSA_data. /// /// The following algorithm OIDs are commonly used. A user can define new inner content usage by ensuring that the sender and /// receiver of the message agree upon the semantics associated with the OID. /// /// /// /// szOID_RSA_data /// /// /// szOID_RSA_signedData /// /// /// szOID_RSA_envelopedData /// /// /// szOID_RSA_signEnvData /// /// /// szOID_RSA_digestedData /// /// /// szOID_RSA_encryptedData /// /// /// SPC_INDIRECT_DATA_OBJID /// /// /// /// /// /// When streaming is being used, this parameter is the address of a CMSG_STREAM_INFO structure. The callback function specified by /// the pfnStreamOutput member of the CMSG_STREAM_INFO structure is called when CryptMsgUpdate is executed. The /// callback is passed the encoded bytes that result from the encoding. For more information about how to use the callback, see CMSG_STREAM_INFO. /// /// /// Note When streaming is being used, the application must not release any data handles that are passed in the /// pvMsgEncodeInfo parameter, such as the provider handle in the hCryptProv member of the CMSG_SIGNER_ENCODE_INFO structure, /// until after the message handle returned by this function is closed by using the CryptMsgClose function. /// /// When streaming is not being used, this parameter is set to /// NULL /// . /// /// Streaming is not used with the CMSG_HASHED message type. When dealing with hashed data, this parameter must be set to NULL. /// /// /// Consider the case of a signed message being enclosed in an enveloped message. The encoded output from the streamed encoding of /// the signed message feeds into another streaming encoding of the enveloped message. The callback for the streaming encoding calls /// CryptMsgUpdate to encode the enveloped message. The callback for the enveloped message receives the encoded bytes of the nested /// signed message. /// /// /// /// /// If the function succeeds, it returns a handle to the opened message. This handle must be closed when it is no longer needed by /// passing it to the CryptMsgClose function. /// /// If this function fails, NULL is returned. /// To retrieve extended error information, use the GetLastError function. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_OID_FORMAT /// The OID is badly formatted. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// There is not enough memory. /// /// /// In addition, if dwMsgType is CMSG_SIGNED, errors can be propagated from CryptCreateHash. /// If dwMsgType is CMSG_ENVELOPED, errors can be propagated from CryptGenKey, CryptImportKey, and CryptExportKey. /// If dwMsgType is CMSG_HASHED, errors can be propagated from CryptCreateHash. /// /// /// /// For functions that perform encryption, the encrypted symmetric keys are reversed from little-endian format to big-endian format /// after CryptExportKey is called internally. For functions that perform decryption, the encrypted symmetric keys are reversed from /// big-endian format to little-endian format before CryptImportKey is called. /// /// CRYPT_NO_SALT is specified when symmetric keys are generated and imported with CryptGenKey and CryptImportKey. /// /// Messages encrypted with the RC2 encryption algorithm use KP_EFFECTIVE_KEYLEN with CryptGetKeyParam to determine the effective /// key length of the RC2 key importing or exporting keys. /// /// /// For messages encrypted with the RC2 encryption algorithm, encode and decode operations have been updated to handle ASN RC2 /// parameters for the ContentEncryptionAlgorithm member of the CMSG_ENVELOPED_ENCODE_INFO structure. /// /// /// For messages encrypted with the RC4, DES, and 3DES encryption algorithms, encode and decode operations now handle the ASN IV /// octet string parameter for the ContentEncryptionAlgorithm member of the CMSG_ENVELOPED_ENCODE_INFO structure. /// /// Examples /// /// For examples that use this function, see Example C Program: Signing, Encoding, Decoding, and Verifying a Message, Alternate Code /// for Encoding an Enveloped Message, Example C Program: Encoding an Enveloped, Signed Message, and Example C Program: Encoding and /// Decoding a Hashed Message. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgopentoencode HCRYPTMSG CryptMsgOpenToEncode( // DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, void const *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, // PCMSG_STREAM_INFO pStreamInfo ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b0d2610b-05ba-4fb6-8f38-10f970a52091")] public static extern SafeHCRYPTMSG CryptMsgOpenToEncode(CertEncodingType dwMsgEncodingType, CryptMsgFlags dwFlags, CryptMsgType dwMsgType, [In] IntPtr pvMsgEncodeInfo, [Optional] SafeOID pszInnerContentObjID, in CMSG_STREAM_INFO pStreamInfo); /// /// The CryptMsgOpenToEncode function opens a cryptographic message for encoding and returns a handle of the opened message. /// The message remains open until CryptMsgClose is called. /// /// /// /// 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 /// /// /// /// /// Currently defined dwFlags are shown in the following table. /// /// /// Value /// Meaning /// /// /// CMSG_BARE_CONTENT_FLAG /// /// The streamed output will not have an outer ContentInfo wrapper (as defined by PKCS #7). This makes it suitable to be streamed /// into an enclosing message. /// /// /// /// CMSG_DETACHED_FLAG /// There is detached data being supplied for the subsequent calls to CryptMsgUpdate. /// /// /// CMSG_AUTHENTICATED_ATTRIBUTES_FLAG /// /// Authenticated attributes are forced to be included in the SignerInfo (as defined by PKCS #7) in cases where they would not /// otherwise be required. /// /// /// /// CMSG_CONTENTS_OCTETS_FLAG /// /// Used when calculating the size of a message that has been encoded by using Distinguished Encoding Rules (DER) and that is nested /// inside an enveloped message. This is particularly useful when performing streaming. /// /// /// /// CMSG_CMS_ENCAPSULATED_CONTENT_FLAG /// /// When set, non-data type-inner content is encapsulated within an OCTET STRING. Applicable to both signed and enveloped messages. /// /// /// /// CMSG_CRYPT_RELEASE_CONTEXT_FLAG /// /// If set, the hCryptProv that is passed to this function is released on the final CryptMsgUpdate. The handle is not released if /// the function fails. /// /// /// /// /// /// Indicates the message type. This must be one of the following values. /// /// /// Value /// Meaning /// /// /// CMSG_DATA /// This value is not used. /// /// /// CMSG_SIGNED /// The pvMsgEncodeInfo parameter is the address of a CMSG_SIGNED_ENCODE_INFO structure that contains the encoding information. /// /// /// CMSG_ENVELOPED /// The pvMsgEncodeInfo parameter is the address of a CMSG_ENVELOPED_ENCODE_INFO structure that contains the encoding information. /// /// /// CMSG_SIGNED_AND_ENVELOPED /// This value is not currently implemented. /// /// /// CMSG_HASHED /// The pvMsgEncodeInfo parameter is the address of a CMSG_HASHED_ENCODE_INFO structure that contains the encoding information. /// /// /// /// /// The address of a structure that contains the encoding information. The type of data depends on the value of the dwMsgType /// parameter. For details, see dwMsgType. /// /// /// /// If CryptMsgCalculateEncodedLength is called and the data for CryptMsgUpdate has already been message encoded, the appropriate /// object identifier (OID) is passed in pszInnerContentObjID. If pszInnerContentObjID is NULL, then the inner content type /// is assumed not to have been previously encoded and is therefore encoded as an octet string and given the type CMSG_DATA. /// /// Note When streaming is being used, pszInnerContentObjID must be either NULL or szOID_RSA_data. /// /// The following algorithm OIDs are commonly used. A user can define new inner content usage by ensuring that the sender and /// receiver of the message agree upon the semantics associated with the OID. /// /// /// /// szOID_RSA_data /// /// /// szOID_RSA_signedData /// /// /// szOID_RSA_envelopedData /// /// /// szOID_RSA_signEnvData /// /// /// szOID_RSA_digestedData /// /// /// szOID_RSA_encryptedData /// /// /// SPC_INDIRECT_DATA_OBJID /// /// /// /// /// /// When streaming is being used, this parameter is the address of a CMSG_STREAM_INFO structure. The callback function specified by /// the pfnStreamOutput member of the CMSG_STREAM_INFO structure is called when CryptMsgUpdate is executed. The /// callback is passed the encoded bytes that result from the encoding. For more information about how to use the callback, see CMSG_STREAM_INFO. /// /// /// Note When streaming is being used, the application must not release any data handles that are passed in the /// pvMsgEncodeInfo parameter, such as the provider handle in the hCryptProv member of the CMSG_SIGNER_ENCODE_INFO structure, /// until after the message handle returned by this function is closed by using the CryptMsgClose function. /// /// When streaming is not being used, this parameter is set to /// NULL /// . /// /// Streaming is not used with the CMSG_HASHED message type. When dealing with hashed data, this parameter must be set to NULL. /// /// /// Consider the case of a signed message being enclosed in an enveloped message. The encoded output from the streamed encoding of /// the signed message feeds into another streaming encoding of the enveloped message. The callback for the streaming encoding calls /// CryptMsgUpdate to encode the enveloped message. The callback for the enveloped message receives the encoded bytes of the nested /// signed message. /// /// /// /// /// If the function succeeds, it returns a handle to the opened message. This handle must be closed when it is no longer needed by /// passing it to the CryptMsgClose function. /// /// If this function fails, NULL is returned. /// To retrieve extended error information, use the GetLastError function. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_OID_FORMAT /// The OID is badly formatted. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// There is not enough memory. /// /// /// In addition, if dwMsgType is CMSG_SIGNED, errors can be propagated from CryptCreateHash. /// If dwMsgType is CMSG_ENVELOPED, errors can be propagated from CryptGenKey, CryptImportKey, and CryptExportKey. /// If dwMsgType is CMSG_HASHED, errors can be propagated from CryptCreateHash. /// /// /// /// For functions that perform encryption, the encrypted symmetric keys are reversed from little-endian format to big-endian format /// after CryptExportKey is called internally. For functions that perform decryption, the encrypted symmetric keys are reversed from /// big-endian format to little-endian format before CryptImportKey is called. /// /// CRYPT_NO_SALT is specified when symmetric keys are generated and imported with CryptGenKey and CryptImportKey. /// /// Messages encrypted with the RC2 encryption algorithm use KP_EFFECTIVE_KEYLEN with CryptGetKeyParam to determine the effective /// key length of the RC2 key importing or exporting keys. /// /// /// For messages encrypted with the RC2 encryption algorithm, encode and decode operations have been updated to handle ASN RC2 /// parameters for the ContentEncryptionAlgorithm member of the CMSG_ENVELOPED_ENCODE_INFO structure. /// /// /// For messages encrypted with the RC4, DES, and 3DES encryption algorithms, encode and decode operations now handle the ASN IV /// octet string parameter for the ContentEncryptionAlgorithm member of the CMSG_ENVELOPED_ENCODE_INFO structure. /// /// Examples /// /// For examples that use this function, see Example C Program: Signing, Encoding, Decoding, and Verifying a Message, Alternate Code /// for Encoding an Enveloped Message, Example C Program: Encoding an Enveloped, Signed Message, and Example C Program: Encoding and /// Decoding a Hashed Message. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgopentoencode HCRYPTMSG CryptMsgOpenToEncode( // DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, void const *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, // PCMSG_STREAM_INFO pStreamInfo ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b0d2610b-05ba-4fb6-8f38-10f970a52091")] public static extern SafeHCRYPTMSG CryptMsgOpenToEncode(CertEncodingType dwMsgEncodingType, CryptMsgFlags dwFlags, CryptMsgType dwMsgType, [In] IntPtr pvMsgEncodeInfo, [Optional] SafeOID pszInnerContentObjID, IntPtr pStreamInfo = default); /// /// The CryptMsgUpdate function adds contents to a cryptographic message. The use of this function allows messages to be /// constructed piece by piece through repetitive calls of CryptMsgUpdate. The added message content is either encoded or /// decoded depending on whether the message was opened with CryptMsgOpenToEncode or CryptMsgOpenToDecode. /// /// Cryptographic message handle of the message to be updated. /// A pointer to the buffer holding the data to be encoded or decoded. /// Number of bytes of data in the pbData buffer. /// /// /// Indicates that the last block of data for encoding or decoding is being processed. Correct usage of this flag is dependent upon /// whether the message being processed has detached data. The inclusion of detached data in a message is indicated by setting /// dwFlags to CMSG_DETACHED_FLAG in the call to the function that opened the message. /// /// /// If CMSG_DETACHED_FLAG was not set and the message was opened using either CryptMsgOpenToDecode or CryptMsgOpenToEncode, fFinal /// is set to TRUE, and CryptMsgUpdate is only called once. /// /// /// If the CMSG_DETACHED_FLAG flag was set and a message is opened using CryptMsgOpenToEncode, fFinal is set to TRUE only on /// the last call to CryptMsgUpdate. /// /// /// If the CMSG_DETACHED_FLAG flag was set and a message is opened using CryptMsgOpenToDecode, fFinal is set to TRUE when the /// header is processed by a single call to CryptMsgUpdate. It is set to FALSE while processing the detached data in /// subsequent calls to CryptMsgUpdate until the last detached data block is to be processed. On the last call to /// CryptMsgUpdate, it is set to TRUE. /// /// /// When detached data is decoded, the header and the content of a message are contained in different BLOBs. Each BLOB requires that /// fFinal be set to TRUE when the last call to the function is made for that BLOB. /// /// /// /// 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. /// /// Errors encountered in the application defined callback function specified by pStreamInfo in CryptMsgOpenToDecode and /// CryptMsgOpenToEncode might be propagated to CryptMsgUpdate if streaming is used. If this happens, SetLastError is not /// called by CryptMsgUpdate after the callback function returns, which preserves any errors encountered under the control of /// the application. It is the responsibility of the callback function (or one of the APIs that it calls) to call /// SetLastError if an error occurs while the application is processing the streamed data. /// /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_INVALID_MSG_TYPE /// The message type is not valid. /// /// /// CRYPT_E_MSG_ERROR /// An error was encountered doing a cryptographic operation. /// /// /// CRYPT_E_OID_FORMAT /// The object identifier is badly formatted. /// /// /// CRYPT_E_UNEXPECTED_ENCODING /// The message is not encoded as expected. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// Ran out of memory. /// /// /// Propagated errors might be encountered from any of the following functions: /// /// /// CryptHashData /// /// /// CryptGetHashParam /// /// /// CryptSignHash /// /// /// CryptGetKeyParam /// /// /// CryptEncrypt /// /// /// CryptCreateHash /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgupdate BOOL CryptMsgUpdate( HCRYPTMSG hCryptMsg, // const BYTE *pbData, DWORD cbData, BOOL fFinal ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d27d75f0-1646-4926-b375-59e52b00326c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgUpdate(HCRYPTMSG hCryptMsg, [In] IntPtr pbData, uint cbData, [MarshalAs(UnmanagedType.Bool)] bool fFinal); /// /// The CryptMsgVerifyCountersignatureEncoded function verifies a countersignature in terms of the SignerInfo structure (as /// defined by PKCS #7). /// /// /// This parameter is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP:NULL or the handle of the cryptographic provider to use to hash the /// encryptedDigest field of pbSignerInfo.This parameter's data type is HCRYPTPROV. /// /// /// Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, pass NULL to cause the /// default RSA or DSS provider to be used. /// /// /// /// /// Specifies the encoding type used. Currently, only X509_ASN_ENCODING and PKCS_7_ASN_ENCODING are being used; however, additional /// encoding types may be added in the future. For either current encoding type, use: /// /// X509_ASN_ENCODING | PKCS_7_ASN_ENCODING. /// /// A pointer to the encoded BLOB that contains the signer of the contents of a message to be countersigned. /// Count, in bytes, of the encoded BLOB for the signer of the contents. /// A pointer to the encoded BLOB containing the countersigner information. /// Count, in bytes, of the encoded BLOB for the countersigner of the message. /// /// A pointer to a CERT_INFO that includes with the issuer and serial number of the countersigner. For more information, see Remarks. /// /// /// 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. /// The following table lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_AUTH_ATTR_MISSING /// The message does not contain an expected authenticated attribute. /// /// /// CRYPT_E_HASH_VALUE /// The hash value is not correct. /// /// /// CRYPT_E_UNEXPECTED_ENCODING /// The message is not encoded as expected. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// Ran out of memory. /// /// /// Propagated errors from the following functions might be returned. /// /// /// CryptHashData /// /// /// CryptGetHashParam /// /// /// CryptImportKey /// /// /// CryptVerifySignature /// /// /// CryptCreateHash /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// Countersigner verification is done using the PKCS #7 SIGNERINFO structure. The signature must contain the encrypted hash /// of the encryptedDigest field of pbSignerInfo. /// /// /// The issuer and serial number of the countersigner must match the countersigner information from pbSignerInfoCountersignature. /// The only fields referenced from pciCountersigner are SerialNumber, Issuer, and SubjectPublicKeyInfo. The SubjectPublicKeyInfo is /// used to access the public key that is then used to encrypt the hash from the pciCountersigner so compare it with the hash from /// the pbSignerInfo. /// /// Examples /// For an example that uses this function, see Example C Program: Encoding and Decoding a CounterSigned Message. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgverifycountersignatureencoded BOOL // CryptMsgVerifyCountersignatureEncoded( HCRYPTPROV_LEGACY hCryptProv, DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD // cbSignerInfo, PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature, PCERT_INFO pciCountersigner ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b0332360-a737-4b48-b592-0c55d493a02d")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgVerifyCountersignatureEncoded([Optional] HCRYPTPROV hCryptProv, CertEncodingType dwEncodingType, [In] IntPtr pbSignerInfo, uint cbSignerInfo, [In] IntPtr pbSignerInfoCountersignature, uint cbSignerInfoCountersignature, in CERT_INFO pciCountersigner); /// /// The CryptMsgVerifyCountersignatureEncodedEx function verifies that the pbSignerInfoCounterSignature parameter contains /// the encrypted hash of the encryptedDigest field of the pbSignerInfo parameter structure. The signer can be a /// CERT_PUBLIC_KEY_INFO structure, a certificate context, or a chain context. /// /// /// This parameter is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP:NULL or the handle of the cryptographic provider to use to hash the /// encryptedDigest field of pbSignerInfo.This parameter's data type is HCRYPTPROV. /// /// /// Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, pass NULL to cause the /// default RSA or DSS provider to be used. /// /// /// /// /// The encoding type used. Currently, only X509_ASN_ENCODING and PKCS_7_ASN_ENCODING are being used; however, additional encoding /// types may be added in the future. For either current encoding type, use: /// /// X509_ASN_ENCODING | PKCS_7_ASN_ENCODING. /// /// A pointer to the encoded BLOB that contains the signer of the contents of a message to be countersigned. /// The count, in bytes, of the encoded BLOB for the signer of the contents. /// A pointer to the encoded BLOB containing the countersigner information. /// The count, in bytes, of the encoded BLOB for the countersigner of the message. /// /// /// The structure that contains the signer information. The following table shows the predefined values and the structures indicated. /// /// /// /// Value /// Meaning /// /// /// CMSG_VERIFY_SIGNER_PUBKEY /// pvSigner is a pointer to a CERT_PUBLIC_KEY_INFO structure. /// /// /// CMSG_VERIFY_SIGNER_CERT /// pvSigner is a pointer to a CERT_CONTEXT structure. /// /// /// CMSG_VERIFY_SIGNER_CHAIN /// pvSigner is a pointer to a CERT_CHAIN_CONTEXT structure. /// /// /// /// /// A pointer to a CERT_PUBLIC_KEY_INFO structure, a certificate context, or a chain context depending on the value of dwSignerType. /// /// /// Flags that modify the function behavior. This can be zero or the following value. /// /// /// Value /// Meaning /// /// /// CMSG_VERIFY_COUNTER_SIGN_ENABLE_STRONG_FLAG 0x00000001 /// /// Performs a strong signature check after successful signature verification. Set the pvExtra parameter to point to a /// CERT_STRONG_SIGN_PARA structure that contains the parameters needed to check the signature strength.. Windows 8 and Windows /// Server 2012: Support for this flag begins. /// /// /// /// /// /// If you set the dwFlags parameter to CMSG_VERIFY_COUNTER_SIGN_ENABLE_STRONG_FLAG, set this parameter (pvExtra) to point to /// a CERT_STRONG_SIGN_PARA structure that contains the parameters used to check the signature strength. /// /// /// 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. /// The following error codes are most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_AUTH_ATTR_MISSING /// The message does not contain an expected authenticated attribute. /// /// /// CRYPT_E_HASH_VALUE /// The hash value is not correct. /// /// /// CRYPT_E_UNEXPECTED_ENCODING /// The message is not encoded as expected. /// /// /// CRYPT_E_UNKNOWN_ALGO /// The cryptographic algorithm is unknown. /// /// /// E_INVALIDARG /// One or more arguments are not valid. /// /// /// E_OUTOFMEMORY /// Ran out of memory. /// /// /// Propagated errors from the following functions might be returned. /// /// /// CryptHashData /// /// /// CryptGetHashParam /// /// /// CryptImportKey /// /// /// CryptVerifySignature /// /// /// CryptCreateHash /// /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// Countersigner verification is done using the PKCS #7 SIGNERINFO structure. The signature must contain the encrypted hash /// of the encryptedDigest field of pbSignerInfo. /// /// /// The issuer and serial number of the countersigner must match the countersigner information from pbSignerInfoCountersignature. /// The only fields referenced from pciCountersigner are SerialNumber, Issuer, and SubjectPublicKeyInfo. The SubjectPublicKeyInfo is /// used to access the public key that is then used to encrypt the hash from the pciCountersigner so compare it with the hash from /// the pbSignerInfo. /// /// Examples /// For an example that uses this function, see Example C Program: Encoding and Decoding a CounterSigned Message. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptmsgverifycountersignatureencodedex BOOL // CryptMsgVerifyCountersignatureEncodedEx( HCRYPTPROV_LEGACY hCryptProv, DWORD dwEncodingType, PBYTE pbSignerInfo, DWORD // cbSignerInfo, PBYTE pbSignerInfoCountersignature, DWORD cbSignerInfoCountersignature, DWORD dwSignerType, void *pvSigner, DWORD // dwFlags, void *pvExtra ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "da756cd5-1dec-4d88-9c90-76dd263035eb")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptMsgVerifyCountersignatureEncodedEx([Optional] HCRYPTPROV hCryptProv, CertEncodingType dwEncodingType, [In] IntPtr pbSignerInfo, uint cbSignerInfo, [In] IntPtr pbSignerInfoCountersignature, uint cbSignerInfoCountersignature, CryptMsgSignerType dwSignerType, IntPtr pvSigner, CryptMsgVerifyCounterFlags dwFlags, [Optional] IntPtr pvExtra); /// /// The CryptSignAndEncryptMessage function creates a hash of the specified content, signs the hash, encrypts the content, /// hashes the encrypted contents and the signed hash, and then encodes both the encrypted content and the signed hash. The result /// is the same as if the hash were first signed and then encrypted. /// /// A pointer to a CRYPT_SIGN_MESSAGE_PARA structure that contains the signature parameters. /// A pointer to a CRYPT_ENCRYPT_MESSAGE_PARA structure containing encryption parameters. /// Number of array elements in rgpRecipientCert. /// /// Array of pointers to CERT_CONTEXT structures. Each structure is the certificate of an intended recipients of the message. /// /// A pointer to a buffer containing the content to be signed and encrypted. /// The size, in bytes, of the pbToBeSignedAndEncrypted buffer. /// /// A pointer to a buffer to receive the encrypted and encoded message. /// /// This parameter can be NULL to set the size of this information for memory allocation purposes. For more information, see /// Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to DWORD specifying the size, in bytes, of the buffer pointed to by pbSignedAndEncryptedBlob. When the function /// returns, this variable contains the size, in bytes, of the signed and encrypted message copied to *pbSignedAndEncryptedBlob. /// /// /// Note When processing the data returned, applications must 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 will fit 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 return value is nonzero (TRUE). /// If the function fails, the return value is zero (FALSE). /// For extended error information, call GetLastError. /// The following lists the error code most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbSignedAndEncryptedBlob parameter is not large enough to hold the returned data, the function /// sets the ERROR_MORE_DATA code, and stores the required buffer size, in bytes, into the variable pointed to by pcbSignedAndEncryptedBlob. /// /// /// /// Note Errors from the called functions CryptSignMessage and CryptEncryptMessage might be propagated to this function. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptsignandencryptmessage BOOL // CryptSignAndEncryptMessage( PCRYPT_SIGN_MESSAGE_PARA pSignPara, PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, DWORD cRecipientCert, // PCCERT_CONTEXT [] rgpRecipientCert, const BYTE *pbToBeSignedAndEncrypted, DWORD cbToBeSignedAndEncrypted, BYTE // *pbSignedAndEncryptedBlob, DWORD *pcbSignedAndEncryptedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "0ab234f2-a681-463f-8ba8-b23b05cf2626")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptSignAndEncryptMessage(in CRYPT_SIGN_MESSAGE_PARA pSignPara, in CRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, uint cRecipientCert, [In, MarshalAs(UnmanagedType.LPArray)] PCCERT_CONTEXT[] rgpRecipientCert, [In] IntPtr pbToBeSignedAndEncrypted, uint cbToBeSignedAndEncrypted, [Out] IntPtr pbSignedAndEncryptedBlob, ref uint pcbSignedAndEncryptedBlob); /// /// The CryptSignMessage function creates a hash of the specified content, signs the hash, and then encodes both the original /// message content and the signed hash. /// /// A pointer to CRYPT_SIGN_MESSAGE_PARA structure containing the signature parameters. /// /// TRUE if this is to be a detached signature. Otherwise, FALSE. If this parameter is set to TRUE, only the /// signed hash is encoded in pbSignedBlob. Otherwise, both rgpbToBeSigned and the signed hash are encoded. /// /// /// Count of the number of array elements in rgpbToBeSigned and rgpbToBeSigned. This parameter must be set to one unless /// fDetachedSignature is set to TRUE. /// /// Array of pointers to buffers that contain the contents to be signed. /// Array of sizes, in bytes, of the content buffers pointed to in rgpbToBeSigned. /// /// /// A pointer to a buffer to receive the encoded signed hash, if fDetachedSignature is TRUE, or to both the encoded content /// and signed hash if fDetachedSignature is FALSE. /// /// /// This parameter can be NULL to set the size of this information for memory allocation purposes. For more information, see /// Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD specifying the size, in bytes, of the pbSignedBlob buffer. When the function returns, this variable /// contains the size, in bytes, of the signed and encoded message. /// /// /// Note When processing the data returned, applications must 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 will fit 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 return value is nonzero ( TRUE). /// If the function fails, the return value is zero ( FALSE). /// For extended error information, call GetLastError. /// The following lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbSignedBlob parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, into the variable pointed to by pcbSignedBlob. /// /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pSignPara is not valid. /// /// /// /// CRYPT_E_NO_KEY_PROPERTY /// The pSigningCert in *pSignPara does not have a CERT_KEY_PROV_INFO_PROP_ID or CERT_KEY_CONTEXT_PROP_ID property. /// /// /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, and CryptSignHash might be propagated to this function. /// /// /// If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For information /// about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptsignmessage BOOL CryptSignMessage( // PCRYPT_SIGN_MESSAGE_PARA pSignPara, BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE * [] rgpbToBeSigned, DWORD [] // rgcbToBeSigned, BYTE *pbSignedBlob, DWORD *pcbSignedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "f14f7c7b-14ac-40a7-9a49-d1a899ecc52a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptSignMessage(in CRYPT_SIGN_MESSAGE_PARA pSignPara, [MarshalAs(UnmanagedType.Bool)] bool fDetachedSignature, uint cToBeSigned, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] rgpbToBeSigned, [In] uint[] rgcbToBeSigned, [Out] IntPtr pbSignedBlob, ref uint pcbSignedBlob); /// /// The CryptSignMessageWithKey function signs a message by using a CSP's private key specified in the parameters. A /// placeholder SignerId is created and stored in the message. /// /// A pointer to a CRYPT_KEY_SIGN_MESSAGE_PARA structure that contains the signature parameters. /// A pointer to a buffer array that contains the message to be signed. /// The number of array elements in the pbToBeSigned buffer array. /// /// A pointer to a buffer to receive the encoded signed message. /// /// This parameter can be NULL to set the size of this information for memory allocation purposes. For more information, see /// Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD value that indicates the size, in bytes, of the pbSignedBlob buffer. When the function returns, this /// variable contains the size, in bytes, of the signed and encoded message. /// /// /// Note When processing the data returned, applications must 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 will fit 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 return value is nonzero (TRUE). /// If the function fails, the return value is zero (FALSE). /// For extended error information, call GetLastError. /// The following lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbSignedBlob parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code and stores the required buffer size, in bytes, into the variable pointed to by pcbSignedBlob. /// /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pSignPara is not valid. /// /// /// /// CRYPT_E_NO_KEY_PROPERTY /// The pSigningCert in *pSignPara does not have a CERT_KEY_PROV_INFO_PROP_ID or CERT_KEY_CONTEXT_PROP_ID property. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptsignmessagewithkey BOOL CryptSignMessageWithKey( // PCRYPT_KEY_SIGN_MESSAGE_PARA pSignPara, const BYTE *pbToBeSigned, DWORD cbToBeSigned, BYTE *pbSignedBlob, DWORD *pcbSignedBlob ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d31024bf-7022-440b-8134-a02578510357")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptSignMessageWithKey(in CRYPT_KEY_SIGN_MESSAGE_PARA pSignPara, [In] IntPtr pbToBeSigned, uint cbToBeSigned, [Out] IntPtr pbSignedBlob, ref uint pcbSignedBlob); /// The CryptVerifyDetachedMessageHash function verifies a detached hash. /// A pointer to a CRYPT_HASH_MESSAGE_PARA structure containing the hash parameters. /// A pointer to the encoded, detached hash. /// The size, in bytes, of the detached hash. /// Number of elements in the rgpbToBeHashed and rgcbToBeHashed arrays. /// Array of pointers to content buffers to be hashed. /// /// Array of sizes, in bytes, for the content buffers pointed to by the elements of the rgcbToBeHashed array. /// /// /// A pointer to a buffer to receive the computed hash. /// /// This parameter can be NULL if the newly created hash is not needed for additional processing, or to set the size of the /// hash for memory allocation purposes. For more information, see Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD specifying the size, in bytes, of the pbComputedHash buffer. When the function returns, this /// DWORD contains the size, in bytes, of the created hash. The hash will not be returned if this parameter is NULL. /// /// /// Note When processing the data returned , applications must 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 will fit 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 return value is nonzero (TRUE). /// If the function fails, the return value is zero (FALSE). /// For extended error information, call GetLastError. /// The following lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a hashed cryptographic message. /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pHashPara is not valid. /// /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbComputedHash parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, into the variable pointed to by pcbComputedHash. /// /// /// /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, and CryptGetHashParam might be propagated to this /// function. If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For /// information about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifydetachedmessagehash BOOL // CryptVerifyDetachedMessageHash( PCRYPT_HASH_MESSAGE_PARA pHashPara, BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD // cToBeHashed, const BYTE * [] rgpbToBeHashed, DWORD [] rgcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "b529b9e2-9798-4548-a44f-c330524a3e6b")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyDetachedMessageHash(in CRYPT_HASH_MESSAGE_PARA pHashPara, [In] IntPtr pbDetachedHashBlob, uint cbDetachedHashBlob, uint cToBeHashed, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] rgpbToBeHashed, [In] uint[] rgcbToBeHashed, [Out] IntPtr pbComputedHash, ref uint pcbComputedHash); /// /// The CryptVerifyDetachedMessageSignature function verifies a signed message containing a detached signature or signatures. /// /// A pointer to a CRYPT_VERIFY_MESSAGE_PARA structure containing the verification parameters. /// /// Index of the signature to be verified. A message might have several signers and this function can be called repeatedly, changing /// dwSignerIndex to verify other signatures. If the function returns FALSE, and GetLastError returns CRYPT_E_NO_SIGNER, the /// previous call received the last signer of the message. /// /// A pointer to a BLOB containing the encoded message signatures. /// The size, in bytes, of the detached signature. /// Number of array elements in rgpbToBeSigned and rgcbToBeSigned. /// Array of pointers to buffers containing the contents to be hashed. /// Array of sizes, in bytes, for the content buffers pointed to in rgpbToBeSigned. /// /// A pointer to a pointer to a CERT_CONTEXT structure of a signer certificate. When you have finished using the certificate /// context, free it by calling the CertFreeCertificateContext function. A pointer to a CERT_CONTEXT structure will not be /// returned if this parameter is NULL. /// /// /// 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. /// The following lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pVerifyPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a signed cryptographic message. /// /// /// CRYPT_E_NO_SIGNER /// The message does not have any signers or a signer for the specified dwSignerIndex. /// /// /// NTE_BAD_ALGID /// The message was hashed and signed by using an unknown or unsupported algorithm. /// /// /// NTE_BAD_SIGNATURE /// The message's signature was not verified. /// /// /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, CryptVerifySignature, and CryptImportKey might be /// propagated to this function.If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) /// encoding/decoding error. For information about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifydetachedmessagesignature BOOL // CryptVerifyDetachedMessageSignature( PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex, const BYTE *pbDetachedSignBlob, // DWORD cbDetachedSignBlob, DWORD cToBeSigned, const BYTE * [] rgpbToBeSigned, DWORD [] rgcbToBeSigned, PCCERT_CONTEXT // *ppSignerCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "d437f6bf-eb56-4d29-bb91-eb8487e50219")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyDetachedMessageSignature(in CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, uint dwSignerIndex, [In] IntPtr pbDetachedSignBlob, uint cbDetachedSignBlob, uint cToBeSigned, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] rgpbToBeSigned, [In] uint[] rgcbToBeSigned, out SafePCCERT_CONTEXT ppSignerCert); /// The CryptVerifyMessageHash function verifies the hash of specified content. /// A pointer to a CRYPT_HASH_MESSAGE_PARA structure containing hash parameters. /// A pointer to a buffer containing original content and its hash. /// The size, in bytes, of the original hash buffer. /// /// A pointer to a buffer to receive the original content that was hashed. /// /// This parameter can be NULL if the original content is not needed for additional processing, or to set the size of the /// original content for memory allocation purposes. For more information, see Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD specifying the size, in bytes, of the pbToBeHashed buffer. When the function returns, this variable /// contains the size, in bytes, of the original content copied to pbToBeHashed. The original content will not be returned if this /// parameter is NULL. /// /// /// Note When processing the data returned, applications must 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 will fit 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 a buffer to receive the computed hash. This parameter can be NULL if the created hash is not needed for /// additional processing, or to set the size of the original content for memory allocation purposes. For more information, see /// Retrieving Data of Unknown Length. /// /// /// /// A pointer to a DWORD specifying the size, in bytes, of the pbComputedHash buffer. When the function returns, this /// variable contains the size, in bytes, of the created hash. The hash is not returned if this parameter is NULL. /// /// /// Note When processing the data returned, applications must 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 will fit 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 return value is nonzero (TRUE). /// If the function fails, the return value is zero (FALSE). /// For extended error information, call GetLastError. /// The following lists the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a hashed cryptographic message. /// /// /// E_INVALIDARG /// /// The message encoding type is not valid. Currently only PKCS_7_ASN_ENCODING is supported. The cbSize in *pHashPara is not valid. /// /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbToBeHashed parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, into the variable pointed to by pcbToBeHashed. /// /// /// /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, and CryptGetHashParam might be propagated to this /// function. If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) encoding/decoding error. For /// information about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifymessagehash BOOL CryptVerifyMessageHash( // PCRYPT_HASH_MESSAGE_PARA pHashPara, BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed, DWORD *pcbToBeHashed, BYTE // *pbComputedHash, DWORD *pcbComputedHash ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "3b5185b9-e24b-4302-a60c-74ccbd19077c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyMessageHash(in CRYPT_HASH_MESSAGE_PARA pHashPara, [In] IntPtr pbHashedBlob, uint cbHashedBlob, [Out] IntPtr pbToBeHashed, ref uint pcbToBeHashed, [Out] IntPtr pbComputedHash, ref uint pcbComputedHash); /// /// The CryptVerifyMessageSignature function verifies a signed message's signature. /// /// This function should not be used to verify the signature of a detached message. You should use the /// CryptVerifyDetachedMessageSignature function to verify the signature of a detached message. /// /// /// A pointer to a CRYPT_VERIFY_MESSAGE_PARA structure that contains verification parameters. /// /// The index of the desired signature. There can be more than one signature. CryptVerifyMessageSignature can be called /// repeatedly, incrementing dwSignerIndex each time. Set this parameter to zero for the first signer, or if there is only one /// signer. If the function returns FALSE, and GetLastError returns CRYPT_E_NO_SIGNER, the previous call processed the last /// signer of the message. /// /// A pointer to a buffer that contains the signed message. /// The size, in bytes, of the signed message buffer. /// /// A pointer to a buffer to receive the decoded message. /// /// This parameter can be NULL if the decoded message is not needed for additional processing or to set the size of the /// message for memory allocation purposes. For more information, see Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD value that specifies the size, in bytes, of the pbDecoded buffer. When the function returns, this /// DWORD contains the size, in bytes, of the decoded message. The decoded message will not be returned if this parameter is NULL. /// /// /// Note When processing the data returned, applications must 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 will fit 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. /// /// /// /// The address of a CERT_CONTEXT structure pointer that receives the certificate of the signer. When you have finished using this /// structure, free it by passing this pointer to the CertFreeCertificateContext function. This parameter can be NULL if the /// signer's certificate is not needed. /// /// /// /// If the function succeeds, the function returns nonzero. This does not necessarily mean that the signature was verified. In the /// case of a detached message, the variable pointed to by pcbDecoded will contain zero. In this case, this function will return /// nonzero, but the signature is not verified. To verify the signature of a detached message, use the /// CryptVerifyDetachedMessageSignature function. /// /// If the function fails, it returns zero. For extended error information, call GetLastError. /// The following table shows the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecoded parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecoded. /// /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pVerifyPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a signed cryptographic message. /// /// /// CRYPT_E_NO_SIGNER /// The message does not have any signers or a signer for the specified dwSignerIndex. /// /// /// NTE_BAD_ALGID /// The message was hashed and signed by using an unknown or unsupported algorithm. /// /// /// NTE_BAD_SIGNATURE /// The message's signature was not verified. /// /// /// /// Note Errors from the called functions CryptCreateHash, CryptHashData, CryptVerifySignature, and CryptImportKey can be /// propagated to this function. If the function fails, GetLastError may return an Abstract Syntax Notation One (ASN.1) /// encoding/decoding error. For information about these errors, see ASN.1 Encoding/Decoding Return Values. /// /// /// /// /// For a verified signer and message, ppSignerCert is updated with the CERT_CONTEXT of the signer. It must be freed by calling /// CertFreeCertificateContext. Otherwise, ppSignerCert is set to NULL. /// /// For a message that contains only certificates and CRLs, pcbDecoded is set to NULL. /// Examples /// For an example that uses this function, see Example C Program: Signing a Message and Verifying a Message Signature. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifymessagesignature BOOL // CryptVerifyMessageSignature( PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex, const BYTE *pbSignedBlob, DWORD // cbSignedBlob, BYTE *pbDecoded, DWORD *pcbDecoded, PCCERT_CONTEXT *ppSignerCert ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "03411e7a-b097-4059-a198-3d412ae40e38")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyMessageSignature(in CRYPT_VERIFY_MESSAGE_PARA pVerifyPara, uint dwSignerIndex, [In] IntPtr pbSignedBlob, uint cbSignedBlob, [Out] IntPtr pbDecoded, ref uint pcbDecoded, out SafePCCERT_CONTEXT ppSignerCert); /// /// The CryptVerifyMessageSignatureWithKey function verifies a signed message's signature by using specified public key information. /// /// A pointer to a CRYPT_KEY_VERIFY_MESSAGE_PARA structure that contains verification parameters. /// /// A pointer to a CERT_PUBLIC_KEY_INFO structure that contains the public key that is used to verify the signed message. If /// NULL, the signature is not verified. /// /// A pointer to a buffer that contains the signed message. /// The size, in bytes, of the signed message buffer. /// /// A pointer to a buffer to receive the decoded message. /// /// This parameter can be NULL if the decoded message is not needed for additional processing or to set the size of the /// message for memory allocation purposes. For more information, see Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD value that specifies the size, in bytes, of the pbDecoded buffer. When the function returns, this /// DWORD contains the size, in bytes, of the decoded message. The decoded message will not be returned if this parameter is NULL. /// /// /// Note When processing the data returned, applications must 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 will fit 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. /// If the function fails, it returns zero. For extended error information, call GetLastError. /// The following table shows the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecoded parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecoded. /// /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pVerifyPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a signed cryptographic message. /// /// /// CRYPT_E_NO_SIGNER /// The message does not have any signers or a signer for the specified dwSignerIndex. /// /// /// NTE_BAD_ALGID /// The message was hashed and signed by using an unknown or unsupported algorithm. /// /// /// NTE_BAD_SIGNATURE /// The message's signature was not verified. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifymessagesignaturewithkey BOOL // CryptVerifyMessageSignatureWithKey( PCRYPT_KEY_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, const BYTE // *pbSignedBlob, DWORD cbSignedBlob, BYTE *pbDecoded, DWORD *pcbDecoded ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "6fe0f9ee-1838-4eb7-8254-05b878eb8f56")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyMessageSignatureWithKey(in CRYPT_KEY_VERIFY_MESSAGE_PARA pVerifyPara, in CERT_PUBLIC_KEY_INFO pPublicKeyInfo, [In] IntPtr pbSignedBlob, uint cbSignedBlob, [Out] IntPtr pbDecoded, ref uint pcbDecoded); /// /// The CryptVerifyMessageSignatureWithKey function verifies a signed message's signature by using specified public key information. /// /// A pointer to a CRYPT_KEY_VERIFY_MESSAGE_PARA structure that contains verification parameters. /// /// A pointer to a CERT_PUBLIC_KEY_INFO structure that contains the public key that is used to verify the signed message. If /// NULL, the signature is not verified. /// /// A pointer to a buffer that contains the signed message. /// The size, in bytes, of the signed message buffer. /// /// A pointer to a buffer to receive the decoded message. /// /// This parameter can be NULL if the decoded message is not needed for additional processing or to set the size of the /// message for memory allocation purposes. For more information, see Retrieving Data of Unknown Length. /// /// /// /// /// A pointer to a DWORD value that specifies the size, in bytes, of the pbDecoded buffer. When the function returns, this /// DWORD contains the size, in bytes, of the decoded message. The decoded message will not be returned if this parameter is NULL. /// /// /// Note When processing the data returned, applications must 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 will fit 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. /// If the function fails, it returns zero. For extended error information, call GetLastError. /// The following table shows the error codes most commonly returned by the GetLastError function. /// /// /// Return code /// Description /// /// /// ERROR_MORE_DATA /// /// If the buffer specified by the pbDecoded parameter is not large enough to hold the returned data, the function sets the /// ERROR_MORE_DATA code, and stores the required buffer size, in bytes, in the variable pointed to by pcbDecoded. /// /// /// /// E_INVALIDARG /// /// Invalid message and certificate encoding types. Currently only PKCS_7_ASN_ENCODING and X509_ASN_ENCODING_TYPE are supported. /// Invalid cbSize in *pVerifyPara. /// /// /// /// CRYPT_E_UNEXPECTED_MSG_TYPE /// Not a signed cryptographic message. /// /// /// CRYPT_E_NO_SIGNER /// The message does not have any signers or a signer for the specified dwSignerIndex. /// /// /// NTE_BAD_ALGID /// The message was hashed and signed by using an unknown or unsupported algorithm. /// /// /// NTE_BAD_SIGNATURE /// The message's signature was not verified. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptverifymessagesignaturewithkey BOOL // CryptVerifyMessageSignatureWithKey( PCRYPT_KEY_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, const BYTE // *pbSignedBlob, DWORD cbSignedBlob, BYTE *pbDecoded, DWORD *pcbDecoded ); [DllImport(Lib.Crypt32, SetLastError = true, ExactSpelling = true)] [PInvokeData("wincrypt.h", MSDNShortId = "6fe0f9ee-1838-4eb7-8254-05b878eb8f56")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CryptVerifyMessageSignatureWithKey(in CRYPT_KEY_VERIFY_MESSAGE_PARA pVerifyPara, [In, Optional] IntPtr pPublicKeyInfo, [In] IntPtr pbSignedBlob, uint cbSignedBlob, [Out] IntPtr pbDecoded, ref uint pcbDecoded); /// /// The CMSG_CMS_SIGNER_INFO structure contains the content of the defined SignerInfo in signed or signed and enveloped /// messages. In decoding a received message, CryptMsgGetParam is called for each signer to get a CMSG_CMS_SIGNER_INFO structure. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_cms_signer_info typedef struct _CMSG_CMS_SIGNER_INFO // { DWORD dwVersion; CERT_ID SignerId; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; CRYPT_ALGORITHM_IDENTIFIER // HashEncryptionAlgorithm; CRYPT_DATA_BLOB EncryptedHash; CRYPT_ATTRIBUTES AuthAttrs; CRYPT_ATTRIBUTES UnauthAttrs; } // CMSG_CMS_SIGNER_INFO, *PCMSG_CMS_SIGNER_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "177323ef-4e26-4681-a474-1a99fb6900af")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CMS_SIGNER_INFO { /// The version of this structure. public uint dwVersion; /// A CERT_ID structure that identifies the signer's certificate. public CERT_ID SignerId; /// A CRYPT_ALGORITHM_IDENTIFIER structure that specifies the algorithm used in generating the hash of a message. public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// A CRYPT_ALGORITHM_IDENTIFIER structure that specifies the algorithm used to encrypt the hash. public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; /// A CRYPT_DATA_BLOB structure that contains the encrypted hash of the message, the signature. public CRYPTOAPI_BLOB EncryptedHash; /// A CRYPT_ATTRIBUTES structure that contains authenticated attributes of the signer. public CRYPT_ATTRIBUTES AuthAttrs; /// A CRYPT_ATTRIBUTES structure that contains unauthenticated attributes of the signer. public CRYPT_ATTRIBUTES UnauthAttrs; } /// /// The CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA structure is used to add an unauthenticated attribute to a signer of a signed /// message. This structure is passed to CryptMsgControl if the dwCtrlType parameter is set to CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_add_signer_unauth_attr_para typedef struct // _CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA { DWORD cbSize; DWORD dwSignerIndex; CRYPT_DATA_BLOB blob; } // CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA, *PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "5e347a50-942e-4278-a9ae-ad4c30c55c6b")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// Index of the signer in the rgSigners array of pointers of CMSG_SIGNER_ENCODE_INFO structures in a signed message's /// CMSG_SIGNED_ENCODE_INFO structure. The unauthenticated attribute is to be added to this signer's information. /// public uint dwSignerIndex; /// public CRYPTOAPI_BLOB blob; } /// /// /// The CMSG_CTRL_DECRYPT_PARA structure contains information used to decrypt an enveloped message for a key transport /// recipient. This structure is passed to CryptMsgControl if the dwCtrlType parameter is CMSG_CTRL_DECRYPT. /// /// /// For information about how CryptoAPI supports Secure/Multipurpose Internet Mail Extensions (S/MIME) email interoperability, see /// the Remarks section of CryptMsgOpenToEncode. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_decrypt_para typedef struct // _CMSG_CTRL_DECRYPT_PARA { DWORD cbSize; union { HCRYPTPROV hCryptProv; NCRYPT_KEY_HANDLE hNCryptKey; } DUMMYUNIONNAME; DWORD // dwKeySpec; DWORD dwRecipientIndex; } CMSG_CTRL_DECRYPT_PARA, *PCMSG_CTRL_DECRYPT_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "eb9b1daa-b04f-419a-88e3-7c772f9e62eb")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_DECRYPT_PARA { /// The size, in bytes, of this structure. public uint cbSize; /// public CMSG_CTRL_DECRYPT_PARA_HANDLES Handle; /// [StructLayout(LayoutKind.Explicit)] public struct CMSG_CTRL_DECRYPT_PARA_HANDLES { /// /// Cryptographic service provider (CSP) handle. The CNG function NCryptIsKeyHandle is called to determine the union choice. /// [FieldOffset(0)] public HCRYPTPROV hCryptProv; /// /// A handle to the CNG Cryptographic service provider (CSP). The CNG function, NCryptIsKeyHandle, is called to determine /// the union choice. New encrypt algorithms are only supported in CNG functions. The CNG function, NCryptTranslateHandle, /// will be called to convert the CryptoAPI hCryptProv choice where necessary. We recommend that applications pass, to the /// hNCryptKey member, the CNG CSP handle that is returned from the NCryptOpenKey function. /// [FieldOffset(0)] public NCrypt.NCRYPT_KEY_HANDLE hNCryptKey; } /// /// The private key to be used. This member is not used when the hNCryptKey member is used. /// The following dwKeySpec values are defined for the default provider. /// /// /// Value /// Meaning /// /// /// AT_KEYEXCHANGE /// Keys used to encrypt and decrypt session keys. /// /// /// AT_SIGNATURE /// Keys used to create and verify digital signatures. /// /// /// If dwKeySpec is zero, the default AT_KEYEXCHANGE is used. /// public CertKeySpec dwKeySpec; /// Index of the recipient in the message associated with the hCryptProv private key. public uint dwRecipientIndex; } /// /// The CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA structure is used to delete an unauthenticated attribute of a signer of a /// signed message. This structure is passed to CryptMsgControl if the dwCrlType parameter is CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_del_signer_unauth_attr_para typedef struct // _CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA { DWORD cbSize; DWORD dwSignerIndex; DWORD dwUnauthAttrIndex; } // CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA, *PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "729fbbe0-40c6-41e7-851f-6f93f47e8f4d")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// Index of the signer in the rgSigners array of pointers to CMSG_SIGNER_ENCODE_INFO structures in a signed message's /// CMSG_SIGNED_ENCODE_INFO structure. The unauthenticated attribute for this signer is deleted. /// public uint dwSignerIndex; /// /// Index of the element in the rgUnauthAttr array of the CMSG_SIGNER_ENCODE_INFO structure holding the unauthenticated /// attribute to be removed. /// public uint dwUnauthAttrIndex; } /// The CMSG_CTRL_KEY_AGREE_DECRYPT_PARA structure contains information about a key agreement recipient. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_key_agree_decrypt_para typedef struct // _CMSG_CTRL_KEY_AGREE_DECRYPT_PARA { DWORD cbSize; union { HCRYPTPROV hCryptProv; NCRYPT_KEY_HANDLE hNCryptKey; } DUMMYUNIONNAME; // DWORD dwKeySpec; PCMSG_KEY_AGREE_RECIPIENT_INFO pKeyAgree; DWORD dwRecipientIndex; DWORD dwRecipientEncryptedKeyIndex; // CRYPT_BIT_BLOB OriginatorPublicKey; } CMSG_CTRL_KEY_AGREE_DECRYPT_PARA, *PCMSG_CTRL_KEY_AGREE_DECRYPT_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "14e58281-4315-4ece-8ea8-92765cffd212")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_KEY_AGREE_DECRYPT_PARA { /// The size, in bytes, of this data structure. public uint cbSize; /// public CMSG_CTRL_KEY_AGREE_DECRYPT_PARA_HANDLES Handle; /// [StructLayout(LayoutKind.Explicit)] public struct CMSG_CTRL_KEY_AGREE_DECRYPT_PARA_HANDLES { /// /// A handle to the cryptographic service provider (CSP) used to do the recipient key encryption and export. If NULL, /// the provider specified in CMSG_ENVELOPED_ENCODE_INFO is used. The CNG function NCryptIsKeyHandle is called to determine /// the union choice. /// [FieldOffset(0)] public HCRYPTPROV hCryptProv; /// /// A handle to the CNG CSP used to do the recipient key encryption and export. The CNG function NCryptIsKeyHandle is called /// to determine the union choice. New encrypt algorithms are only supported in CNG functions. The CNG function /// NCryptTranslateHandle will be called to convert the CryptoAPI CSP hCryptProv choice where necessary. We recommend that /// applications pass, to the hNCryptKey member, the CNG CSP handle that is returned from the NCryptOpenKey function. /// [FieldOffset(0)] public NCrypt.NCRYPT_KEY_HANDLE hNCryptKey; } /// /// Specifies the encrypted key. The encrypted key is the result of encrypting the content-encryption key. This member is not /// used when the hNCryptKey member is used. /// public CertKeySpec dwKeySpec; /// A pointer to a CMSG_KEY_AGREE_RECIPIENT_INFO structure. public IntPtr pKeyAgree; /// Indicates a specific recipient in an array of recipients. public uint dwRecipientIndex; /// Indicates a specific encrypted key in an array of encrypted keys. public uint dwRecipientEncryptedKeyIndex; /// A CRYPT_BIT_BLOB structure that contains the sender's public key information. public CRYPTOAPI_BLOB OriginatorPublicKey; } /// The CMSG_CTRL_KEY_TRANS_DECRYPT_PARA structure contains information about a key transport message recipient. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_key_trans_decrypt_para typedef struct // _CMSG_CTRL_KEY_TRANS_DECRYPT_PARA { DWORD cbSize; union { HCRYPTPROV hCryptProv; NCRYPT_KEY_HANDLE hNCryptKey; } DUMMYUNIONNAME; // DWORD dwKeySpec; PCMSG_KEY_TRANS_RECIPIENT_INFO pKeyTrans; DWORD dwRecipientIndex; } CMSG_CTRL_KEY_TRANS_DECRYPT_PARA, *PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "5f3387c9-4ff0-42a0-8fc7-67d3bb8b6bef")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_KEY_TRANS_DECRYPT_PARA { /// The size, in bytes, of this data structure. public uint cbSize; /// public CMSG_CTRL_KEY_TRANS_DECRYPT_PARA_HANDLES Handle; /// [StructLayout(LayoutKind.Explicit)] public struct CMSG_CTRL_KEY_TRANS_DECRYPT_PARA_HANDLES { /// /// A handle to the cryptographic service provider (CSP) used to do the recipient key encryption and export. If NULL, /// the provider specified in CMSG_ENVELOPED_ENCODE_INFO is used. The CNG function NCryptIsKeyHandle is called to determine /// the union choice. /// [FieldOffset(0)] public HCRYPTPROV hCryptProv; /// /// A handle to the CNG CSP used to do the recipient key encryption and export. The CNG function NCryptIsKeyHandle is called /// to determine the union choice. New encrypt algorithms are only supported in CNG functions. The CNG function /// NCryptTranslateHandle will be called to convert the CryptoAPI CSP hCryptProv choice where necessary. We recommend that /// applications pass, to the hNCryptKey member, the CNG CSP handle that is returned from the NCryptOpenKey function. /// [FieldOffset(0)] public NCrypt.NCRYPT_KEY_HANDLE hNCryptKey; } /// /// Specifies the encrypted key. The encrypted key is the result of encrypting the content-encryption key for a specific /// recipient by using that recipient's public key. This member is not used when the hNCryptKey member is used. /// public uint dwKeySpec; /// A pointer to a CMSG_KEY_TRANS_RECIPIENT_INFO structure. public IntPtr pKeyTrans; /// Indicates a specific recipient in any array of recipients. public uint dwRecipientIndex; } /// The CMSG_CTRL_MAIL_LIST_DECRYPT_PARA structure contains information on a mail list message recipient. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_mail_list_decrypt_para typedef struct // _CMSG_CTRL_MAIL_LIST_DECRYPT_PARA { DWORD cbSize; HCRYPTPROV hCryptProv; PCMSG_MAIL_LIST_RECIPIENT_INFO pMailList; DWORD // dwRecipientIndex; DWORD dwKeyChoice; union { HCRYPTKEY hKeyEncryptionKey; void *pvKeyEncryptionKey; } DUMMYUNIONNAME; } // CMSG_CTRL_MAIL_LIST_DECRYPT_PARA, *PCMSG_CTRL_MAIL_LIST_DECRYPT_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "30735e01-db6b-40fc-b4c8-cdc24e73defa")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_MAIL_LIST_DECRYPT_PARA { /// The size, in bytes, of this data structure. public uint cbSize; /// /// The provider used to do the recipient key encryption and export. If hCryptProv is NULL, the provider specified /// in CMSG_ENVELOPED_ENCODE_INFO is used. /// public HCRYPTPROV hCryptProv; /// A pointer to a CMSG_MAIL_LIST_RECIPIENT_INFO structure. public IntPtr pMailList; /// Indicates a specific recipient in any array of recipients. public uint dwRecipientIndex; /// /// Indicates the member of the following union that will be used. Currently only CMSG_MAIL_LIST_HANDLE_KEY_CHOICE is defined. /// public uint dwKeyChoice; /// Handle of the key encryption key. Used with dwKeyChoice set to CMSG_MAIL_LIST_HANDLE_KEY_CHOICE. public HCRYPTKEY hKeyEncryptionKey; } /// /// The CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA structure contains information used to verify a message signature. It contains the /// signer index and signer public key. The signer public key can be the signer's CERT_PUBLIC_KEY_INFO structure, certificate /// context, or chain context. /// /// /// If dwSignerType is CMSG_VERIFY_SIGNER_NULL, the signature is expected to contain only the unencrypted hash octets. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_ctrl_verify_signature_ex_para typedef struct // _CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA { DWORD cbSize; HCRYPTPROV_LEGACY hCryptProv; DWORD dwSignerIndex; DWORD dwSignerType; void // *pvSigner; } CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA, *PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "56b73de8-c170-46f6-b488-096475b59c15")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA { /// The size, in bytes, of this structure. public uint cbSize; /// /// This member is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: A handle to the cryptographic provider used to verify the signature. If /// NULL, the cryptographic provider specified in CryptMsgOpenToDecode is used. If the hCryptProv in /// CryptMsgOpenToDecode is also NULL, the default provider according to the signer's public key object identifier /// (OID) is used.This member's data type is HCRYPTPROV. /// /// public HCRYPTPROV hCryptProv; /// The index of the signer in the message. public uint dwSignerIndex; /// /// /// The structure that contains the signer information. The following table shows the predefined values and the structures indicated. /// /// /// /// Value /// Meaning /// /// /// CMSG_VERIFY_SIGNER_PUBKEY /// CERT_PUBLIC_KEY_INFO /// /// /// CMSG_VERIFY_SIGNER_CERT /// CERT_CONTEXT /// /// /// CMSG_VERIFY_SIGNER_CHAIN /// CERT_CHAIN_CONTEXT /// /// /// CMSG_VERIFY_SIGNER_NULL /// NULL /// /// /// public CryptMsgSignerType dwSignerType; /// /// A pointer to a CERT_PUBLIC_KEY_INFO structure, a certificate context, a chain context, or NULL depending on the value /// of dwSignerType. /// public IntPtr pvSigner; } /// The CMSG_KEY_AGREE_RECIPIENT_INFO structure contains information used for key agreement algorithms. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_key_agree_recipient_info typedef struct // _CMSG_KEY_AGREE_RECIPIENT_INFO { DWORD dwVersion; DWORD dwOriginatorChoice; union { CERT_ID OriginatorCertId; // CERT_PUBLIC_KEY_INFO OriginatorPublicKeyInfo; } DUMMYUNIONNAME; CRYPT_DATA_BLOB UserKeyingMaterial; CRYPT_ALGORITHM_IDENTIFIER // KeyEncryptionAlgorithm; DWORD cRecipientEncryptedKeys; PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO *rgpRecipientEncryptedKeys; } // CMSG_KEY_AGREE_RECIPIENT_INFO, *PCMSG_KEY_AGREE_RECIPIENT_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "d29d04d6-065e-4bb7-843b-f563643eeb4c")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_KEY_AGREE_RECIPIENT_INFO { /// A DWORD that indicates the version of the structure. Always set to three. public uint dwVersion; /// A DWORD that indicates the key identifier to use. public CryptMsgKeyOriginator dwOriginatorChoice; /// public CMSG_KEY_AGREE_RECIPIENT_INFO_UNION Originator; /// [StructLayout(LayoutKind.Explicit)] public struct CMSG_KEY_AGREE_RECIPIENT_INFO_UNION { /// A CERT_ID that identifies the public key of the message originator. [FieldOffset(0)] public CERT_ID OriginatorCertId; /// A CERT_PUBLIC_KEY_INFO structure that contains the public key of the message originator. [FieldOffset(0)] public CERT_PUBLIC_KEY_INFO OriginatorPublicKeyInfo; } /// /// A CRYPT_DATA_BLOB that indicates that a different key is generated each time the same two parties generate a pair of keys. /// The sender provides the bits of this BLOB with some key agreement algorithms. This member can be NULL. /// public CRYPTOAPI_BLOB UserKeyingMaterial; /// /// A CRYPT_ALGORITHM_IDENTIFIER that identifies the key-encryption algorithm and any associated parameters used to encrypt the /// content encryption key. /// public CRYPT_ALGORITHM_IDENTIFIER KeyEncryptionAlgorithm; /// The number of elements in the rgpRecipientEncryptedKeys array. public uint cRecipientEncryptedKeys; /// /// The address of an array of CMSG_RECIPIENT_ENCRYPTED_KEY_INFO structures that contains information about the key recipients. /// The cRecipientEncryptedKeys member contains the number of elements in this array. /// public IntPtr rgpRecipientEncryptedKeys; } /// The CMSG_KEY_TRANS_RECIPIENT_INFO structure contains information used in key transport algorithms. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_key_trans_recipient_info typedef struct // _CMSG_KEY_TRANS_RECIPIENT_INFO { DWORD dwVersion; CERT_ID RecipientId; CRYPT_ALGORITHM_IDENTIFIER KeyEncryptionAlgorithm; // CRYPT_DATA_BLOB EncryptedKey; } CMSG_KEY_TRANS_RECIPIENT_INFO, *PCMSG_KEY_TRANS_RECIPIENT_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "956b0646-50a5-46d1-aa9a-91194c35d2b2")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_KEY_TRANS_RECIPIENT_INFO { /// /// Indicates the version of the structure. If RecipientId uses the ISSUER_SERIAL_NUMBER to identify the recipient, /// dwVersion is set to zero. If RecipientId uses KEYID, dwVersion is set to two. /// public uint dwVersion; /// /// A CERT_ID that identifies the recipient. Currently, only ISSUER_SERIAL_NUMBER or KEYID choices in the CERT_ID are valid. /// public CERT_ID RecipientId; /// /// A CRYPT_ALGORITHM_IDENTIFIER that identifies the key-encryption algorithm and any associated parameters used to encrypt the /// content encryption key. /// public CRYPT_ALGORITHM_IDENTIFIER KeyEncryptionAlgorithm; /// A CRYPT_DATA_BLOB that contains the bytes of the encrypted session key. public CRYPTOAPI_BLOB EncryptedKey; } /// /// The CMSG_MAIL_LIST_RECIPIENT_INFO structure contains information used for previously distributed symmetric key-encryption /// keys (KEK). /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_mail_list_recipient_info typedef struct // _CMSG_MAIL_LIST_RECIPIENT_INFO { DWORD dwVersion; CRYPT_DATA_BLOB KeyId; CRYPT_ALGORITHM_IDENTIFIER KeyEncryptionAlgorithm; // CRYPT_DATA_BLOB EncryptedKey; FILETIME Date; PCRYPT_ATTRIBUTE_TYPE_VALUE pOtherAttr; } CMSG_MAIL_LIST_RECIPIENT_INFO, *PCMSG_MAIL_LIST_RECIPIENT_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "e0946278-75e9-4990-af81-d9e61da9724b")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_MAIL_LIST_RECIPIENT_INFO { /// Indicates the version of the structure. This member is always four. public uint dwVersion; /// /// A CRYPT_DATA_BLOB structure that identifies a symmetric key-encryption key previously distributed to the sender and one or /// more recipients. /// public CRYPTOAPI_BLOB KeyId; /// /// CRYPT_ALGORITHM_IDENTIFIER that identifies the key-encryption algorithm and any associated parameters used to encrypt the /// content encryption key. /// public CRYPT_ALGORITHM_IDENTIFIER KeyEncryptionAlgorithm; /// A CRYPT_DATA_BLOB structure that contains the encrypted content encryption key. public CRYPTOAPI_BLOB EncryptedKey; /// Optional. When present, this member specifies a single key-encryption key from a previously distributed set. public FILETIME Date; /// Optional pointer to a CRYPT_ATTRIBUTE_TYPE_VALUE structure containing additional information. public IntPtr pOtherAttr; } /// /// The CMSG_RECIPIENT_ENCRYPTED_KEY_INFO structure contains information used for an individual key agreement recipient. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_recipient_encrypted_key_info typedef struct // _CMSG_RECIPIENT_ENCRYPTED_KEY_INFO { CERT_ID RecipientId; CRYPT_DATA_BLOB EncryptedKey; FILETIME Date; // PCRYPT_ATTRIBUTE_TYPE_VALUE pOtherAttr; } CMSG_RECIPIENT_ENCRYPTED_KEY_INFO, *PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "1921f9b6-86d9-47a0-a36e-e20d481382a3")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_RECIPIENT_ENCRYPTED_KEY_INFO { /// /// CERT_ID structure identifying the recipient. Currently, only the ISSUER_SERIAL_NUMBER or KEYID choices in the CERT_ID /// structure are valid. /// public CERT_ID RecipientId; /// A CRYPT_DATA_BLOB structure that contains the encrypted content encryption key. public CRYPTOAPI_BLOB EncryptedKey; /// /// Optional. When present, this member specifies which of the recipient's previously distributed UKMs was used by the sender. /// Only applicable to KEYID choice in the RecipientId CERT_ID structure. /// public FILETIME Date; /// /// Optional pointer to a CRYPT_ATTRIBUTE_TYPE_VALUE structure containing additional information. Only applicable to KEYID /// choice in the RecipientId CERT_ID structure. /// public IntPtr pOtherAttr; } /// /// The CMSG_SIGNER_ENCODE_INFO structure contains signer information. It is passed to CryptMsgCountersign, /// CryptMsgCountersignEncoded, and optionally to CryptMsgOpenToEncode as a member of the CMSG_SIGNED_ENCODE_INFO structure, if the /// dwMsgType parameter is CMSG_SIGNED. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_signer_encode_info typedef struct // _CMSG_SIGNER_ENCODE_INFO { DWORD cbSize; PCERT_INFO pCertInfo; union { HCRYPTPROV hCryptProv; NCRYPT_KEY_HANDLE hNCryptKey; // BCRYPT_KEY_HANDLE hBCryptKey; } DUMMYUNIONNAME; DWORD dwKeySpec; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; void *pvHashAuxInfo; // DWORD cAuthAttr; PCRYPT_ATTRIBUTE rgAuthAttr; DWORD cUnauthAttr; PCRYPT_ATTRIBUTE rgUnauthAttr; CERT_ID SignerId; // CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; void *pvHashEncryptionAuxInfo; } CMSG_SIGNER_ENCODE_INFO, *PCMSG_SIGNER_ENCODE_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "f599226d-ddd7-455f-b650-74b91674d8f9")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_SIGNER_ENCODE_INFO { /// The size, in bytes, of this structure. public uint cbSize; /// /// A pointer to a CERT_INFO structure that contains the /// Issuer, SerialNumber, and SubjectPublicKeyInfo members. /// /// The pbData members of the Issuer and SerialNumber structures combined uniquely identify a certificate. /// The Algorithm member of the SubjectPublicKeyInfo structure specifies the hash encryption algorithm used. /// /// public IntPtr pCertInfo; /// public CMSG_SIGNER_ENCODE_INFO_HANDLES Handle; /// [StructLayout(LayoutKind.Explicit)] public struct CMSG_SIGNER_ENCODE_INFO_HANDLES { /// /// A handle to the cryptographic service provider (CSP). If HashEncryptionAlgorithm is set to /// szOID_PKIX_NO_SIGNATURE, this handle can be the handle of a CSP acquired by using the dwFlags parameter set to /// CRYPT_VERIFYCONTEXT. The CNG function NCryptIsKeyHandle is called to determine the union choice. /// [FieldOffset(0)] public HCRYPTPROV hCryptProv; /// /// A handle to the CNG CSP. The CNG function NCryptIsKeyHandle is called to determine the union choice. New encrypt /// algorithms are only supported in CNG functions. The CNG function NCryptTranslateHandle will be called to convert the /// CryptoAPI hCryptProv choice where necessary. We recommend that applications pass, to the hNCryptKey member, the CNG CSP /// handle that is returned from the NCryptOpenKey function. /// [FieldOffset(0)] public NCrypt.NCRYPT_KEY_HANDLE hNCryptKey; /// [FieldOffset(0)] public BCrypt.BCRYPT_KEY_HANDLE hBCryptKey; } /// /// Specifies the private key to be used. This member is not used when the hNCryptKey member is used. /// If dwKeySpec is zero, then the default AT_KEYEXCHANGE value is used. /// The following dwKeySpec values are defined for the default provider. /// /// /// Value /// Meaning /// /// /// AT_KEYEXCHANGE /// Keys used to encrypt/decrypt session keys. /// /// /// AT_SIGNATURE /// Keys used to create and verify digital signatures. /// /// /// public CertKeySpec dwKeySpec; /// A CRYPT_ALGORITHM_IDENTIFIER structure that specifies the hash algorithm. public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// Not used. This member must be set to NULL. public IntPtr pvHashAuxInfo; /// /// The number of elements in the rgAuthAttr array. If no authenticated attributes are present in rgAuthAttr, then /// cAuthAttr is zero. /// public uint cAuthAttr; /// /// An array of pointers to CRYPT_ATTRIBUTE structures, each of which contains authenticated attribute information. /// /// The PKCS #9 standard dictates that if there are any attributes, there must be at least two: the content type object /// identifier (OID) and the hash of the message. These attributes are automatically added by the system. /// /// public IntPtr rgAuthAttr; /// /// The number of elements in the rgUnauthAttr array. If there are no unauthenticated attributes, cUnauthAttr is zero. /// public uint cUnauthAttr; /// /// An array of pointers to CRYPT_ATTRIBUTE structures, each of which contains unauthenticated attribute information. /// Unauthenticated attributes can contain countersignatures, among other uses. /// public IntPtr rgUnauthAttr; /// /// A CERT_ID structure that contains a unique identifier of the signer's certificate. This member can optionally be used with /// PKCS #7 with Cryptographic Message Syntax (CMS). If this member is not NULL and its dwIdChoice member is not /// zero, it is used to identify the certificate instead of the Issuer and SerialNumber members of the CERT_INFO /// structure pointed to by pCertInfo. CMS supports the KEY_IDENTIFIER and ISSUER_SERIAL_NUMBER CERT_ID structures. PKCS /// version 1.5 supports only the ISSUER_SERIAL_NUMBER CERT_ID choice. This member is used with CMS for PKCS #7 processing and /// can be used only if CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS is defined. /// public CERT_ID SignerId; /// /// /// A CRYPT_ALGORITHM_IDENTIFIER structure optionally used with PKCS #7 with CMS. If this member is not NULL, the /// algorithm identified is used instead of the SubjectPublicKeyInfo.Algorithm algorithm. If this member is set to /// szOID_PKIX_NO_SIGNATURE, the signature value contains only the hash octets. /// /// /// For RSA, the hash encryption algorithm is normally the same as the public key algorithm. For DSA, the hash encryption /// algorithm is normally a DSS signature algorithm. /// /// /// This member is used with CMS for PKCS #7 processing and can be used only if CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS is defined. /// /// public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; /// /// This member is not used. This member must be set to NULL if it is present in the data structure. This member is /// present only if CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS is defined. /// public IntPtr pvHashEncryptionAuxInfo; } /// /// The CMSG_SIGNER_INFO structure contains the content of the PKCS #7 defined SignerInfo in signed messages. In decoding a /// received message, CryptMsgGetParam is called for each signer to get a CMSG_SIGNER_INFO structure. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_signer_info typedef struct _CMSG_SIGNER_INFO { DWORD // dwVersion; CERT_NAME_BLOB Issuer; CRYPT_INTEGER_BLOB SerialNumber; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; // CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; CRYPT_DATA_BLOB EncryptedHash; CRYPT_ATTRIBUTES AuthAttrs; CRYPT_ATTRIBUTES // UnauthAttrs; } CMSG_SIGNER_INFO, *PCMSG_SIGNER_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "NS:wincrypt._CMSG_SIGNER_INFO")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_SIGNER_INFO { /// The version of this structure. public uint dwVersion; /// A CERT_NAME_BLOB structure that contains the issuer of a certificate with the public key needed to verify a signature. public CRYPTOAPI_BLOB Issuer; /// /// A CRYPT_INTEGER_BLOB structure that contains the serial number of the certificate that contains the public key needed to /// verify a signature. For more information, see CERT_INFO. /// public CRYPTOAPI_BLOB SerialNumber; /// CRYPT_ALGORITHM_IDENTIFIER structure specifying the algorithm used in generating the hash of a message. public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// CRYPT_ALGORITHM_IDENTIFIER structure specifying the algorithm used to encrypt the hash. public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; /// A CRYPT_DATA_BLOB that contains the encrypted hash of the message, the signature. public CRYPTOAPI_BLOB EncryptedHash; /// CRYPT_ATTRIBUTES structure containing authenticated attributes of the signer. public CRYPT_ATTRIBUTES AuthAttrs; /// CRYPT_ATTRIBUTES structure containing unauthenticated attributes of the signer. public CRYPT_ATTRIBUTES UnauthAttrs; } /// /// /// The CMSG_STREAM_INFO structure is used to enable stream processing of data rather than single block processing. Stream /// processing is most often used when processing large messages. Stream-processed messages can originate from any serialized source /// such as a file on a hard disk, a server, or a CD ROM. /// /// This structure is passed to the CryptMsgOpenToEncode and CryptMsgOpenToDecode functions. /// /// /// /// Messages can be so large that processing them all at once by storing the whole message in memory can be difficult, if not /// impossible. It is possible to process large messages without encountering memory limitations by streaming the data that is to be /// processed into manageable sized blocks. The low-level message functions can be used with streaming to encode or decode a /// message. Any level of nesting of messages is supported when streaming to encode and streaming to decode. /// /// /// The input message to be processed as a stream feeds into CryptMsgUpdate one block at a time, with the application determining /// the size of the block. As the streamed message is processed for encoding or decoding, the resulting output data is passed back /// to the application through an application-specified callback function that is specified by the pfnStreamOutput member. /// /// /// No assumptions can be made about the block size of the output data because the size can vary for several reasons, such as the /// jitter in output block size caused by the block size for the encryption algorithm when processing an enveloped message, or when /// blocks that contain the message header and the SignerInfo as defined by PKCS # 7 are processed. /// /// /// The size of the output block is passed to the callback function in its cbData parameter. The use of output data is determined in /// the calling application. Typically, output from stream processing will not be persisted in memory as a whole due to memory /// limitations; rather, it will be serialized to a disk or server file. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cmsg_stream_info typedef struct _CMSG_STREAM_INFO { DWORD // cbContent; PFN_CMSG_STREAM_OUTPUT pfnStreamOutput; void *pvArg; } CMSG_STREAM_INFO, *PCMSG_STREAM_INFO; [PInvokeData("wincrypt.h", MSDNShortId = "a4e7f6e8-351f-4981-b223-50b65f503394")] [StructLayout(LayoutKind.Sequential)] public struct CMSG_STREAM_INFO { /// /// Specifies the size, in bytes, of the content. Normal Distinguished Encoding Rules (DER) encoding is used unless /// CMSG_INDEFINITE_LENGTH(0xFFFFFFFF) is passed, indicating that the application is not specifying the content length. /// This forces the use of indefinite-length Basic Encoding Rules (BER) encoding. /// public uint cbContent; /// /// The address of a callback function used to read from and write data to a disk when processing large messages. /// The callback function must have the following signature and parameters: /// public PFN_CMSG_STREAM_OUTPUT pfnStreamOutput; /// /// A pointer to the argument to pass to the callback function. Typically, this is used for state data that includes the handle /// to a more deeply nested message (when decoding) or a less deeply nested message (when encoding). /// public IntPtr pvArg; } /// The CRYPT_DECRYPT_MESSAGE_PARA structure contains information for decrypting messages. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_decrypt_message_para typedef struct // _CRYPT_DECRYPT_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgAndCertEncodingType; DWORD cCertStore; HCERTSTORE *rghCertStore; DWORD // dwFlags; } CRYPT_DECRYPT_MESSAGE_PARA, *PCRYPT_DECRYPT_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "67e136cd-12e3-4a31-9d8b-b53e1129e940")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_DECRYPT_MESSAGE_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// /// Type of encoding 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 /// /// /// public CertEncodingType dwMsgAndCertEncodingType; /// Number of elements in the rghCertStore array. public uint cCertStore; /// /// Array of certificate store handles. /// /// These certificate store handles are used to obtain the certificate context to use for decrypting a message. For more /// information, see the decryption functions CryptDecryptMessage, and CryptDecryptAndVerifyMessageSignature. An encrypted /// message can have one or more recipients. The recipients are identified by a unique certificate identifier, often the hash of /// the certificate issuer and serial number. The certificate stores are searched to find a certificate context corresponding to /// the unique identifier. /// /// /// Recipients can also be identified by their KeyId. Both Key Agreement (Diffie-Hellman) and Key Transport (RSA) recipients are supported. /// /// /// Only certificate contexts in the store with one of the following properties, CERT_KEY_PROV_INFO_PROP_ID, or /// CERT_KEY_CONTEXT_PROP_ID can be used. These properties specify the location of a needed private exchange key. /// /// public IntPtr rghCertStore; /// /// The CRYPT_MESSAGE_SILENT_KEYSET_FLAG can be set to suppress any UI by the CSP. For more information about the CRYPT_SILENT /// flag, see CryptAcquireContext. /// public CryptMsgActionFlags dwFlags; } /// The CRYPT_ENCRYPT_MESSAGE_PARA structure contains information used to encrypt messages. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_encrypt_message_para typedef struct // _CRYPT_ENCRYPT_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgEncodingType; HCRYPTPROV_LEGACY hCryptProv; CRYPT_ALGORITHM_IDENTIFIER // ContentEncryptionAlgorithm; void *pvEncryptionAuxInfo; DWORD dwFlags; DWORD dwInnerContentType; } CRYPT_ENCRYPT_MESSAGE_PARA, *PCRYPT_ENCRYPT_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "c683c515-3061-48e3-a64a-2798bd1245b0")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_ENCRYPT_MESSAGE_PARA { /// The size, in bytes, of this structure. public uint cbSize; /// /// /// The type of encoding 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 /// /// /// public CertEncodingType dwMsgEncodingType; /// /// This member is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: The handle to the cryptographic service provider (CSP) to be used for encryption. /// The CSP identified by hCryptProv is used to do content encryption, recipient key encryption, and recipient key /// export. Its private key is not used. /// /// /// Unless there is a strong reason for passing in a specific cryptographic provider in hCryptProv, pass zero to use the /// default RSA or DSS provider. /// /// This member's data type is HCRYPTPROV. /// public HCRYPTPROV hCryptProv; /// /// /// A CRYPT_ALGORITHM_IDENTIFIER structure that contains the object identifier (OID) of the encryption algorithm to use. The CSP /// specified by the hCryptProv must support this encryption algorithm. /// /// /// The szOID_OIWSEC_desCBC (CALG_DES) and szOID_RSA_DES_EDE3_CBC (CALG_3DES) encryption algorithms require the /// Parameters member of this structure to contain an encoded eight-byte initialization vector (IV). If the cbData /// member of the Parameters member is zero, an Abstract Syntax Notation One (ASN.1)-encoded OCTET STRING that contains /// the IV is generated using CryptGenRandom. For more information about the KP_IV parameter, see CryptSetKeyParam. /// /// /// The szOID_NIST_AES128_CBC (BCRYPT_AES_ALGORITHM, 128 bit), szOID_NIST_AES192_CBC (BCRYPT_AES_ALGORITHM, 192 /// bit), and szOID_NIST_AES256_CBC (BCRYPT_AES_ALGORITHM, 256 bit) encryption algorithms require the Parameters /// member of this structure to contain an encoded sixteen-byte initialization vector (IV). If the cbData member of the /// Parameters member is zero, an Abstract Syntax Notation One (ASN.1)-encoded OCTET STRING that contains the IV is generated. /// /// /// The szOID_RSA_RC2CBC (CALG_RC2) algorithm requires the pbData member of the Parameters member of this /// structure to be a CRYPT_RC2_CBC_PARAMETERS structure. If the cbData member of the Parameters member is zero, /// an ASN.1-encoded CRYPT_RC2_CBC_PARAMETERS structure that contains the IV is generated as the pbData member. /// This generated pbData uses the default dwVersion that corresponds to the 40-bit key length. To override the /// default 40-bit key length, pvEncryptionAuxInfo can be set to point to a CMSG_RC2_AUX_INFO structure that contains a /// key bit length. /// /// /// Note When a message is decrypted, if it has an initialization vector parameter, the cryptographic message functions /// call CryptSetKeyParam with the initialization vector before decrypting. /// /// public CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm; /// /// /// A pointer to a CMSG_RC2_AUX_INFO structure for RC2 encryption or a CMSG_SP3_COMPATIBLE_AUX_INFO structure for SP3-compatible /// encryption. For other than RC2 or SP3-compatible encryption, this member must be set to NULL. /// /// /// If the ContentEncryptionAlgorithm member contains szOID_RSA_RC4, this member points to a CMSG_RC4_AUX_INFO /// structure that specifies the number of salt bytes to be included. /// /// public IntPtr pvEncryptionAuxInfo; /// /// /// Normally set to zero. However, if the encoded output is to be a CMSG_ENVELOPED inner content of an outer cryptographic /// message, such as a CMSG_SIGNED message, the CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG must be set. If it is not set, content will /// be encoded as an inner content type of CMSG_DATA. /// /// /// CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG can be set to encapsulate non-data inner content within an OCTET STRING before encrypting. /// /// /// CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG can be set to identify recipients by their Key Identifier and not their Issuer and Serial Number. /// /// public CryptMsgActionFlags dwFlags; /// /// Normally set to zero. The dwInnerContentType member must be set to set the cryptographic message types if the input /// to be encrypted is the encoded output of another cryptographic message such as CMSG_SIGNED. /// public CryptMsgType dwInnerContentType; } /// The CRYPT_HASH_MESSAGE_PARA structure contains data for hashing messages. // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_hash_message_para typedef struct // _CRYPT_HASH_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgEncodingType; HCRYPTPROV_LEGACY hCryptProv; CRYPT_ALGORITHM_IDENTIFIER // HashAlgorithm; void *pvHashAuxInfo; } CRYPT_HASH_MESSAGE_PARA, *PCRYPT_HASH_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "60415136-3ac0-4fab-bdbf-faa16e8e43e1")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_HASH_MESSAGE_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// /// Type of encoding 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 /// /// /// public CertEncodingType dwMsgEncodingType; /// /// This member is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: A handle to the cryptographic service provider (CSP) to be used.Unless there is a /// strong reason for passing in a specific cryptographic provider in hCryptProv, pass zero to use the default RSA or DSS provider. /// /// This member's data type is HCRYPTPROV. /// public HCRYPTPROV hCryptProv; /// CRYPT_ALGORITHM_IDENTIFIER containing the algorithm for generating the hash of the message. public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// Not currently used, and must be set to NULL. public IntPtr pvHashAuxInfo; } /// /// The CRYPT_KEY_SIGN_MESSAGE_PARA structure contains information about the cryptographic service provider (CSP) and /// algorithms used to sign a message. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_key_sign_message_para typedef struct // _CRYPT_KEY_SIGN_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgAndCertEncodingType; union { HCRYPTPROV hCryptProv; NCRYPT_KEY_HANDLE // hNCryptKey; } DUMMYUNIONNAME; DWORD dwKeySpec; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; void *pvHashAuxInfo; // CRYPT_ALGORITHM_IDENTIFIER PubKeyAlgorithm; } CRYPT_KEY_SIGN_MESSAGE_PARA, *PCRYPT_KEY_SIGN_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "d5426ad6-2181-42ce-99f2-cc6cc83e20a8")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_KEY_SIGN_MESSAGE_PARA { /// The size, in bytes, of this data structure. public uint cbSize; /// /// /// Specifies the type of message and certificate encoding used. This can be a combination of one or more of the following values. /// /// /// /// Value /// Meaning /// /// /// X509_ASN_ENCODING /// Specifies X.509 certificate encoding. /// /// /// PKCS_7_ASN_ENCODING /// Specifies PKCS 7 message encoding. /// /// /// public CertEncodingType dwMsgAndCertEncodingType; /// public CRYPT_KEY_SIGN_MESSAGE_PARA_HANDLE Handle; /// [StructLayout(LayoutKind.Explicit)] public struct CRYPT_KEY_SIGN_MESSAGE_PARA_HANDLE { /// /// The handle of the CSP to use to sign the message. The CryptAcquireContext function is called to obtain this handle. /// [FieldOffset(0)] public HCRYPTPROV hCryptProv; /// /// The handle of the Cryptography API: Next Generation (CNG) CSP to use to sign the message. CNG signature algorithms are /// only supported in CNG functions. /// [FieldOffset(0)] public NCrypt.NCRYPT_KEY_HANDLE hNCryptKey; } /// /// /// Identifies the type of private key to use to sign the message. This must be one of the following values. This member is /// ignored if a CNG key is passed in the hNCryptKey member. /// /// /// /// Value /// Meaning /// /// /// AT_KEYEXCHANGE /// Use the key exchange key. /// /// /// AT_SIGNATURE /// Use the digital signature key. /// /// /// public CertKeySpec dwKeySpec; /// /// A CRYPT_ALGORITHM_IDENTIFIER structure that specifies the algorithm to use to generate the hash of the message. This must be /// a hash algorithm. /// public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// This member is not used and must be set to NULL. public IntPtr pvHashAuxInfo; /// /// A CRYPT_ALGORITHM_IDENTIFIER structure that specifies the algorithm to use to sign the message. This must be either a public /// key or a signature algorithm. /// public CRYPT_ALGORITHM_IDENTIFIER PubKeyAlgorithm; } /// /// The CRYPT_KEY_VERIFY_MESSAGE_PARA structure contains information needed to verify signed messages without a certificate /// for the signer. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_key_verify_message_para typedef struct // _CRYPT_KEY_VERIFY_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgEncodingType; HCRYPTPROV_LEGACY hCryptProv; } // CRYPT_KEY_VERIFY_MESSAGE_PARA, *PCRYPT_KEY_VERIFY_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "4e0178fb-1f9f-4ee4-9a83-f37cf71d35ff")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_KEY_VERIFY_MESSAGE_PARA { /// The size, in bytes, of this structure. public uint cbSize; /// /// /// Type of encoding 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 /// /// /// public CertEncodingType dwMsgEncodingType; /// /// This member is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: A handle to the cryptographic service provider (CSP) to be used to verify a /// signed message. The CSP identified by this handle is used for hashing and for signature verification.Unless there is a /// strong reason for using a specific cryptographic provider, set this member to zero to use the default RSA or DSS provider. /// /// This member's data type is HCRYPTPROV. /// public HCRYPTPROV hCryptProv; } /// /// The CRYPT_SIGN_MESSAGE_PARA structure contains information for signing messages using a specified signing certificate context. /// /// /// The HashEncryptionAlgorithm and pvHashEncryptionAuxInfo members can only be used if /// CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS is defined. /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_sign_message_para typedef struct // _CRYPT_SIGN_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgEncodingType; PCCERT_CONTEXT pSigningCert; CRYPT_ALGORITHM_IDENTIFIER // HashAlgorithm; void *pvHashAuxInfo; DWORD cMsgCert; PCCERT_CONTEXT *rgpMsgCert; DWORD cMsgCrl; PCCRL_CONTEXT *rgpMsgCrl; DWORD // cAuthAttr; PCRYPT_ATTRIBUTE rgAuthAttr; DWORD cUnauthAttr; PCRYPT_ATTRIBUTE rgUnauthAttr; DWORD dwFlags; DWORD // dwInnerContentType; CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; void *pvHashEncryptionAuxInfo; } CRYPT_SIGN_MESSAGE_PARA, *PCRYPT_SIGN_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "1601d860-6054-4650-a033-ea088655b7e4")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_SIGN_MESSAGE_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// /// Type of encoding 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 /// /// /// public CertEncodingType dwMsgEncodingType; /// /// A pointer to the CERT_CONTEXT to be used in the signing. /// /// Either the CERT_KEY_PROV_INFO_PROP_ID, or CERT_KEY_CONTEXT_PROP_ID property must be set for the context to provide access to /// the private signature key. /// /// public PCCERT_CONTEXT pSigningCert; /// CRYPT_ALGORITHM_IDENTIFIER containing the hashing algorithm used to hash the data to be signed. public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; /// Not currently used, and must be set to NULL. public IntPtr pvHashAuxInfo; /// /// Number of elements in the rgpMsgCert array of CERT_CONTEXT structures. If set to zero no certificates are included in /// the signed message. /// public uint cMsgCert; /// /// Array of pointers to CERT_CONTEXT structures to be included in the signed message. If the pSigningCert is to be /// included, a pointer to it must be in the rgpMsgCert array. /// public IntPtr rgpMsgCert; /// /// Number of elements in the rgpMsgCrl array of pointers to CRL_CONTEXT structures. If set to zero, no /// CRL_CONTEXT structures are included in the signed message. /// public uint cMsgCrl; /// Array of pointers to CRL_CONTEXT structures to be included in the signed message. public IntPtr rgpMsgCrl; /// /// Number of elements in the rgAuthAttr array. If no authenticated attributes are present in rgAuthAttr, this /// member is set to zero. /// public uint cAuthAttr; /// /// Array of pointers to CRYPT_ATTRIBUTE structures, each holding authenticated attribute information. If there are /// authenticated attributes present, the PKCS #9 standard dictates that there must be at least two attributes present, the /// content type object identifier (OID), and the hash of the message itself. These attributes are automatically added by the system. /// public IntPtr rgAuthAttr; /// /// Number of elements in the rgUnauthAttr array. If no unauthenticated attributes are present in rgUnauthAttr, /// this member is zero. /// public uint cUnauthAttr; /// /// Array of pointers to CRYPT_ATTRIBUTE structures each holding an unauthenticated attribute information. Unauthenticated /// attributes can be used to contain countersignatures, among other uses. /// public IntPtr rgUnauthAttr; /// /// /// Normally zero. If the encoded output is to be a CMSG_SIGNED inner content of an outer cryptographic message such as a /// CMSG_ENVELOPED message, the CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG must be set. If it is not set, the message will be encoded /// as an inner content type of CMSG_DATA. /// /// /// CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG can be set to encapsulate non-data inner content into an OCTET STRING. /// CRYPT_MESSAGE_KEYID_SIGNER_FLAG can be set to identify signers by their Key Identifier and not their Issuer and Serial Number. /// /// /// CRYPT_MESSAGE_SILENT_KEYSET_FLAG can be set to suppress any UI by the CSP. For more information about the CRYPT_SILENT flag, /// see CryptAcquireContext. /// /// public CryptMsgActionFlags dwFlags; /// /// Normally zero. Set to the encoding type of the input message if that input to be signed is the encoded output of another /// cryptographic message. /// public uint dwInnerContentType; /// /// A CRYPT_ALGORITHM_IDENTIFIER. If present and not NULL, it is used instead of the signer's certificate /// PublicKeyInfo.Algorithm member. Note that for RSA, the hash encryption algorithm is normally the same as the public /// key algorithm. For DSA, the hash encryption algorithm is normally a DSS signature algorithm. This member can only be used if /// CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS is defined. /// [MarshalAs(UnmanagedType.FunctionPtr)] public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm; /// /// Currently not used and must be set to NULL. This member can only be used if CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS is defined. /// public IntPtr pvHashEncryptionAuxInfo; } /// The CRYPT_VERIFY_MESSAGE_PARA structure contains information needed to verify signed messages. /// /// This structure is passed to the following functions: /// /// /// CryptDecodeMessage /// /// /// CryptDecryptAndVerifyMessageSignature /// /// /// CryptVerifyDetachedMessageSignature /// /// /// CryptVerifyMessageSignature /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_verify_message_para typedef struct // _CRYPT_VERIFY_MESSAGE_PARA { DWORD cbSize; DWORD dwMsgAndCertEncodingType; HCRYPTPROV_LEGACY hCryptProv; // PFN_CRYPT_GET_SIGNER_CERTIFICATE pfnGetSignerCertificate; void *pvGetArg; PCCERT_STRONG_SIGN_PARA pStrongSignPara; } // CRYPT_VERIFY_MESSAGE_PARA, *PCRYPT_VERIFY_MESSAGE_PARA; [PInvokeData("wincrypt.h", MSDNShortId = "bbd56b5e-2bbe-420f-8842-1be50dca779f")] [StructLayout(LayoutKind.Sequential)] public struct CRYPT_VERIFY_MESSAGE_PARA { /// Size of this structure in bytes. public uint cbSize; /// /// /// Type of encoding 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 /// /// /// public CertEncodingType dwMsgAndCertEncodingType; /// /// This member is not used and should be set to NULL. /// /// Windows Server 2003 and Windows XP: A handle to the cryptographic service provider to be used to verify a signed /// message. The CSP identified by this handle is used for hashing and for signature verification.Unless there is a strong /// reason for using a specific cryptographic provider, set to zero to use the default RSA or DSS provider. /// /// This member's data type is HCRYPTPROV. /// public HCRYPTPROV hCryptProv; /// /// /// A pointer to the callback function used to get the signer's certificate context. If NULL, the default callback is /// used. The default callback tries to get the signer certificate context from the message's certificate store. /// /// /// An application defined–callback function that gets the signer's certificate can be used in place of the default. It is /// passed the certificate identifier of the signer (its issuer and serial number) and a handle to its cryptographic signed /// message's certificate store. /// /// See CryptGetSignerCertificateCallback for the callback functions signature and arguments. /// public PFN_CRYPT_GET_SIGNER_CERTIFICATE pfnGetSignerCertificate; /// Argument to pass to the callback function. Typically, this gets and verifies the message signer's certificate. public IntPtr pvGetArg; /// /// /// Optional pointer to a CERT_STRONG_SIGN_PARA structure that contains parameters used for strong signing. If you set this /// member and the function successfully verifies the signature, the function will then check for a strong signature. If the /// signature is not strong, the operation will fail and set the GetLastError value to NTE_BAD_ALGID. /// /// /// Note You can use the pStrongSignPara member only if CRYPT_VERIFY_MESSAGE_PARA_HAS_EXTRA_FIELDS is /// defined by using the #define directive before including Wincrypt.h. If /// CRYPT_VERIFY_MESSAGE_PARA_HAS_EXTRA_FIELDS is defined, you must zero all unused fields. /// /// Windows 8 and Windows Server 2012: /// Support for this member begins. /// public IntPtr pStrongSignPara; } /// Provides a for that is disposed using . public class SafeHCRYPTMSG : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHCRYPTMSG(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHCRYPTMSG() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HCRYPTMSG(SafeHCRYPTMSG h) => h.handle; /// protected override bool InternalReleaseHandle() => CryptMsgClose(handle); } } }