| ||||
| ||||
Добовляю подпись к сообщению следующим образом: 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"); } Почему функция CryptMsgGetParam не отрабатывает с параметром CMSG_ENCODED_MESSAGE? | ||||
Ответы: | ||||
| ||||
Какая ошибка? | ||||
| ||||
Если ошибку смотреть следующим образом: fprintf(stderr,"Error number %x.\n",GetLastError()); то ea. | ||||
| ||||
ERROR_MORE_DATA - слишком маленький размер буфера под возращаемые данные. | ||||
| ||||
Подписываю сообщение следующим образом: 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."); } Подпись проверяется все в порядке. Далле доподписываю сообщение: 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; } Количество байт выделяемое при подписи равно 992 байта, а при доподписи 966 байт должно быть не так? | ||||
| ||||
Если сертификаты подписчиков разные то вполне нормально | ||||
| ||||
Если исаользовать один и тот же сертификат для подписи то, при подписи выделяется 992 байта, а для дополнительной подписи 1026айт. После того как функция CryptMsgGetParam отработает с ошибкой параметру (cbMessageBlob) присваивается значение 1206, почему память выделяется неправильно? Если праметру cbMessageBlob присвоить значение 1206 CryptMsgGetParam отрабатывает нормально. | ||||
| ||||
И это нормально MSDN pvData: 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. | ||||
| ||||
Проверяю получившуюся подпись следующим образом: 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; char NameString[256]; PCCERT_CONTEXT pTestCer; while(CryptVerifyDetachedMessageSignature( &msgPara, 0, pbMessageBlob,//pbArray,//pbEncodedBlob, cbMessageBlob,//cbArray,//cbEncodedBlob, 1, &pbContent, &cbContent, &pTestCer)) { printf("The Signature verified.\n"); } Данная функция выполняется с ошибкой 80092004. | ||||
| ||||
Сертификат подписчика не найден, скорее всего. | ||||
| ||||
А какой сертификат ищет данная функция ведь последний параметр у нее выходной? Когда я проверял одну подпись то у меня функция возвращала сертификат подписчика. | ||||
| ||||
Ищет тот который указан в подписи номер 0. Если найдет - его и вернет в последнем параметре. | ||||
| ||||
При проверке подписей CryptVerifyDetachedMessageSignature( &msgPara, 1, pbMessageBlob, cbMessageBlob, 1, &pbContent, &cbContent, &pTestCer) [/code] проверяется только первая если индекс равен 1, если его сделать равным 0 то функция отработает с ошибкой 80092004 Object or property not found, если больше еденицы то 8009200e The signed message doesn't have a signer for the specified signer index, но ведь я добавлял подпись! | ||||
| ||||
Посмотрите чем-нибудь типа dumpasn1, точно ли там 2 подписи и есть ли нужный сертификат. | ||||
| ||||
А где можно взять dumpasn1? | ||||
| ||||
http://www.cryptopro.ru/cryptopro/download/default.asp | ||||
| ||||
а с каким ключом запускать? чтоб узнать количество подписей? | ||||
| ||||
Ни с каким, dumpasn1 только приводит ASN.1 к читаемому виду. Количество придется считать вручную. | ||||
| ||||
Запускаю эту утилиту следующим образом: dumpasn1 sign.sgn > test.txt появляется строка 0 warnings 1058 errors | ||||
| ||||
sign.sgn дб бинарный а не base64 | ||||
| ||||
Hello! Good Site! Thanks you! ngqzuulwcdnctg | ||||