02.07.2007 10:54:04Доподпись сообщения Ответов: 20
Волков
Добовляю подпись к сообщению следующим образом:
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?
 
Ответы:
04.07.2007 16:05:03Kirill Sobolev
Какая ошибка?
05.07.2007 6:33:38Волков
Если ошибку смотреть следующим образом:
fprintf(stderr,"Error number %x.\n",GetLastError());
то ea.
05.07.2007 11:42:24Kirill Sobolev
ERROR_MORE_DATA - слишком маленький размер буфера под возращаемые данные.
09.07.2007 8:52:53Волков
Подписываю сообщение следующим образом:
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 байт должно быть не так?
09.07.2007 11:14:43Kirill Sobolev
Если сертификаты подписчиков разные то вполне нормально
09.07.2007 13:36:11Волков
Если исаользовать один и тот же сертификат для подписи то, при подписи выделяется 992 байта, а для дополнительной подписи 1026айт. После того как функция CryptMsgGetParam отработает с ошибкой параметру (cbMessageBlob) присваивается значение 1206, почему память выделяется неправильно? Если праметру cbMessageBlob присвоить значение 1206 CryptMsgGetParam отрабатывает нормально.
09.07.2007 15:26:53Kirill Sobolev
И это нормально
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.
10.07.2007 13:50:33Волков
Проверяю получившуюся подпись следующим образом:
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.
10.07.2007 14:10:17Kirill Sobolev
Сертификат подписчика не найден, скорее всего.
10.07.2007 14:13:35Волков
А какой сертификат ищет данная функция ведь последний параметр у нее выходной? Когда я проверял одну подпись то у меня функция возвращала сертификат подписчика.
10.07.2007 15:24:07Kirill Sobolev
Ищет тот который указан в подписи номер 0.
Если найдет - его и вернет в последнем параметре.
11.07.2007 8:09:12Волков
При проверке подписей
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, но ведь я добавлял подпись!
11.07.2007 10:08:57Kirill Sobolev
Посмотрите чем-нибудь типа dumpasn1, точно ли там 2 подписи и есть ли нужный сертификат.
11.07.2007 10:13:59Волков
А где можно взять dumpasn1?
11.07.2007 12:28:15Kirill Sobolev
http://www.cryptopro.ru/cryptopro/download/default.asp
11.07.2007 13:16:27Волков
а с каким ключом запускать? чтоб узнать количество подписей?
11.07.2007 13:40:00Kirill Sobolev
Ни с каким, dumpasn1 только приводит ASN.1 к читаемому виду.
Количество придется считать вручную.
11.07.2007 13:50:54Волков
Запускаю эту утилиту следующим образом:
dumpasn1 sign.sgn > test.txt
появляется строка 0 warnings 1058 errors
11.07.2007 15:30:48Kirill Sobolev
sign.sgn дб бинарный а не base64
17.08.2007 17:19:43tibnwdayzo
Hello! Good Site! Thanks you! ngqzuulwcdnctg