Export (0) Print
Expand All
Expand Minimize

CryptVerifyDetachedMessageSignature function

The CryptVerifyDetachedMessageSignature function verifies a signed message containing a detached signature or signatures.

Syntax


BOOL WINAPI CryptVerifyDetachedMessageSignature(
  _In_       PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  _In_       DWORD dwSignerIndex,
  _In_       const BYTE *pbDetachedSignBlob,
  _In_       DWORD cbDetachedSignBlob,
  _In_       DWORD cToBeSigned,
  _In_       const BYTE *rgpbToBeSigned[],
  _In_       DWORD rgcbToBeSigned[],
  _Out_opt_  PCCERT_CONTEXT *ppSignerCert
);

Parameters

pVerifyPara [in]

A pointer to a CRYPT_VERIFY_MESSAGE_PARA structure containing the verification parameters.

dwSignerIndex [in]

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.

pbDetachedSignBlob [in]

A pointer to a BLOB containing the encoded message signatures.

cbDetachedSignBlob [in]

The size, in bytes, of the detached signature.

cToBeSigned [in]

Number of array elements in rgpbToBeSigned and rgcbToBeSigned.

rgpbToBeSigned [in]

Array of pointers to buffers containing the contents to be hashed.

rgcbToBeSigned [in]

Array of sizes, in bytes, for the content buffers pointed to in rgpbToBeSigned.

ppSignerCert [out, optional]

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.

Return value

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

Examples

The following example shows using the CryptVerifyDetachedMessageSignature function to verify a message with a detached signature.


#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)


// Replace the following string with the subject of the signer 
// certificate.

#define SIGNER_NAME L"YOUR_SIGNER_CERTIFICATE" 

void MyHandleError(char *s);

void main()
{
    const BYTE* pbContent = (BYTE*)"Test Message.";

    DWORD cbContent;               // Size of message
    HCRYPTPROV hCryptProv;         // CSP handle
    HCERTSTORE hStoreHandle;       // Store handle
    PCCERT_CONTEXT pSignerCert;    // Signer certificate

    CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
    CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1];
    CERT_BLOB SignerCertBlob;
    CERT_BLOB SignerCertBlobArray[1];
    CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
    DWORD cbEncodedBlob;
    BYTE* pbEncodedBlob;
    HCRYPTMSG hMsg;
    DWORD dwKeySpec;

    CRYPT_VERIFY_MESSAGE_PARA msgPara;

    //---------------------------------------------------------------
    //  Initialize cbContent to the length of pbContent
    //  including the terminating NULL character.
    cbContent = strlen((char *) pbContent)+1;

    //---------------------------------------------------------------
    // Open the My system certificate store.

    hStoreHandle = CertOpenStore(
                                 CERT_STORE_PROV_SYSTEM,
                                 0,
                                 NULL,
                                 CERT_SYSTEM_STORE_CURRENT_USER,
                                 L"MY");
    if(!hStoreHandle)
    {
        MyHandleError( "Could not open the MY system store.");
    }

    //---------------------------------------------------------------
    // Get a pointer to a signer's signature certificate.
    pSignerCert = CertFindCertificateInStore(
                                             hStoreHandle,
                                             MY_ENCODING_TYPE,
                                             0,
                                             CERT_FIND_SUBJECT_STR,
                                             SIGNER_NAME,
                                             NULL);
    if (!pSignerCert)
    {
        MyHandleError("Cert not found.\n");
    }

    //---------------------------------------------------------------
    // Get a handle to a cryptographic provider. 
    if( !(CryptAcquireCertificatePrivateKey(
                                            pSignerCert,
                                            0,
                                            NULL,
                                            &hCryptProv,
                                            &dwKeySpec,
                                            NULL)))
    {
        MyHandleError("CryptAcquireContext failed");
    }
 
    memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
    SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
    SignerEncodeInfo.pCertInfo = pSignerCert->pCertInfo;
    SignerEncodeInfo.hCryptProv = hCryptProv;
    SignerEncodeInfo.dwKeySpec = dwKeySpec;
    SignerEncodeInfo.HashAlgorithm.pszObjId = szOID_RSA_MD5;
    SignerEncodeInfo.pvHashAuxInfo = NULL;

    //---------------------------------------------------------------
    // Initialize the first element of an array of signers. 
    // Note: Currently, there is only one signer.
    SignerEncodeInfoArray[0] = SignerEncodeInfo;

    //---------------------------------------------------------------
    // Initialize the CMSG_SIGNED_ENCODE_INFO structure.
    SignerCertBlob.cbData = pSignerCert->cbCertEncoded;
    SignerCertBlob.pbData = pSignerCert->pbCertEncoded;

    //---------------------------------------------------------------
    //  Initialize the first element of an array of signer BLOBs.
    //  Note: In this program, only one signer BLOB is used.

    SignerCertBlobArray[0] = SignerCertBlob;
    memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
    SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
    SignedMsgEncodeInfo.cSigners = 1;
    SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray;
    SignedMsgEncodeInfo.cCertEncoded = 1;
    SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray;

    //---------------------------------------------------------------
    // Get the size of the encoded message BLOB.
    if(!(cbEncodedBlob = CryptMsgCalculateEncodedLength(
        MY_ENCODING_TYPE,     // Message encoding type
        0,                    // Flags
        CMSG_SIGNED,          // Message type
        &SignedMsgEncodeInfo, // Pointer to structure
        NULL,                 // Inner content OID
        cbContent)))          // Size of content
    {
        MyHandleError("Getting cbEncodedBlob length failed.");
    }

    //---------------------------------------------------------------
    // Allocate memory for the encoded BLOB.
    if(!(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob)))
    {
        MyHandleError("Malloc operation failed.");
    }

    //---------------------------------------------------------------
    // Open a message to encode.
    if(!(hMsg = CryptMsgOpenToEncode(
        MY_ENCODING_TYPE,      // Encoding type
        CMSG_DETACHED_FLAG,    // Flags
        CMSG_SIGNED,           // Message type
        &SignedMsgEncodeInfo,  // Pointer to structure
        NULL,                  // Inner content OID
        NULL)))                // Stream information (not used)
    {
        MyHandleError("OpenToEncode failed");
    }

    //---------------------------------------------------------------
    // Update the message with the data.
    if(!(CryptMsgUpdate(
        hMsg,       // Handle to the message
        pbContent,  // Pointer to the content
        cbContent,  // Size of the content
        TRUE)))     // Last call
    {
        MyHandleError("MsgUpdate failed");
    }

    //---------------------------------------------------------------
    // Get the resulting message.
    if(!CryptMsgGetParam(
        hMsg,               // Handle to the message
        CMSG_CONTENT_PARAM, // Parameter type
        0,                  // Index
        pbEncodedBlob,      // Pointer to the BLOB
        &cbEncodedBlob))    // Size of the BLOB
    {
        MyHandleError("MsgGetParam failed.");
    }

    //---------------------------------------------------------------
    // The message is signed and encoded.
    // Close the message handle and the certificate store.
    CryptMsgClose(hMsg);
    CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
    CryptReleaseContext(hCryptProv, 0);


    // Verify the detached message.
    msgPara.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
    msgPara.dwMsgAndCertEncodingType = 
        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
    msgPara.hCryptProv = NULL;
    msgPara.pfnGetSignerCertificate = NULL;
    msgPara.pvGetArg = NULL;

    if ( CryptVerifyDetachedMessageSignature(
                                             &msgPara,
                                             0,
                                             pbEncodedBlob,
                                             cbEncodedBlob,
                                             1,
                                             &pbContent,
                                             &cbContent,
                                             NULL
                                            ) )
    {
        printf("The Signature verified.\n");
    }
    else
    {
        printf("Verification message failed.");
    }

    //---------------------------------------------------------------
    // Clean up.
    free(pbEncodedBlob);
}

//-------------------------------------------------------------------
//  Define function MyHandleError
void MyHandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr,"Error number %x.\n",GetLastError());
    fprintf(stderr,"Program terminating. \n");
    exit(1);
}

Requirements

Minimum supported client

Windows XP [desktop apps only]

Minimum supported server

Windows Server 2003 [desktop apps only]

Header

Wincrypt.h

Library

Crypt32.lib

DLL

Crypt32.dll

See also

Simplified Message Functions
CryptVerifyMessageSignature

 

 

Community Additions

ADD
Show:
© 2014 Microsoft