Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
|
Re: Подпись XML (СМЭВ) | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Ну вот, и с массивами почти что разобрался Для массива строк вполне подойдёт этот код (т.к. такой массив на самом деле это массив указателей на строки - сам массив - это "строка" lqBinArray и есть - lhBuffer это дополнительная память, где хранятся сами строки на которые и идут ссылки из массива). Он правда делает массив ASCIIZ строк - если понадобится юникод то придётся чуток "допилить". Он же в принципе применим и для массива указателей на структуры - ну за тем небольшим нюансом, что для структур не нужен нуль-терминатор, впрочем, лишний нулевой байтик в памяти не смертелен.
А для масива структур или массива чисел нужно просто понять, что в Си массив это расположенные в памяти друг за другом элементы - т.е. для DWORD[] это будет
Только не путай маcсив структур (или простых типов - например чисел) с массивом указателей на структуры (простые типы). ------------------ WBR, Igor |
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
С учетом изложенного выше, получается, что если функция CertFindCertificateInStore возвращает некий контекст сертификата pCertContext, соответствующий структуре CERT_CONTEXT (вернее ссылку на него, поскольку pCertContext=1821504), то при условии использования только лишь данного контекста, я должен заполнять 3-ий и 7-ой элементы структуры CRYPT_SIGN_MESSAGE_PARA для последующего обращения к функции CryptSignMessage одинаковым значением:
3-ий элемент структуры CRYPT_SIGN_MESSAGE_PARA: "PCCERT_CONTEXT pSigningCert;" определен в MSDN как указатель на структуру CERT_CONTEXT, которая будет использована при подписывании, а 7-ой элемент структуры CRYPT_SIGN_MESSAGE_PARA: "PCCERT_CONTEXT *rgpMsgCert;" определен как массив указателей на структуры CERT_CONTEXT, которые должны быть включены в подписываемое сообщение. Ещё цитата без перевода: If the pSigningCert is to be included, a pointer to it must be in the rgpMsgCert array. Парадоксально, но на языке Си эти элементы заполняются разными значениями:
Исправлено 2 раз(а). Последнее : rvc44, 17.07.12 13:17 |
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
Переделал, с учетом всех выясненных новых обстоятельств, но электронная подпись пока что по-прежнему не формируется. Произведенные изменения в коде:
1. Поменял в декларации функции CryptSignMessage некоторые типы параметров:
2. Поменял код для формирования 4-го и 5-го параметров функции CryptSignMessage, с учетом процедуры VFP2BinArray, код которой приведен в одном из предыдущих постов:
3. Поменял lcOID со значения '1.2.643.2.2.3' на значение '1.2.643.2.2.9' по совету, приведенному в теме "Получение цифровой подписи алгоритмом GOST3411(C# по средством invoke)", по ссылке: www.crypto-pro.ru 4. В отладчике видно, что при первом вызове CryptSignMessage для запроса размера подписи - возвращается нулевой размер, значит какие-то параметры (значения всех их приведены на прилагаемом рисунке) указаны по-прежнему неверно! Может ли быть такой эффект из-за передачи в API-функцию из VFP вместо true значения 1? [attachment 13810 SignTrace.jpg] |
Re: Подпись XML (СМЭВ) | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Указатель а не ссылка. По простому - адрес в памяти. Нет. В первом случае требуется просто указатель на структуру (и тут ты правильно всё делаешь), а во втором - массив. Массив в данном случае определяется как указатель (адрес) на начало области памяти, где хранятся элементы массива. Элементами же ЭТОГО массива являются в свою очередь указатели на структуры. Т.е. ты должен явно выделить память под массив (если там всего 1 элемент - то хватит 4-х байт) записать в ЭТУ память BINTOC(pCertContext,"4RS"), а в саму структуру записать адрес этого блока памяти. Если бы фокс не занимался управлением памятью, то можно было бы поступить примерно так: lqArray = BINTOC(pCertContext,"4RS") lqCRYPT_SIGN_MESSAGE_PARA = ... + BINTOC(адрес_lqArray_в_памяти) + ... Но фокс не даёт получить адрес переменной (и правильно делает, т.к. он может её спокойно переместить в другое место в самый неожиданный момент!), потому придётся использовать *Alloc. При том MSDN советует Heap* функции использовать, а не Local*/Global*. Это логично. Они ДОЛЖНЫ быть разными. Вот pSigningCert и один из элементов массива могут содержать одинаковое значение - ссылку на один и тот же контекст. Более того, если бы у тебя был настоящий сишный указатель (а он есть переменная - т.е. 4 (или 8 для x64 систем) байта хранящие адрес), то можно было бы в качестве "массива" использовать указатель на этот самый указатель - что и делается в примере из MSDN-а - там берётся именно "адрес указателя". В твоём же примере наоборот - в первом случае идёт обращение к первому элементу массива (берётся значение элемента с индексом 0), а во втором - просто передаётся указатель на сам массив (берётся адрес элемента с индексом 0 - это и есть сам массив). VFP2BinArray - возвращает сам массив, а не указатель на него. Если есть параметр функции - массив, то можно через STRING@ эту "строку" ему и скормить. Если же это член структуры, то надо эту строку засунуть в "настоящий" блок памяти (не перемещаемый фоксом, как обычная строка), а в структуру поместить указатель (адрес этого блока). ------------------ WBR, Igor |
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
Наконец-то электронно-цифровая подпись (ЭЦП) стала генерироваться из VFP без применения всяких DLL/FLL! Ключом к решению была последняя консультация Игоря, за что ему безмерно благодарен. Теперь осталось написать еще проверку ЭЦП. Размер буфера в байтах при первом обращении к функции CryptSignMessage возвращается 2314, а не 256! При втором, размер почему-то уменьшается до 2298 байт. Сейчас потестирую, чтобы выяснить, будет ли изменяться данный размер при подписании других документов и от чего это зависит?
P.S. Если сразу не выставить нужный размер буфера в 2314 байт, то функция CryptSignMessage будет вызываться дважды, причем каждый раз при обращении к ней будет появляться окно ввода пароля (PINа): [attachment 13811 InputPIN.JPG] Первый раз, даже может показаться, что был введен неверный PIN, однако, это не так. |
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
Добрый день. Недавно заинтересовала тема ЭЦП в VFP. К сожалению у меня так и не получилось подписать файл ЭЦП,
CryptSignMessage(@SignPara, 1, 1, @DataArray, @SizeArray, @m.lcSignature, @m.lnLen)все равно выдает оба раза 0. |
Re: Подпись XML (СМЭВ) | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Первый вызов должен вместо параметра @m.lcSignature содержать NULL (не указывать на пустую строку - она хоть и пустая, но вполне себе "адрес в памяти"! Если бы там был INTEGER - т.е. непосредственно адрес, то можно было бы прописать 0) - и при том САМ вызов по идее должен завершиться успешно (вернуть <> 0, а в переменную m.lnLen записать требуемый размер буфера - который уже следует применить для второго вызова).
------------------ WBR, Igor |
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
В принципе я так и делала.
If CryptSignMessage(@SignPara, .T., 1, @lqDataArray, @lqDwordArray, .Null.,@m.lnLen) = 0 lnLen = 256 lcSignature = Replicate(Chr(0), m.lnLen) If CryptSignMessage(@SignPara, 1, 1, @lqDataArray, @lqDwordArray, @m.lcSignature, @m.lnLen) = 0 =Messagebox("ЭЦП не была сгенерирована!",16,"Ошибка") lDSig = .F. Endif Endif Но я не поняла почему после первого вызова CryptSignMessage(@SignPara, .T., 1, @lqDataArray, @lqDwordArray, .Null.,@m.lnLen) стала m.lnLen = 0, но во второй раз CryptSignMessage(@SignPara, 1, 1, @lqDataArray, @lqDwordArray, @m.lcSignature, @m.lnLen) = 0. |
Re: Подпись XML (СМЭВ) | |
---|---|
Igor Korolyov Сообщений: 34580 Дата регистрации: 28.05.2002 |
Первый вызов должен по идее завершаться <> 0 - если 0 то через GetLastError надо изучать что за ошибка. При ошибке этот вызов, очевидно, и не меняет содержимое переменой - вот она и остаётся 0.
------------------ WBR, Igor |
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
2vahromeeva-ov
Начнем с того, что Вы собираетесь подписывать и в каком формате? Если Вам нужна подпись XML-запроса в СМЭВ в формате XMLDSig, то используйте вместо CryptSignMessage другую API-функцию, а именно: CryptSignHash c параметром AT_KEYEXCHANGE. Последовательность вызовов такова: 1. Открываем системное хранилище сертификатов - CertOpenStore 2. Ищем нужный сертификат по его CN в хранилище - CertFindCertificateInStore (Сертификат должен быть установлен в системе, а закрытый ключ связан с ним и находиться на флэшке или установлен в считыватель "Реестр" с помощью КриптоПро CSP) 2.5 (необязательный шаг) Можно получить CertOID, а по нему AlgId, который указывается 2-м параметром при вызове функции CryptCreateHash (альтернатива - указать его явно) 3. Получаем информацию о ключе - CertGetCertificateContextProperty 4. Подключаемся к криптопровайдеру с нужным контейнером - CryptAcquireContextA 5. Вводим ПИН код контейнера (указатель на байтовую ASCIIZ-строку) - CryptSetProvParam (если опустить данный шаг, то PIN-код будет запрашиваться всякий раз при подписании, что неудобно) 6. Получаем ключ пользователя (для последующего вызова CryptVerifySignature для проверки ЭЦП) - CryptGetUserKey 7. Создаем объект функции хеширования, который использует алгоритм хэширования CALG_GR3411 по ГОСТ Р 34.11-94 криптопровайдера КриптоПро CSP - CryptCreateHash 8. Копируем параметр HP_OID в lcHash - CryptGetHashParam 9. Получаем, на основе каких параметров работает провайдер - CryptGetHashParam (должна быть строка: "1.2.643.2.2.30.1") 10. Добавляем данные к созданному хэш-объекту hHash - CryptHashData 11. Получаем размер хэша - CryptGetHashParam (Размер хэша по алгоритму ГОСТ Р 34.11-94 составляет 32 байта) 12. На этом шаге можно преобразовать хэш в 16-ричный формат (если надо) и/или в формат Base64 (StrConv(m.lcHash, 13)) 13. Подписываем ПОЛУЧЕННЫЙ ХЭШ - CryptSignHash(..., AT_KEYEXCHANGE, ...) а не сам XML-документ (!) 14. На этом шаге можно преобразовать полученную сигнатуру в 16-ричный формат (если надо) и/или в формат Base64 15. Проверяем ЭЦП (сигнатуру) - CryptVerifySignature. Учтите, что при подписании одних и тех же данных несколько раз, все полученные подписи будут различными! 16. CryptDestroyHash 17. CryptReleaseContext 18. CertFreeCertificateContext 19. CertCloseStore Вот, собственно, и всё! Только в Росреестр подпись нужна несколько в другом формате PKCS#7 да плюс ещё с вполне определенными OID'ами, регламентированными документами на их сайте (ЭЦП во внешнем /отдельном/ файле). Сервис в какое ведомство и с каким SID вы пытаетесь реализовать? Исправлено 2 раз(а). Последнее : rvc44, 13.11.12 08:49 |
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
Я реализовываю подпись для взаимодействия с Росреестром.
Что в результате вы изменили и у вас сформировалась подпись? |
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
ура! кажется получилось сформировать подпись! Спасибо за ответы на вопросы.
|
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
С Россреестром на самом деле не так-то всё и просто! Помимо ведомственной ЭП (ЭП информационной системы) там раньше было обязательное (!) наличие второй ЭП для сотрудника ведомства!
А с заморочками с введенными обязательными OID'ами как проблему решила? Лично у меня складывается впечатление, что Росреестр - единственная контора, которая не смотря на общие правила предприняла все усилия, чтобы межведомственные запросы им слали как можно меньше организаций, отступив от всех мыслимых стандартов и методических рекомендаций СМЭВ. |
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
На самом деле мы только в начале пути, пока отрабатываем возможности, а росреестр "мутный" и не понятно вообще что им нужно, у них сейчас очередные изменения в работе, поэтому пока просто разрабатываем возможность эцп в том числе.
|
Re: Подпись XML (СМЭВ) | |
---|---|
vahromeeva-ov Сообщений: 27 Дата регистрации: 19.08.2009 |
Удалось ли кому-нибудь средствами VFP при помощи Crypto API Крипто-Про проверить подписанный ЭЦП
XML-файл? DECLARE INTEGER CryptVerifyDetachedMessageSignature IN crypt32; STRING @ pVerifyPara,; INTEGER dwSignerIndex,; STRING @ pbDetachedSignedBlob,; long @ cbDetachedSignedBlob,; INTEGER cToBeSigned,; STRING @ rgpbToBeSigned,; && [] string @ rgcbToBeSigned,; &&[] STRING @ ppSignerCert lnLen1 = 84 pVerifyPara = BinToC(lnLen1,"4RS") +; && Size of this structure in bytes BinToC(Bitor(PKCS_7_ASN_ENCODING, X509_ASN_ENCODING),"4RS") +; && Type of encoding used Replicate(Chr(0), 12) If CryptVerifyDetachedMessageSignature(@pVerifyPara, 0,@m.lcSignature, @m.lnLen , 1, @lqDataArray, @lqDwordArray, .null.)! =0 =Messagebox("Проверка прошла успешно!",64,"Сообщение") Endif |
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
Привожу полностью рабочий код из своего рабочего приложения. Возможно, данный код кому-то пригодится и сильно облегчит жизнь, но имейте ввиду, что его придется дополнить определением некоторых значений констант и переменных!
|
Re: Подпись XML (СМЭВ) | |
---|---|
rvc44 Автор Сообщений: 2211 Откуда: Тамбов Дата регистрации: 06.12.2005 |
Оказывается, для выбора сертификата, установленного в систему, можно использовать также стандартный Windows-диалог, как описано в MSDN: msdn.microsoft.com
Но использование данного способа завязано на использование библиотеки .NET Framework. Думаю, что при большом желании, его можно "прикрутить" через какой-нибудь wrapper типа VistaDialogs4COM.dll и VistaBridgeLibrary.DLL, которые позволяют работать из Visual FoxPro с .NET Framework: [attachment 24776 WinCertSelectDialog.jpg] |
Re: Подпись XML (СМЭВ) | |
---|---|
Рома Сообщений: 1079 Дата регистрации: 06.06.2001 |
|
Re: Подпись XML (СМЭВ) | |
---|---|
S-type Сообщений: 2969 Дата регистрации: 24.04.2004 |
и функций (например CertNameToStr). Могу сказать - работа проделана просто колоссальная. |
© 2000-2024 Fox Club  |