| ||||
| ||||
Пытался с помощью примера в lowsign.c, переведенного на Делфи подписать файл размером 4Мб. Для чтения большого файла использую BlockRead(infile, buf, 512);, т.е. читаю блоками по 512 байт. Вот, что делал я: ---------------------------------------- var hProv : HCRYPTPROV; // Дескриптор провайдера pUserCert : PCCERT_CONTEXT; // Сертификат, используемый для формирования ЭЦП keytype : DWORD; // Тип ключа (возвращается) size : DWORD; hMsg : HCRYPTMSG; // Дескриптор сообщения HashAlgorithm : CRYPT_ALGORITHM_IDENTIFIER; // Идентификатор алг-ма хеширования HashAlgSize : DWORD; SignerEncodeInfo : CMSG_SIGNER_ENCODE_INFO; // Структура, описывающая отправителя SignerEncodeInfoArray : array[1..1] of CMSG_SIGNER_ENCODE_INFO; // Массив структур, описывающих отправителя SignerCertBlob : CERT_BLOB; SignerCertBlobArray : array[1..1] of CERT_BLOB; cbEncodedBlob : DWORD; pbEncodedBlob : pbyte; SignedMsgEncodeInfo : CMSG_SIGNED_ENCODE_INFO; // Структура, описывающая подписанное сообщение flags : DWORD; should_release_ctx : boolean; certfile : pchar; ret : PCCERT_CONTEXT; TYPE_DER : DWORD; file_path : string; sign_file_path : string; include : integer; detached : integer; hCertSt : HCERTSTORE; subject : PWideChar; subj : string; cbContent : string; i : word; infile: file; buf: array[0..511] of byte; begin file_path := ’D:\!!\test.txt’; sign_file_path := ’D:\!!\testsign.p7s’; line := ’’; include := 1; // Включать в подпись сертификат подписчика? detached := 1; // ЭЦП отдельна от подписываемого файла. errors := ’’; TYPE_DER := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING; cert_subject := ’SARIT’; OID := szOID_RSA_MD5; CryptAcquireContext(@hProv, NIL, NIL, PROV_RSA_FULL, 0); showmessage(syserrormessage(getlasterror())); hCertSt := CertOpenSystemStore(0, ’MY’); GetMem(subject, 2 * length(cert_subject) + 1); StringToWideChar(cert_subject, subject, 2 * length(cert_subject) + 1); pUserCert := CertFindCertificateInStore ( hCertSt, TYPE_DER, 0, CERT_FIND_SUBJECT_STR, subject, nil ); showmessage(syserrormessage(getlasterror())); // -------------------------------------------------------------------- // Инициализируем структуру алгоритма HashAlgorithm.pszObjId := pansichar(OID); // Идентификатор алгоритма хэша // -------------------------------------------------------------------- // Инициализируем структуру CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo.cbSize := sizeof(CMSG_SIGNER_ENCODE_INFO); SignerEncodeInfo.pCertInfo := pUserCert^.pCertInfo; SignerEncodeInfo.hCryptProv := hProv; SignerEncodeInfo.dwKeySpec := keytype; SignerEncodeInfo.HashAlgorithm := HashAlgorithm; SignerEncodeInfo.pvHashAuxInfo := NIL; // -------------------------------------------------------------------- // Создадим массив отправителей. Сейчас только из одного. SignerEncodeInfoArray[1] := SignerEncodeInfo; // -------------------------------------------------------------------- // Инициализируем структуру CMSG_SIGNED_ENCODE_INFO SignerCertBlob.cbData := pUserCert^.cbCertEncoded; SignerCertBlob.pbData := pUserCert^.pbCertEncoded; SignerCertBlobArray[1] := SignerCertBlob; // -------------------------------------------------------------------- // Инициализируем структуру массив структур CertBlob. SignedMsgEncodeInfo.cbSize := sizeof(CMSG_SIGNED_ENCODE_INFO); SignedMsgEncodeInfo.cSigners := 1; SignedMsgEncodeInfo.rgSigners := @SignerEncodeInfoArray; SignedMsgEncodeInfo.cCertEncoded := include; // Если задан флаг добавления сертификата отправителя if ( include = 1 ) Then SignedMsgEncodeInfo.rgCertEncoded := @SignerCertBlobArray else SignedMsgEncodeInfo.rgCertEncoded := NIL; SignedMsgEncodeInfo.rgCrlEncoded := NIL; if (detached = 1) Then flags := CMSG_DETACHED_FLAG; // -------------------------------------------------------------------- // Определим длину подписанного сообщения cbEncodedBlob := CryptMsgCalculateEncodedLength( TYPE_DER, // Message encoding type flags, // Flags CMSG_SIGNED, // Message type @SignedMsgEncodeInfo, // Pointer to structure NIL, // Inner content object ID mem_len // Size of content ); showmessage(syserrormessage(getlasterror())); pbEncodedBlob := allocmem(cbEncodedBlob); // -------------------------------------------------------------------- // Создадим дескриптор сообщения hMsg := CryptMsgOpenToEncode( TYPE_DER, // Encoding type flags, // Flags (CMSG_DETACHED_FLAG) CMSG_SIGNED, // Message type @SignedMsgEncodeInfo, // Pointer to structure NIL, // Inner content object ID NIL // Stream information (not used) ); showmessage(syserrormessage(getlasterror())); // -------------------------------------------------------------------- // Поместим в сообщение подписываемые данные AssignFile(infile, file_path); reset(infile, 1); while not eof(infile) do begin BlockRead(infile, buf, 512, size); // size=512 постоянно CryptMsgUpdate(hMsg, @buf, size, True); showmessage(syserrormessage(getlasterror())); End; showmessage(syserrormessage(getlasterror())); CloseFile(infile); // -------------------------------------------------------------------- // Вернем подписанное сообщение или только значение ЭЦП, если установлен признак detached if(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index pbEncodedBlob, // Pointer to the blob @cbEncodedBlob) // Size of the blob ) Then errors := errors + ’Message encoded successfully.’ else errors := errors + ’MsgGetParam failed.’; ---------------------------------------- Первый раз вызов CryptMsgUpdate выполняется успешно, последующие вызовы выдают ошибку "Ошибка при обработке криптографического сообщения". Скажите, пожалуйста, что я делаю не так? Спасибо. | ||||
Ответы: | ||||
| ||||
Советую почитать в MSDN описание функции CryptMsgUpdate. Обратите внимание на примечания к этой функции и на ее реакцию на флаг ATTACHED/DETACHED. | ||||
| ||||
Спасибо за совет. Я решил немного формализировать задачу. Мне необходимо подписать файл размером 4 Мб, причем подпись должна быть отдельно от файла(flags := CMSG_DETACHED_FLAG). Из MSDN-а я понял, что ф-ию CryptMsgUpdate необходимо вызывать с fFinal=True ТОЛЬКО при апдейте последним блоком данных. Но в результате функция CryptMsgUpdate уже при первом вызове(с fFinal=False) выдает "Ошибка при обработке криптогр. сообщения". Что делать не знаю... | ||||
| ||||
:) И я не знаю :) Все, программе трындец :) | ||||
| ||||
Да, скорее всего, что так :)))))) | ||||
| ||||
CryptMsgUpdate(hMsg, @buf, size, True); Насколько помню, True - флаг последнего блоа. | ||||
| ||||
Кстати, большие файлы это больше 4 Гб. | ||||
| ||||
Вроде так и делал...:)) Теперь все работает. Спасибо всем! | ||||