Code: bool SignData(BYTE *sgin1Data,int sgin1Len, BYTE *sgoutData,int &sgoutLen, LPWSTR CertName,LPWSTR SignerName) { BYTE *sgin11Data; DWORD sgin11Len; if(! make_hash( sgin1Data, sgin1Len, sgin11Data, sgin11Len)) { return false; } PBYTE tempBuffer =NULL; bool sdRet =true; //------------------------------------------------------------------- // Size of message. Note that the length set is one more than the // length returned by the strlen function in order to include // the NULL string termination character. DWORD cbMessage = sgin11Len+1; DWORD cbSignedMessageBlob; //------------------------------------------------------------------- // Pointer to a signer certificate PCCERT_CONTEXT pSignerCert; CRYPT_SIGN_MESSAGE_PARA SigParams; //------------------------------------------------------------------- // Create the MessageArray and the MessageSizeArray. const BYTE* MessageArray[] = {sgin11Data}; DWORD MessageSizeArray[1]; MessageSizeArray[0] = cbMessage; //------------------------------------------------------------------- // System store handle HCERTSTORE hStoreHandle; //------------------------------------------------------------------- // Open a certificate store. if ( !( hStoreHandle = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, CertName))) { return false; } //------------------------------------------------------------------- // Get a pointer to the signer's certificate. // This certificate must have access to the signer's private key. if(pSignerCert = CertFindCertificateInStore( hStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, SignerName, NULL)) { } else { AfxTrace("%d ", GetLastError()); return false; } if(VerifyClientCertificate(pSignerCert,0) !=SEC_E_OK) { sdRet =false; goto SPError; } //------------------------------------------------------------------- // Initialize the signature structure. SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType = MY_ENCODING_TYPE; SigParams.pSigningCert = pSignerCert; SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5; SigParams.HashAlgorithm.Parameters.cbData = NULL; SigParams.cMsgCert = 1; SigParams.rgpMsgCert = &pSignerCert; SigParams.cAuthAttr = 0; SigParams.dwInnerContentType = 0; SigParams.cMsgCrl = 0; SigParams.cUnauthAttr = 0; SigParams.dwFlags = 0; SigParams.pvHashAuxInfo = NULL; SigParams.rgAuthAttr = NULL; //------------------------------------------------------------------- // With two calls to CryptSignMessage, sign the message. // First, get the size of the output signed BLOB. if(CryptSignMessage( &SigParams, // Signature parameters FALSE, // Not detached 1, // Number of messages MessageArray, // Messages to be signed MessageSizeArray, // Size of messages NULL, // Buffer for signed message &cbSignedMessageBlob)) // Size of buffer { } else { AfxTrace("%d ", GetLastError()); return false; } //------------------------------------------------------------------- // Allocate memory for the signed BLOB. if(!(tempBuffer = (BYTE*)malloc(cbSignedMessageBlob*10))) { return false; } //------------------------------------------------------------------- // Get the SignedMessageBlob. if(CryptSignMessage( &SigParams, // Signature parameters FALSE, // Not detached 1, // Number of messages MessageArray, // Messages to be signed MessageSizeArray, // Size of messages tempBuffer, // Buffer for signed message &cbSignedMessageBlob)) // Size of buffer { } else { AfxTrace("%d ", GetLastError()); return false; } memcpy(sgoutData,tempBuffer,cbSignedMessageBlob); sgoutLen+=cbSignedMessageBlob; //------------------------------------------------------------------- // Clean up and free memory. SPError:if(tempBuffer) free(tempBuffer); if(pSignerCert) CertFreeCertificateContext(pSignerCert); CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG); return sdRet; } bool VerifyData(BYTE *vfinData,int vfinLen, BYTE *vfnewData,int vfnewLen) { BYTE *vfin11Data; DWORD vfin11Len; if(! make_hash(vfnewData,vfnewLen, vfin11Data ,vfin11Len)) { return false; } HCRYPTMSG hMsg; DWORD cb3Decoded; BYTE *p3Decoded; // Open a message for decoding. if(!(hMsg = CryptMsgOpenToDecode( MY_ENCODING_TYPE, // Encoding type. 0, // Flags. 0, // Use the default message type. // The message type is // listed in the message header. NULL, // Cryptographic provider. Use NULL // for the default provider. NULL, // Recipient information. NULL))) // Stream information. { return false; } //------------------------------------------------------------------- // Update the message with an encoded BLOB. // Both pbEncodedBlob, the encoded data, // and cbEnclodeBlob, the length of the encoded data, // must be available. if(!(CryptMsgUpdate( hMsg, // Handle to the message vfinData, // Pointer to the encoded BLOB vfinLen, // Size of the encoded BLOB TRUE))) // Last call { return false; } //------------------------------------------------------------------- // Get the number of bytes needed for a buffer // to hold the decoded message. if(!(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index NULL, &cb3Decoded))) // Size of the returned // information. { AfxTrace("%d ", GetLastError()); return false; } //------------------------------------------------------------------- // Allocate memory. if(!(p3Decoded = (BYTE *) malloc(cb3Decoded))) { return false; } //------------------------------------------------------------------- // Copy the content to the buffer. if(!(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index p3Decoded, // Address for returned // information. &cb3Decoded))) // Size of the returned // information. { return false; } if(memcmp(p3Decoded,vfin11Data, min(vfin11Len,cb3Decoded))) { return false; } //------------------------------------------------------------------- // Clean up. if(p3Decoded) free(p3Decoded); if(hMsg) CryptMsgClose(hMsg); return true; }