Кто-нибудь занимался вопросом множественной подписи с использованием CryptoAPI? Помогите разобраться, подписываю и дописываю сообщение следующим образом: Код (Text): DWORD cbContent; HCRYPTPROV hCryptProv; HCERTSTORE hStoreHandle; PCCERT_CONTEXT pSignerCert; 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; DWORD cbMessageBlob; BYTE* pbEncodedBlob; BYTE* pbMessageBlob; HCRYPTMSG hMsg; HCRYPTMSG cryptMsg; DWORD dwKeySpec; CRYPT_VERIFY_MESSAGE_PARA msgPara; const BYTE* pbContent = (BYTE*)"Test Message."; cbContent = strlen((char *) pbContent)+1; //îòêðûâàåì õðàíèëèùå MY 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."); } //ïîëó÷àåì êîíòåêñò ñåðòèôèêàòà êîòîðûì áóäåì ïîäïèñûâàòü pSignerCert = CertFindCertificateInStore( hStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, SIGNER_NAME, NULL); if (!pSignerCert) { MyHandleError("Cert not found.\n"); } //ïîëó÷åíèå äåñêðèïòîðà çàêðûòîãî êëþ÷à 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; SignerEncodeInfoArray[0] = SignerEncodeInfo; SignerCertBlob.cbData = pSignerCert->cbCertEncoded; SignerCertBlob.pbData = pSignerCert->pbCertEncoded; 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; 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."); } if(!(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob))) { MyHandleError("Malloc operation failed."); } //---------------------------------------------------------------- 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."); } if(!(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob))) { MyHandleError("Malloc operation failed."); } //---------------------------------------------------------------- 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"); } if(!(CryptMsgUpdate( hMsg, // Handle to the message pbContent, // Pointer to the content cbContent, // Size of the content TRUE))) // Last call { MyHandleError("MsgUpdate failed"); } 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."); } print_signature("C:\\sign",cbEncodedBlob, pbEncodedBlob); CryptReleaseContext(hCryptProv, 0); //------------------------------------------------------------- //äîáàâëÿåì åùå îäíó ïîäïèñü //------------------------------------------------------------- DWORD Spec; HCRYPTPROV hProv; PCCERT_CONTEXT pSecondSigner=NULL; CMSG_SIGNER_ENCODE_INFO CmsgSignerEncodeInfo; CMSG_SIGNER_ENCODE_INFO CmsgSignerEncodeInfoArray[1]; CERT_BLOB CertBlob; CERT_BLOB CertBlobArray[1]; CMSG_SIGNED_ENCODE_INFO CmsgSignedEncodeInfo; pSecondSigner = CertFindCertificateInStore( hStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, SIGNER_NAME1, NULL); if (!pSecondSigner) { MyHandleError("Cert not found.\n"); } if(!(CryptAcquireCertificatePrivateKey( pSecondSigner, 0, NULL, &hProv, &Spec, NULL))) { MyHandleError("CryptAcquireContext failed"); } memset(&CmsgSignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO)); CmsgSignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO); CmsgSignerEncodeInfo.pCertInfo = pSecondSigner->pCertInfo; CmsgSignerEncodeInfo.hCryptProv = hProv; CmsgSignerEncodeInfo.dwKeySpec = dwKeySpec; CmsgSignerEncodeInfo.HashAlgorithm.pszObjId = szOID_RSA_MD5; CmsgSignerEncodeInfo.pvHashAuxInfo = NULL; CmsgSignerEncodeInfoArray[0] = CmsgSignerEncodeInfo; CertBlob.cbData = pSecondSigner->cbCertEncoded; CertBlob.pbData = pSecondSigner->pbCertEncoded; CertBlobArray[0] = CertBlob; memset(&CmsgSignedEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO)); CmsgSignedEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO); CmsgSignedEncodeInfo.cSigners = 1; CmsgSignedEncodeInfo.rgSigners = CmsgSignerEncodeInfoArray; CmsgSignedEncodeInfo.cCertEncoded = 1; CmsgSignedEncodeInfo.rgCertEncoded = CertBlobArray; if(!(cbMessageBlob = CryptMsgCalculateEncodedLength( MY_ENCODING_TYPE, // Message encoding type 0, // Flags CMSG_SIGNED, // Message type &CmsgSignedEncodeInfo, // Pointer to structure NULL, // Inner content OID cbContent))) // Size of content { MyHandleError("Getting cbEncodedBlob length failed."); } if(!(pbMessageBlob = (BYTE *) malloc(cbMessageBlob))) { MyHandleError("Malloc operation failed."); } cryptMsg = CryptMsgOpenToDecode( MY_ENCODING_TYPE, CMSG_DETACHED_FLAG, 0, NULL, NULL, NULL); if (!CryptMsgUpdate( cryptMsg, pbEncodedBlob, cbEncodedBlob, TRUE)) { printf("Error CryptMsgUpdate with encoded"); } if (!CryptMsgControl( cryptMsg, 0, CMSG_CTRL_ADD_SIGNER, &CmsgSignerEncodeInfo)) { printf("Error CryptMsgControl"); } if (!CryptMsgGetParam( cryptMsg, CMSG_ENCODED_MESSAGE, 0, pbMessageBlob, &cbMessageBlob)) { printf("CryptMsgGetParam failed"); DWORD i=GetLastError(); return 0; } CryptMsgClose(hMsg); CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG); CryptReleaseContext(hCryptProv, 0); Но функция CryptMsgGetParam отрабатывает с ошибкой ERROR_MORE_DATA - слишком маленький размер буфера под возращаемые данные. Что делаю не так?
так сначала нужно получить желаемый размер буфера, а потом уже этот буфер использовать! см. описание CryptMsgGetParam в MSDN, там как раз этот вопрос рассмотрен/ фактически ты вызываешь ф-цию два раза: сначала для выяснения размера буфера, а потом собсно по делу
Создал вторую подпись для сообщения, но при проверке Код (Text): CryptVerifyDetachedMessageSignature( &msgPara, 1, pbMessageBlob, cbMessageBlob, 1, &pbContent, &cbContent, &pTestCer) проверяется только первая если индекс равен 1, если его сделать равным 0 то функция отработает с ошибкой 80092004 Object or property not found, если больше еденицы то 8009200e The signed message doesn't have a signer for the specified signer index, но ведь я добавлял подпись!