22.11.2005 7:48:49Нюансы CryptoAPI… Ответов: 5
Альт
Формирование структуры
CryptDecryptMessagePara : CRYPT_DECRYPT_MESSAGE_PARA;
Для функции CryptDecryptMessage
Размер структуры

CryptDecryptMessagePara.cbSize := SizeOf( CRYPT_DECRYPT_MESSAGE_PARA );

который надо заполнять при указании длины 20 получаем не работающий функционал на Win2k с отваливанием по ошибке E_INVALIDARG
Методом научного тыка вывел, что:

CryptDecryptMessagePara.cbSize := 16; //SizeOf( CRYPT_DECRYPT_MESSAGE_PARA );

Все начинает работать, но сколько это стоило времени при перепроверках всего кода вверх.

Еще пример CryptSignMessage, Retrieving Data of Unknown Length и его последний параметр DWORD* pcbSignedBlob
На отделенных подписях при первом вызове возвращает длину больше, чем на втором и реальная длина подписи именно второе возвращаемое значение.

Может у вас есть список таких композиций для танцев с бубном?
 
Ответы:
22.11.2005 10:34:03Kirill Sobolev
Я бы это назвал "Нюансы паскаля(дельфи) при работе с Windows API (в т.ч. и CryptoAPI)".
Описание структуры:
typedef struct _CRYPT_DECRYPT_MESSAGE_PARA {
DWORD cbSize;
DWORD dwMsgAndCertEncodingType;
DWORD cCertStore;
HCERTSTORE *rghCertStore;

#ifdef CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS
// The above defined, CRYPT_MESSAGE_SILENT_KEYSET_FLAG, can be set to
// suppress UI by the CSP. See CryptAcquireContext’s CRYPT_SILENT
// flag for more details.

DWORD dwFlags;
#endif

} CRYPT_DECRYPT_MESSAGE_PARA, *PCRYPT_DECRYPT_MESSAGE_PARA;

Причем флаг CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS не поддерживается на Win ниже XP/2003. Поэтому на 2000 SizeOf(CRYPT_DECRYPT_MESSAGE_PARA) будет конечно 16.
22.11.2005 15:00:05Альт
Спасибо вам за ответ Кирилл…
Действительно в заголовочном есть информация
#ifdef CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS
Но нет _нигде_ его объявления
Ссылка же на CryptAcquireContext’s CRYPT_SILENT в примечании к которому написано
«Windows Me/98/95 or Internet Explorer 5: This flag is not supported.»
Но версия IE 6.0.2600.0000

В Platform SDK: Cryptography, который идет в поставке январского MSDN 2005
typedef struct _CRYPT_DECRYPT_MESSAGE_PARA {
DWORD cbSize;
DWORD dwMsgAndCertEncodingType;
DWORD cCertStore;
HCERTSTORE* rghCertStore;
DWORD dwFlags;
} CRYPT_DECRYPT_MESSAGE_PARA,
И вот там уже есть примечание Windows 2000, Windows NT, Windows Me/98/95: This flag is not supported о флаге, а не о размере структуры

Пробежался по заголовочному, нашел еще таких:

CMSG_SIGNER_ENCODE_INFO (CMSG_SIGNER_ENCODE_INFO_HAS_CMS_FIELDS)
CMSG_SIGNED_ENCODE_INFO (CMSG_SIGNED_ENCODE_INFO_HAS_CMS_FIELDS)
CMSG_ENVELOPED_ENCODE_INFO (CMSG_ENVELOPED_ENCODE_INFO_HAS_CMS_FIELDS)
CERT_REVOCATION_PARA (CERT_REVOCATION_PARA_HAS_EXTRA_FIELDS)
CERT_CHAIN_PARA (CERT_CHAIN_PARA_HAS_EXTRA_FIELDS)
CERT_CHAIN_FIND_BY_ISSUER_PARA (CERT_CHAIN_FIND_BY_ISSUER_PARA_HAS_EXTRA_FIELDS)
CRYPT_SIGN_MESSAGE_PARA (CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS)

Интересует только последний…

typedef struct _CRYPT_SIGN_MESSAGE_PARA {
DWORD cbSize;
DWORD dwMsgEncodingType;
PCCERT_CONTEXT pSigningCert;
CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
void *pvHashAuxInfo;
DWORD cMsgCert;
PCCERT_CONTEXT *rgpMsgCert;
DWORD cMsgCrl;
PCCRL_CONTEXT *rgpMsgCrl;
DWORD cAuthAttr;
PCRYPT_ATTRIBUTE rgAuthAttr;
DWORD cUnauthAttr;
PCRYPT_ATTRIBUTE rgUnauthAttr;
DWORD dwFlags;
DWORD dwInnerContentType;

#ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS
CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
void *pvHashEncryptionAuxInfo;
#endif
} CRYPT_SIGN_MESSAGE_PARA, *PCRYPT_SIGN_MESSAGE_PARA;

получается, что и его структуру тоже надо обрезать? По ifdef?
Откуда у вас информация по CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS? Самый свежий Platform SDK? Или есть другой источник?
22.11.2005 15:59:02Kirill Sobolev
Конечно надо.
А в MSDN действительно про это ничего нет...
Инфа была из wincrypt.h
22.11.2005 16:26:14Альт
Проверил... подписывает и с полной структурой, но все равно обрезал оба типа.

{.$define CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS}
type
PCRYPT_DECRYPT_MESSAGE_PARA = ^CRYPT_DECRYPT_MESSAGE_PARA;
CRYPT_DECRYPT_MESSAGE_PARA = record
cbSize :DWORD;
dwMsgAndCertEncodingType :DWORD;
cCertStore : DWORD;
rghCertStore : PHCERTSTORE;
{$ifdef CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS}
dwFlags : DWORD;
{$endif}
end;

--------

{.$define CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS}

type
PCRYPT_SIGN_MESSAGE_PARA = ^CRYPT_SIGN_MESSAGE_PARA;
CRYPT_SIGN_MESSAGE_PARA = record
cbSize :DWORD;
dwMsgEncodingType :DWORD;
pSigningCert :PCCERT_CONTEXT;
HashAlgorithm :CRYPT_ALGORITHM_IDENTIFIER;
pvHashAuxInfo :PVOID;
cMsgCert :DWORD;
rgpMsgCert : PPCCERT_CONTEXT;
cMsgCrl : DWORD;
rgpMsgCrl : PPCCRL_CONTEXT;
cAuthAttr :DWORD;
rgAuthAttr :PCRYPT_ATTRIBUTE;
cUnauthAttr :DWORD;
rgUnauthAttr :PCRYPT_ATTRIBUTE;
dwFlags :DWORD;
dwInnerContentType :DWORD;
{$ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS}
HashEncryptionAlgorithm : CRYPT_ALGORITHM_IDENTIFIER;
pvHashEncryptionAuxInfo : DWORD;
{$endif}
end;

Спасибо вам большое за пояснение, при всей не любви к паскалю. За что платят... на том и пишем. Авось кому еще пригодится
22.11.2005 16:33:11Kirill Sobolev
Пожалуйста.
По идее должно работать и так и так.
Просто в 1м случае Вы CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS не определили, а размер структуры указали наоборот - с полем dwFlags. Вот функция и полезла туда где ей делать нечего )))