crm

До семинара в Сочи осталось

  • 9
  • 3
дня

Форум

ГлавнаяПоддержка длинных строк

Поддержка длинных строк

RSS
Поддержка длинных строк
 
Цитата
two_oceans пишет:
Могу понять почему не указан массив - если установить массив более чем из одного элемента компилятор изменит размер структуры, а если объявить как массив из одного элемента (как обычно делается для массива неизвестной длины), то нужно отключать проверку индексов массива при работе со структурой (иначе вылетит исключение). Так что явно придется менять описание структуры.
Есть еще одна мысль, где искать ошибку - возможно в описании еще и перепутаны одноименные A и W функции и на самом деле надо передать Юникод строку (да еще с двойным нулем в качестве завершающего символа).
Насчёт unicode - вряд ли. Он описан как LPSTR *, а не как LPTSTR * или LPWSTR *. Да и функция CertFindCertificateInStore - одна, без A и W версий.
Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.
 
Цитата
Sergey Cheban пишет:
Насчёт unicode - вряд ли.
И это странно, так как функция ищет в том числе и по именам субъекта или издателя, и они могут быть в utf-8 для отображения кириллицы.
Цитата
Sergey Cheban пишет:
Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.
Похоже что так, Паскалевская специфика, а именно "мутный" тип Pchar в который можно присвоить и строковую константу и адрес и нетипизированный указатель (аналог void*), но нельзя типизированный указатель (на какую либо структуру, даже на массив символов). Должен представлять как раз таки указатель на массив символов с нулем в конце. Все должно преобразовываться автоматически, но похоже автоматикой где-то лишний раз берется адрес.

По умолчанию LPSTR в описаниях преобразуется именно в него. Ок, переписал в явных указателях и типах предложенных в статье по ссылке, без изменения описания структуры. Сделал дополнительные функции-обертки, чтобы каждый раз не вспоминать как с ними извращаться, но.. в итоге, ничего не изменилось. Получаю enhkey_usage из cryptoapi и могу его вывести на экран, заношу свое значение и тоже вывожу на экран - все такое же. За исключением того, что для получения память выделяется одним куском (идет структура, указатель в ней указывает на память сразу за ней в которой массив указателей на строки, строки тут же сразу после массива), а в моем заполнении структура в одном куске памяти, массив в другом, строки в третьем. Не находит. Объединил структуру и массив в один кусок - не находит. Уже заполнил все назначения enhkey_usage, которые есть у этого сертификата - не находит. Поставил флаг ИЛИ - не находит. Кажется разбираться с этим - только время терять.

Остается пожалуй еще один вариант - что константа типа поиска перенесена неверно. Навскидку справочное значение не нашлось, в руководствах все по имени, как будет время - поищу значение константы в заголовочном файле для Си. Пока отложил, отрабатываю проверку подписи.
 
Константу проверил A0000 в шестнадцатиричной записи, вроде бы все верно. Странно все это. Попробую освоить поиск сертификата по отпечатку. Для удобства наверно - получить блоб с отпечатком, преобразовать в base64, сохранить. Потом считать, преобразовать обратно и в поиск. Также нашел статью про КриптоПро Capi Lite и там внезапно не поддерживается флаг поиска ИЛИ.
Кстати про отпечаток - у меня вот еще были сомнения какой криптопровайдер нужно указывать при открытии хранилища в CertOpenSystemStore (в пояснении к параметру указано, что он будет использован для вычисления хэша в хранилище), указал КриптоПро. Однако может надо NULL указывать и из-за этого какой-нибудь внутренний поиск по SHA1 хэшу от enhkey_usage не проходит. Сегодня пробую с NULL.

Первая математическая проверка значения самой простой подписи прошла успешно. Столкнулся с 2 моментами - 1) вместо CryptImportKey (выдало, что неверный блоб) пришлось использовать CryptImportPublicKeyInfo. 2) функция декодирования из base64 (стандартная) использовала неявно shortstring, поэтому длина входного текста была ограничена 255 байтами, хотя внутренне кодирование сделано через стримы. На декодирование хэша и подписи это не влияло, а вот сертификат в 3 Кб оказался испорчен (вернулось 189 байт). Опять же сделал переходник с композитной строки на стрим и обратно, для проверки сохранил в файл сертификат до и после. Тут выяснилось, что если из base64 удалить и символы 10 и символы 13, то открыть сертификат не удается, если оставить один из них либо оба - все нормально. Еще перепроверю с чем связано.

По составным частям пока при взятии тега по id один символ пропадает и хэш не сходится. Далее планирую поправить проверку так, чтобы после нее были выполнены приготовления для переподписания (либо замены либо добавления еще одной подписи).
 
За неделю: проверил подписанный файл на техническом портале СМЭВ - там меня обрадовали, что документ соответствует методическим рекомендациям 2.5.5, 2.5.6 и 2.6.0 (на 2.4.x не соответствует), но ЭП органа власти неверна. Подключил самописный модуль каноникализации, увидел, что действительно, был неканоничный вид. Однако и на такой все равно говорит неверная ЭП. Вот такая вот зараза.

Указание NULL (0 с учетом как перенесено на Паскаль) вместо провайдера при открытии хранилища - результат тот же, не находится.

Для разнообразия вчера разбирался с конфигурацией OpenSSL для внутреннего УЦ. Теперь сертификат УЦ гораздо больше похож на корневые сертификаты аккредитованных УЦ. Во-первых, добавил огрн и инн организации - это оказалось довольно просто (пока есть небольшое различие: по приказу ФСБ они NumericString, а у меня вышло UTF8String). Во-вторых, CN написал на русском (этого пришлось увеличить ограничение на длину, так как в UTF8 длина 34 символов вышла около 70 байт, а ограничение по RFC в 64 символа (и OpenSSL его применяет к байтам вместо символов).

В-третьих, разобрался с UTF8 и ASN1 кодированием. Раньше я говорил, что если файл конфигурации в UTF8, то ASN1 кодирование это игнорирует и кодирует второй раз (при этом кодирует как будто символы были в расширенной латинице, то есть и без изначального UTF8 текст с кириллицей портится). Сейчас я разобрался - если текст уже в UTF8, то нужно добавить модификатор формата, выглядит как [code:1kmgknpt]FORMAT:UTF8,UTF8:Строка[/code:1kmgknpt]При этом двойное перекодирование отменяется, но OpenSSL проверяет, что Строка действительно в UTF8 и если нет, то выпадает в ошибку. По этой же теме, сделал соединение целого файла конфигурации из частей, части могут быть как в UTF8, так и в 1251 кодировке. В перспективе хочу доделать HTML Application с динамическим подбором частей под генерацию конкретного сертификата и динамическим подбором параметров openssl для внутреннего УЦ.

В-четвертых, все же получилось закодировать расширение "Сведения о средстве ЭП и УЦ издателя" - для этого потребовалось использовать длинную форму расширения - когда вместо значения указывается SEQUENCE: и ссылка на секцию в файле конфигурации. При этом имена параметров в секции игнорируются, но должны быть различными. Тут заминка оказалась в возмутительном факте, что в стандартном файле конфигурации секции названы вроде [ v3_ca ] - с пробелом до и после названия, прекрасно находятся по указанию v3_ca, однако секцию для расширения нужно называть БЕЗ пробелов, в точности как указано после SEQUENCE: иначе не найдется.

В-пятых, добавил расширения по версии УЦ и хэшу прошлого сертификата. Итого: в корневом сертификате 9 расширений (по результатам сравнения корневых и кросс сертификатов составил список из 12 возможных: у меня отсутствуют ссылка на сертификат УЦ, ссылка на список отзыва и период действия закрытого ключа, так как они не имеют смысла для корневого УЦ). Пока разбирался, еще встретил про встраивание заявления УЦ о политике и встраивание логотипа. С Логотипом правда я пока сертификатов не видел, но интересно попробовать (это уже наверно на подчиненном УЦ).

Также на форме криптопро узнал, что они переписали gost_capi.dll в gostengy.dll (с поддержкой ГОСТ-2012), слепили свою версию OpenSSL 1.1.0 (отключили что еще не поддерживается криптопровайдером, включили TLS 1.2, со стандартным OpenSSL по-прежнему 1.0) и nginx для openssl 1.1.0 - все это предлагают взаимнонастроенное, в одном архиве. Для работы еще и сам криптопро нужен.Пока не пробовал, но интригует, версию собственного УЦ с гост-2012 вероятно попробую сделать на их версии openssl. Там же они слепили версию Хрома 60 с поддержкой ГОСТ.
 
Разбирался выходные с переводами строк: все же, как и предполагалось можно без опасений удалить переводы строк из base64 кодированной подписи или сертификата.
Глюк с порчей сертификата при удалении символов и с кодом 10 и с кодом 13 был из-за другой редкой ситуации - при склейке композитной строки, если требуемая длина данных результата была в точности равна длине выделенного буфера, то проверка на выделение дополнительной памяти не срабатывала. А вот при копировании данных в буфер там резервировалось место на терминирующий символ с кодом 0. Таким образом, 1 символ терялся и портил сертификат. Добавил в проверку буфера учет терминирующего символа и сертификат теперь не портится, попутно выводится сообщение если при склейке сумма длин частей не равна длине результата.
Также немного прояснилось, почему кто-то говорит что только символ 13 запрещен, а кто-то советует убирать символ 10 тоже. Соль в том, что XPath при выборке определенных тегов (для фрагмента) может выбрать только теги, но не выбрать переводы строк между тегами (равно как и прочие "текстовые ноды", а в каноническом представлении внутри самих тегах тоже НЕТ никаких переводов строк). В итоге, когда результат XPath проходит каноникализацию переводов строк вообще не остается и весь текст для хэша/подписи представляет собой одну строку. Получается в каноническом фрагменте документа переводов строки нет, но в канонической форме целого документа символы 10 могут использоваться как переводы строк. Во как.

Следующее разбирательство - насчет неразрывного пробела. Так как канонический вид подразумевает приведение к UTF-8, то явно речь не о символе с кодом 160 (замена символа 160 на пробел ломает кодировку UTF-8), видимо придется смотреть стандарт для уточнения.

Вник в каноникализацию еще глубже, оказалось у моей реализации есть определенные проблемы с ancestor context (контекст предков). Если точнее: с наследованием пространств имен и атрибутов которые были объявлены ДО выбранного в каконикализацию фрагмента. Сами теги погоды не делают, а вот пространства имен и атрибуты (да, я удивился, что атрибуты специального пространства xml: также наследуются) наследуются фрагментом. Например, попробовал получить каконический вид целого тега ds:Signature со ссылкой на сертификат и потребовалось пространство wsse для wsse:Reference. Вручную-то конечно добавил, теперь смотрю как автоматизировать.

Основная проблема, конечно, в последовательности формирования документа - сначала формирую подписываемую часть, потом всю "обертку", то есть на момент подписания контекста предков вообще еще нет. Видимо придется делать некую заготовку обертки и ее передать как контекст. Но это тоже как-то извращенно: ведь для каждого фрагмента приводимого к каноническому нужен свой контекст. Жесть.

Отправлено спустя 16 минуты 29 секунды:
С Openssl сделал для доменного УЦ на алгоритме shaRSA подчиненный УЦ и из последнего выпустил сертификат сервера. По поводу указания инн и огрн как NumericString ничего не нашел - вопросы есть, ответов нет. Однако в одном месте высказали предположение что формат никак не указывается, дескать надо вкомпилить в OpenSSL. Скорее всего, способ все же есть, потому что все равно все строки проходят через кодирование ASN1 и формат должен определяться где-то там, но это опять же надо долго разбираться в исходниках OpenSSL.
 
Чтобы проверить на чем запинается проверка ЭП (там тоже такие умники от безопасности, которые не уточняют какая часть подписи неверна) и каноникализацию позаимствовал ответы, пришедшие по запросам через СМЭВ от федеральных сервисов (заведомо правильные). Отправил их на проверку своей каноникализацией. Как оказалось - в ответах как будто специально сделано неканоничное содержимое (нужно добавлять из контекста предков недостающие объявления пространств имен, в основном soap, wsu, ds, также поднимать или опускать объявления на 1 уровень). А еще сортировать пространства имен нужно все же по имени, а не по адресу (вот и несоответствие стандарту).

С ответом Росреестра трудность возникла с тем, что данные ответа от них в виде base64 кодированного блоба между тегами - естественно, 255 символов shortstring не хватило на такой "текстовый узел", пришлось ставить композитную строку. Налоговая порадовала кириллическими тегами, кириллическими атрибутами и кириллическими значениями, пришлось расширить список допустимых символов. Конечно, надо просто разобраться какие символы еще допустимы по стандарту (предположительно в кавычках допустимо все кроме кавычек). ПФР - просто вынос мозга: все объявления пространств идут на пространство по умолчанию (тут несколько не осилил - сложно отличить 2 пространства у которых имя из пустой строки, но разные адреса) и все по правилам: аж три ЭП. Проверка SignatureValue ответа ПФР не проходила, если убрать совсем символы с кодом 10 из SignedInfo. Поэтому все же пришлось их оставить (это по стандарту, за исключением возможного поведения XPath о котором писал вчера). Сочетания символов 13+10,10+13,13 заменяются на 10, с этим проблем не возникло.

В результате улучшений, буквально только что наконец-то получил сообщение, что ЭП-ОВ корректна на странице проверки подписи XML техпортала СМЭВ. И догадайтесь, куда закралась ошибка, после исправления которой свершилось чудо? Вместо Algorithm было написано Algorihtm. /рукалицо
Обнаружилось после введения проверки на алгоритмы (вообще с прицелом на гост-2012, но пока без него) - с проверочных ответов не было ошибки, а со своего запроса алгоритм не выбрался, пригляделся, а там такое.
 
Итак, разобрался с файлом в котором все объявления пространств идут на пространство по умолчанию. 3 подписи проверяются (были небольшие проблемы с определением какой сертификат к какой подписи - второй и третий сертификат не добавлялись). Казалось бы отлично, но проверка на наличие четвертой вываливается с ошибкой "Недостаточно памяти". В системе-то память есть, но видимо heap закончился.

Глянул сколько памяти и остался в недоумении - после третьей подписи Виндоуз показывает порядка 648 Мб (из них 112 Мб Working Set (в оперативке), остальное в подкачке), мини-менеджер памяти по суммированию выделения и освобождения - 612 Мб (разница в 30 с небольшим Мб вполне может быть на статические переменные и выдедение на иной памяти кроме компзитных строк), сумма размеров по зафиксированным в мини-менеджере адресам - 43 Мб. Как я понимаю, с такими симптомами... утечка в самом мини-менеджере, буду искать. Вчера вроде бы разобрался с неявными присвоениями, но особо ситуация не изменилась.
 
Умудрился сам себя удивить - в мини-менеджере оказалась строка с комментарием "<- утечка памяти здесь" :D Как выяснилось, из-за того, что менеджер определял дублирование буфера при неявном присвоении, то освобождение буфера с дублями было закомментировано "до выяснения". При изменении буфера на новый другого размера, освобождение вызывалось с временной переменной и это тоже считалось как дубль - по факту ничего не освобождалось. Теперь доработал еще одну версию освобождения, в которую можно передать адрес старой переменной и проблема с заменой буфера решилась. Также более-менее разобрался с дублями: при работе программы они теперь корректно освобождаются, но несколько вылезает в конце работы. Начальный размер памяти для считывания XML либо формирования SOAP уменьшил до 5Мб. И освободил отработавшие объекты каноникализации (вот где 1-2 Мб на объект было). В итоге, после третьей подписи менеджер памяти показывает около 10,5 Мб (2 буфера по 5 Мб, 1 по 40Кб и еще 300Кб суммарно в мелких буферах), памяти хватает и проверка корректно завершается.
 
Подправил композитные строки еще раз - теперь при освобождении не нужно указывать адрес старой переменной, есть возможность исправить адрес старой переменной на адрес временной переменной. Дубли теперь определяются как по адресу буфера, так и по адресу переменной - если адрес переменной используется с новым буфером и на прежний буфер не зарегистрировано других переменных делается попытка его освободить. Поэтому добавлено еще одно поле в мини-менеджер: условный тип переменной. Фиксировано значение 1 для композитной строки, при нем работает восстановление переменной. Значение 2 уже потребовалось - чтобы выделять буфер для расширенного использования сертификата.
Необходимость поля связана с тем, что привязке буфера композитной строки к использованию сертификата это считалось как использование переменной с новым буфером и прежний освобождался. Поэтому теперь элемент массива с адресом буфера в расширенном использовании регистрируется в качестве переменной. Естественно такой адрес переменной нельзя использовать для восстановления.
В целом, сейчас утечка памяти в композитных строках и расширенном использовании устранена. После работы программы счетчик строк=0.

Другим важным изменением стало решение вынести некоторые Unit в качестве отдельных независимых библиотек - это должно улучшить процесс обновления для нескольких исполняемых файлов при изменении модулей и добавить некоторую совместимость для других языков программирования (конвенции пока не указаны, так что совместимость минимальна. Также библиотеки много сообщений выводят на консоль, то есть сейчас их нельзя использовать с консольными программами без консоли). Соответственно, будет странно, если в каждой библиотеке будет свой мини-менеджер для композитных строк. Поэтому мини-менеджер тоже вынесен в отдельную библиотеку lstrmem.dll. Конечно, это имеет свои минусы, но они пока не проявились. С остальными функциями работы с композитными строками пока не вышло, так как: 1) для библиотеки требуются функции с уникальными именами, а у меня много в модуле композитных строк много "перегруженных функций", которые имеют одинаковое имя, но разные списки параметров; 2) там еще и предыдущие опробованные типы строк определены, так что дублей имен функций из-за них еще больше. Так что пока часть модуля в единой библиотеке, часть дублируется в каждой. Если подводить под совместимость с другими языками программирования - дублирующую часть нужно сократить до минимума, поэтому все же как-нибудь найду время и разберусь с одинаковыми именами и сделаю еще библиотеку (только для композитных строк, другие строки перенесу в другой модуль).
Дескрипторы теперь тоже в отдельной библиотеке handles2.dll - она предназначена для замены адресов объектов внутри библиотек (как уже обсуждали, передача ссылки на объект между библиотекой и программой, между разными средами программирования проблематична) на номер по которому этот адрес можно найти. Тут тоже желательна единая таблица между библиотекой и программой. поэтому вынесено в отдельную библиотеку.

Первой библиотекой использующей их стала canonic.dll - версия модуля каконикализации в формате библиотеки. Для типовых текстов SOAP уже работает, но до полного соответствия стандарту еще далеко. Размер трех библиотек чуть более 100 Кб без отладочных символов (плюс программа около 900 Кб включая отладочные номера строк), много меньше размера dotNet.

Из нового в библиотеку вошли - возможность делить SOAP на части тегами soap:Header soap:Body, загружать из первой части (до soap:Header включительно) контекст предков для тегов wsse:Security и ds:Signature, вставлять soap:Header если отсутствует, вставлять в soap:Header дополнительную подпись (в начало) и дополнительные данные подписи (в конец). Загрузить контекст предков для подписи внутри Body также возможно, но деление текста пока не реализовано. Добавлено преобразование контекста предков в фиксированный список ключей пространств имен для формирования ЭП (по фиксированным адресам пространств, urn пока не поддерживаются). Если нужные пространства отсутствуют в контексте, то они будут добавлены в контекст с ключами по умолчанию. Планирую еще добавить возможность задания ключей по умолчанию.

Кстати, перечитал примеры в стандарте - все же пространства имен сортируются по ключу, так что я ошибался. Но ошибался не полностью - все интереснее: несмотря на это атрибуты с указанным пространством имен сортируются по адресу пространства!! dash2 У меня пока сортировка атрибутов в том же порядке что и пространств имен, для атрибутов одного пространства нет проблем, но возможно несоответствие стандарту, если будут атрибуты разных пространств.
Также стало яснее с символами в виде &...; - сначала все подобные записи символов переводятся в код в кодировке Юникод (или UTF-8), затем определенные по списку символы преобразуются обратно в &...; (в форму числового шестадцатиричного заглавного кода символа). Пока не реализовал.

Далее предполагается вынесение подписи и взаимодействия по HTTP также в отдельные библиотеки. Возможно также придется поделить unit подписи на части (сертификаты отдельно, взаимодействие с Майкросрофтовским провайдером отдельно) - сейчас получается слишком много кода.
 
За выходной перенес работу с композитными строками в библиотеку. Много заморочек вышло с переименованием функций, в том плане, что переименовал функции, которых было 3, а в интерфейсном модуле (аналог заголовочного файла Си) названия остались те же, в итоге во все три получили адрес совпадающей со старым названием при импорте из библиотеки. Преимущественно с этим разобрался, но еще перепроверю. Текущий статус: 4 библиотеки без отладочных символов + приложение с отладочными 1001 Кб.
 
В четверг придумал новую идею - сделать библиотеку-основу для генерации XML и к ней подключать библиотеки-плагины с описанием определителя адреса сервиса, конкретных сервисов и частей сервисов. Предполагается встроенная поддержка тестового сервиса СМЭВ. Регистрацию плагинов сделал, дело за их перечислением и загрузкой. Количество библиотек явно возрастет. 4 библиотеки без отладочных символов (182 Кб) + приложение с отладочными (825 Кб) = 1007 Кб. Основа для генерации - 90 Кб, не сплюсована, потому что частично дублирует программу.
С длинными строками эпопея продолжается - попробовал подключить FindFirstFileA копированием декларации из модуля windows (так как там все и сразу - много ненужного) - не взлетело, Access Violation. Сначала подумал, что функции ядра не принимают память выделенную процессу, углубился в это и не нашел ничего необычного, через кучу промежуточных вызовов и коррекций размера дело пришло к HeapAlloc(GetProcessHeap(),0,size), то есть используется куча по-умолчанию, а не какая-то другая и приватная. Память из стека или из программы тоже не сработала.
Потом подключил весь модуль windows целиком - взлетело. Путем разбора деталей выяснилось, что все просто - в исходниках модуля windows проставлено stdcall по умолчанию для всех функций, а в декларации каждой отдельной stdcall не написано. В моей программе по умолчанию не stdcall и потому его нужно указывать. Дописал в скопированную строчку stdcall; и тадам - теперь файл читается не вслепую, а с учетом информации о его существовании и размере. Попутно починил и другие скопированные декларации, как ни удивительно, некоторые функции каким-то чудом работали и без этого.
 
За прошедший месяц внес некоторые изменения в схему - вынес в отдельные библиотеки работу с HTTP, алгоритмами ГОСТ и пространствами имен. Подписание тоже вынесено в библиотеку. Суммарно вышло 11 библиотек, при проверке подписи используются 7 из них; 3 отвечают за генерацию; 1 за HTTP. Базовые адреса им назначил разные, теперь смотрю как их по памяти оптимизировать.

Идея с основой для соап и подключаемыми библиотеками тоже в некоторой степени реализована, но еще не до конца, продолжаю менять форму и форматы. На текущий момент предполагается 3-4 уровня надстроек над основой - 1) концентратор сервисов (пространство узлов на которых сервисы совпадают, но могут отличаться по количеству сервисов, например, ГИС ЖКХ и СМЭВ), тут реализуются процедуры адресации и базовые части для всех сервисов одного концентратора; 2) сервис и операция (формирование сервисного тега); 3) подсервис - формирование внутреннего содержания сервисного тега. Естественно будут еще процедуры для формирования повторяющихся в сервисе тегов, но они будут вызываться внутри подсервиса и не регистрирутся. Уровня 3 или 4 пока не ясно - не могу понять стоит ли выделять операцию в отдельный уровень.
Предполагается, что уровни взаимодействуют через основу, в которой регистрируются адреса процедур, поэтому уровни могут быть как в одной библиотеке, так и в разных. Также основа отвечает за базовое формирование конверта SOAP, настройку взаимодействия с адресом сервиса по http и прочие базовые операции (вроде формирования guid). Плюс предполагается функция-комбайин, которая будет принимать указатели на стируктуры параметры для разных уровней, потом собирать из этого XML, вызывая зарегистрированные адреса концентраторов, сервисов и подсервисов.

В ходе проектирования этой структуры пришел к объединению контекста предков и списка ключей частоиспользуемых пространств в 1 структуру (не мог решить что лучше - оставил оба варианта) и набросал процедуры синхронизации частей структуры. С другой стороны, несколько структур поделил из соображений принадлежности к разным уровням.

В плане алгоритмов попробовал проверить подпись для гис жкх и не смог, так как у меня более-менее отлажена эксклюзивная каноникализация, а там - то вообще не указана никакая, то указана не-эксклюзивная. Полистал примеры не-эксклюзивной - по примерам весь контекст предков включается в тег верхнего уровня фрагмента. Не могу понять, что делать если вообще не указана. Оставить без изменений нельзя, потому что тогда во фрагменте нет определения пространств имен (и контекста предков вообще), но по не-эксклюзивной тоже сумма не выходит.
 
За прошедший месяц - не было особо времени на библиотеки, понемногу отлаживал соединение измененной структуры библиотек: тестовый сервис СМЭВ - тело формируется и проверяется правильно, а вот с конвертом замечены странности.

Немного разобрался как FreePascal трассирует стек при ошибках. Теперь при объявлении композитной строки мини-менеджер еще и запрашивает строку (номер строки и имя файла по адресу в фрейме стека, в котором произошло объявление) и записывает ее в контрольную таблицу. Чтобы выводило отладочную информацию нужно чтобы и библиотека строк и библиотека в которой объявление были собраны с отладочной информацией. Если собраны, то просто в конце программы вызываю статистику по оставшимся строкам и вижу где объявлены строки которые "утекли". Имена функций которые задействованы в самом объявлении и объявлении составных типов исключаются (трассировка переходит к вызвавшей их функции).

По другому поводу (для входа в ЕГИССО) попробовал установить Vipnet CSP 4.2 (ЕГИССО видите ли TLS 1.2 требует, а криптопро 3.6 только 1.0 в большинстве случаев дает) - в итоге сломался вход на госзакупки (нарушилась работа криптопро). После попыток настроить на работу с криптопро, снес випнет (госзакупки не починились) и заодно обновился до криптопро 4.0 (тут починились и ЕГИССО тоже заработал). Как и предполагал - обновление с 3.6 на 4.0.9842 (сертифицированную) прошло не очень гладко для библиотеки формирования подписи. Особым шоком стало, что эта версия иногда не возвращает длину записанной строки - передаешь буффер 1024 байт, запрашиваешь, например, оид хэша, криптопро пишет около 20 байт и #0, но длина остается 1024. Пришлось отлавливать #0 у строк. При этом длина бинарных данных, например сертификата (который может содержать #0 в середине), возвращается корректно.
Судя по протоколу изменений позже ошибку исправили, но версия с исправлением еще не сертифицирована.

Стартовая проверка на доступность криптопровайдеров тоже идет странно - на все типы 75,80,81 (доступные в криптопро 4.0) возвращает ошибку "Плохая подпись", хотя там еще и подписи нет, но потом с хэшем и подписью нормально работает.

Отправлено спустя 14 минуты 48 секунды:
Разобрался как получить хэш сертификата (для поиска в хранилище), но пока не искал. Заодно получил идентификатор ключа (хэш от открытого ключа).
#31
0 0
Цитата
two_oceans пишет:
Могу понять почему не указан массив - если установить массив более чем из одного элемента компилятор изменит размер структуры, а если объявить как массив из одного элемента (как обычно делается для массива неизвестной длины), то нужно отключать проверку индексов массива при работе со структурой (иначе вылетит исключение). Так что явно придется менять описание структуры.
Есть еще одна мысль, где искать ошибку - возможно в описании еще и перепутаны одноименные A и W функции и на самом деле надо передать Юникод строку (да еще с двойным нулем в качестве завершающего символа).
Насчёт unicode - вряд ли. Он описан как LPSTR *, а не как LPTSTR * или LPWSTR *. Да и функция CertFindCertificateInStore - одна, без A и W версий.
Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.
#32
0 0
Цитата
Sergey Cheban пишет:
Насчёт unicode - вряд ли.
И это странно, так как функция ищет в том числе и по именам субъекта или издателя, и они могут быть в utf-8 для отображения кириллицы.
Цитата
Sergey Cheban пишет:
Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.
Похоже что так, Паскалевская специфика, а именно "мутный" тип Pchar в который можно присвоить и строковую константу и адрес и нетипизированный указатель (аналог void*), но нельзя типизированный указатель (на какую либо структуру, даже на массив символов). Должен представлять как раз таки указатель на массив символов с нулем в конце. Все должно преобразовываться автоматически, но похоже автоматикой где-то лишний раз берется адрес.

По умолчанию LPSTR в описаниях преобразуется именно в него. Ок, переписал в явных указателях и типах предложенных в статье по ссылке, без изменения описания структуры. Сделал дополнительные функции-обертки, чтобы каждый раз не вспоминать как с ними извращаться, но.. в итоге, ничего не изменилось. Получаю enhkey_usage из cryptoapi и могу его вывести на экран, заношу свое значение и тоже вывожу на экран - все такое же. За исключением того, что для получения память выделяется одним куском (идет структура, указатель в ней указывает на память сразу за ней в которой массив указателей на строки, строки тут же сразу после массива), а в моем заполнении структура в одном куске памяти, массив в другом, строки в третьем. Не находит. Объединил структуру и массив в один кусок - не находит. Уже заполнил все назначения enhkey_usage, которые есть у этого сертификата - не находит. Поставил флаг ИЛИ - не находит. Кажется разбираться с этим - только время терять.

Остается пожалуй еще один вариант - что константа типа поиска перенесена неверно. Навскидку справочное значение не нашлось, в руководствах все по имени, как будет время - поищу значение константы в заголовочном файле для Си. Пока отложил, отрабатываю проверку подписи.
#33
0 0
Константу проверил A0000 в шестнадцатиричной записи, вроде бы все верно. Странно все это. Попробую освоить поиск сертификата по отпечатку. Для удобства наверно - получить блоб с отпечатком, преобразовать в base64, сохранить. Потом считать, преобразовать обратно и в поиск. Также нашел статью про КриптоПро Capi Lite и там внезапно не поддерживается флаг поиска ИЛИ.
Кстати про отпечаток - у меня вот еще были сомнения какой криптопровайдер нужно указывать при открытии хранилища в CertOpenSystemStore (в пояснении к параметру указано, что он будет использован для вычисления хэша в хранилище), указал КриптоПро. Однако может надо NULL указывать и из-за этого какой-нибудь внутренний поиск по SHA1 хэшу от enhkey_usage не проходит. Сегодня пробую с NULL.

Первая математическая проверка значения самой простой подписи прошла успешно. Столкнулся с 2 моментами - 1) вместо CryptImportKey (выдало, что неверный блоб) пришлось использовать CryptImportPublicKeyInfo. 2) функция декодирования из base64 (стандартная) использовала неявно shortstring, поэтому длина входного текста была ограничена 255 байтами, хотя внутренне кодирование сделано через стримы. На декодирование хэша и подписи это не влияло, а вот сертификат в 3 Кб оказался испорчен (вернулось 189 байт). Опять же сделал переходник с композитной строки на стрим и обратно, для проверки сохранил в файл сертификат до и после. Тут выяснилось, что если из base64 удалить и символы 10 и символы 13, то открыть сертификат не удается, если оставить один из них либо оба - все нормально. Еще перепроверю с чем связано.

По составным частям пока при взятии тега по id один символ пропадает и хэш не сходится. Далее планирую поправить проверку так, чтобы после нее были выполнены приготовления для переподписания (либо замены либо добавления еще одной подписи).
#34
0 0
За неделю: проверил подписанный файл на техническом портале СМЭВ - там меня обрадовали, что документ соответствует методическим рекомендациям 2.5.5, 2.5.6 и 2.6.0 (на 2.4.x не соответствует), но ЭП органа власти неверна. Подключил самописный модуль каноникализации, увидел, что действительно, был неканоничный вид. Однако и на такой все равно говорит неверная ЭП. Вот такая вот зараза.

Указание NULL (0 с учетом как перенесено на Паскаль) вместо провайдера при открытии хранилища - результат тот же, не находится.

Для разнообразия вчера разбирался с конфигурацией OpenSSL для внутреннего УЦ. Теперь сертификат УЦ гораздо больше похож на корневые сертификаты аккредитованных УЦ. Во-первых, добавил огрн и инн организации - это оказалось довольно просто (пока есть небольшое различие: по приказу ФСБ они NumericString, а у меня вышло UTF8String). Во-вторых, CN написал на русском (этого пришлось увеличить ограничение на длину, так как в UTF8 длина 34 символов вышла около 70 байт, а ограничение по RFC в 64 символа (и OpenSSL его применяет к байтам вместо символов).

В-третьих, разобрался с UTF8 и ASN1 кодированием. Раньше я говорил, что если файл конфигурации в UTF8, то ASN1 кодирование это игнорирует и кодирует второй раз (при этом кодирует как будто символы были в расширенной латинице, то есть и без изначального UTF8 текст с кириллицей портится). Сейчас я разобрался - если текст уже в UTF8, то нужно добавить модификатор формата, выглядит как [code:1kmgknpt]FORMAT:UTF8,UTF8:Строка[/code:1kmgknpt]При этом двойное перекодирование отменяется, но OpenSSL проверяет, что Строка действительно в UTF8 и если нет, то выпадает в ошибку. По этой же теме, сделал соединение целого файла конфигурации из частей, части могут быть как в UTF8, так и в 1251 кодировке. В перспективе хочу доделать HTML Application с динамическим подбором частей под генерацию конкретного сертификата и динамическим подбором параметров openssl для внутреннего УЦ.

В-четвертых, все же получилось закодировать расширение "Сведения о средстве ЭП и УЦ издателя" - для этого потребовалось использовать длинную форму расширения - когда вместо значения указывается SEQUENCE: и ссылка на секцию в файле конфигурации. При этом имена параметров в секции игнорируются, но должны быть различными. Тут заминка оказалась в возмутительном факте, что в стандартном файле конфигурации секции названы вроде [ v3_ca ] - с пробелом до и после названия, прекрасно находятся по указанию v3_ca, однако секцию для расширения нужно называть БЕЗ пробелов, в точности как указано после SEQUENCE: иначе не найдется.

В-пятых, добавил расширения по версии УЦ и хэшу прошлого сертификата. Итого: в корневом сертификате 9 расширений (по результатам сравнения корневых и кросс сертификатов составил список из 12 возможных: у меня отсутствуют ссылка на сертификат УЦ, ссылка на список отзыва и период действия закрытого ключа, так как они не имеют смысла для корневого УЦ). Пока разбирался, еще встретил про встраивание заявления УЦ о политике и встраивание логотипа. С Логотипом правда я пока сертификатов не видел, но интересно попробовать (это уже наверно на подчиненном УЦ).

Также на форме криптопро узнал, что они переписали gost_capi.dll в gostengy.dll (с поддержкой ГОСТ-2012), слепили свою версию OpenSSL 1.1.0 (отключили что еще не поддерживается криптопровайдером, включили TLS 1.2, со стандартным OpenSSL по-прежнему 1.0) и nginx для openssl 1.1.0 - все это предлагают взаимнонастроенное, в одном архиве. Для работы еще и сам криптопро нужен.Пока не пробовал, но интригует, версию собственного УЦ с гост-2012 вероятно попробую сделать на их версии openssl. Там же они слепили версию Хрома 60 с поддержкой ГОСТ.
#35
0 0
Разбирался выходные с переводами строк: все же, как и предполагалось можно без опасений удалить переводы строк из base64 кодированной подписи или сертификата.
Глюк с порчей сертификата при удалении символов и с кодом 10 и с кодом 13 был из-за другой редкой ситуации - при склейке композитной строки, если требуемая длина данных результата была в точности равна длине выделенного буфера, то проверка на выделение дополнительной памяти не срабатывала. А вот при копировании данных в буфер там резервировалось место на терминирующий символ с кодом 0. Таким образом, 1 символ терялся и портил сертификат. Добавил в проверку буфера учет терминирующего символа и сертификат теперь не портится, попутно выводится сообщение если при склейке сумма длин частей не равна длине результата.
Также немного прояснилось, почему кто-то говорит что только символ 13 запрещен, а кто-то советует убирать символ 10 тоже. Соль в том, что XPath при выборке определенных тегов (для фрагмента) может выбрать только теги, но не выбрать переводы строк между тегами (равно как и прочие "текстовые ноды", а в каноническом представлении внутри самих тегах тоже НЕТ никаких переводов строк). В итоге, когда результат XPath проходит каноникализацию переводов строк вообще не остается и весь текст для хэша/подписи представляет собой одну строку. Получается в каноническом фрагменте документа переводов строки нет, но в канонической форме целого документа символы 10 могут использоваться как переводы строк. Во как.

Следующее разбирательство - насчет неразрывного пробела. Так как канонический вид подразумевает приведение к UTF-8, то явно речь не о символе с кодом 160 (замена символа 160 на пробел ломает кодировку UTF-8), видимо придется смотреть стандарт для уточнения.

Вник в каноникализацию еще глубже, оказалось у моей реализации есть определенные проблемы с ancestor context (контекст предков). Если точнее: с наследованием пространств имен и атрибутов которые были объявлены ДО выбранного в каконикализацию фрагмента. Сами теги погоды не делают, а вот пространства имен и атрибуты (да, я удивился, что атрибуты специального пространства xml: также наследуются) наследуются фрагментом. Например, попробовал получить каконический вид целого тега ds:Signature со ссылкой на сертификат и потребовалось пространство wsse для wsse:Reference. Вручную-то конечно добавил, теперь смотрю как автоматизировать.

Основная проблема, конечно, в последовательности формирования документа - сначала формирую подписываемую часть, потом всю "обертку", то есть на момент подписания контекста предков вообще еще нет. Видимо придется делать некую заготовку обертки и ее передать как контекст. Но это тоже как-то извращенно: ведь для каждого фрагмента приводимого к каноническому нужен свой контекст. Жесть.

Отправлено спустя 16 минуты 29 секунды:
С Openssl сделал для доменного УЦ на алгоритме shaRSA подчиненный УЦ и из последнего выпустил сертификат сервера. По поводу указания инн и огрн как NumericString ничего не нашел - вопросы есть, ответов нет. Однако в одном месте высказали предположение что формат никак не указывается, дескать надо вкомпилить в OpenSSL. Скорее всего, способ все же есть, потому что все равно все строки проходят через кодирование ASN1 и формат должен определяться где-то там, но это опять же надо долго разбираться в исходниках OpenSSL.
#36
0 0
Чтобы проверить на чем запинается проверка ЭП (там тоже такие умники от безопасности, которые не уточняют какая часть подписи неверна) и каноникализацию позаимствовал ответы, пришедшие по запросам через СМЭВ от федеральных сервисов (заведомо правильные). Отправил их на проверку своей каноникализацией. Как оказалось - в ответах как будто специально сделано неканоничное содержимое (нужно добавлять из контекста предков недостающие объявления пространств имен, в основном soap, wsu, ds, также поднимать или опускать объявления на 1 уровень). А еще сортировать пространства имен нужно все же по имени, а не по адресу (вот и несоответствие стандарту).

С ответом Росреестра трудность возникла с тем, что данные ответа от них в виде base64 кодированного блоба между тегами - естественно, 255 символов shortstring не хватило на такой "текстовый узел", пришлось ставить композитную строку. Налоговая порадовала кириллическими тегами, кириллическими атрибутами и кириллическими значениями, пришлось расширить список допустимых символов. Конечно, надо просто разобраться какие символы еще допустимы по стандарту (предположительно в кавычках допустимо все кроме кавычек). ПФР - просто вынос мозга: все объявления пространств идут на пространство по умолчанию (тут несколько не осилил - сложно отличить 2 пространства у которых имя из пустой строки, но разные адреса) и все по правилам: аж три ЭП. Проверка SignatureValue ответа ПФР не проходила, если убрать совсем символы с кодом 10 из SignedInfo. Поэтому все же пришлось их оставить (это по стандарту, за исключением возможного поведения XPath о котором писал вчера). Сочетания символов 13+10,10+13,13 заменяются на 10, с этим проблем не возникло.

В результате улучшений, буквально только что наконец-то получил сообщение, что ЭП-ОВ корректна на странице проверки подписи XML техпортала СМЭВ. И догадайтесь, куда закралась ошибка, после исправления которой свершилось чудо? Вместо Algorithm было написано Algorihtm. /рукалицо
Обнаружилось после введения проверки на алгоритмы (вообще с прицелом на гост-2012, но пока без него) - с проверочных ответов не было ошибки, а со своего запроса алгоритм не выбрался, пригляделся, а там такое.
#37
0 0
Итак, разобрался с файлом в котором все объявления пространств идут на пространство по умолчанию. 3 подписи проверяются (были небольшие проблемы с определением какой сертификат к какой подписи - второй и третий сертификат не добавлялись). Казалось бы отлично, но проверка на наличие четвертой вываливается с ошибкой "Недостаточно памяти". В системе-то память есть, но видимо heap закончился.

Глянул сколько памяти и остался в недоумении - после третьей подписи Виндоуз показывает порядка 648 Мб (из них 112 Мб Working Set (в оперативке), остальное в подкачке), мини-менеджер памяти по суммированию выделения и освобождения - 612 Мб (разница в 30 с небольшим Мб вполне может быть на статические переменные и выдедение на иной памяти кроме компзитных строк), сумма размеров по зафиксированным в мини-менеджере адресам - 43 Мб. Как я понимаю, с такими симптомами... утечка в самом мини-менеджере, буду искать. Вчера вроде бы разобрался с неявными присвоениями, но особо ситуация не изменилась.
#38
0 0
Умудрился сам себя удивить - в мини-менеджере оказалась строка с комментарием "<- утечка памяти здесь" :D Как выяснилось, из-за того, что менеджер определял дублирование буфера при неявном присвоении, то освобождение буфера с дублями было закомментировано "до выяснения". При изменении буфера на новый другого размера, освобождение вызывалось с временной переменной и это тоже считалось как дубль - по факту ничего не освобождалось. Теперь доработал еще одну версию освобождения, в которую можно передать адрес старой переменной и проблема с заменой буфера решилась. Также более-менее разобрался с дублями: при работе программы они теперь корректно освобождаются, но несколько вылезает в конце работы. Начальный размер памяти для считывания XML либо формирования SOAP уменьшил до 5Мб. И освободил отработавшие объекты каноникализации (вот где 1-2 Мб на объект было). В итоге, после третьей подписи менеджер памяти показывает около 10,5 Мб (2 буфера по 5 Мб, 1 по 40Кб и еще 300Кб суммарно в мелких буферах), памяти хватает и проверка корректно завершается.
#39
0 0
Подправил композитные строки еще раз - теперь при освобождении не нужно указывать адрес старой переменной, есть возможность исправить адрес старой переменной на адрес временной переменной. Дубли теперь определяются как по адресу буфера, так и по адресу переменной - если адрес переменной используется с новым буфером и на прежний буфер не зарегистрировано других переменных делается попытка его освободить. Поэтому добавлено еще одно поле в мини-менеджер: условный тип переменной. Фиксировано значение 1 для композитной строки, при нем работает восстановление переменной. Значение 2 уже потребовалось - чтобы выделять буфер для расширенного использования сертификата.
Необходимость поля связана с тем, что привязке буфера композитной строки к использованию сертификата это считалось как использование переменной с новым буфером и прежний освобождался. Поэтому теперь элемент массива с адресом буфера в расширенном использовании регистрируется в качестве переменной. Естественно такой адрес переменной нельзя использовать для восстановления.
В целом, сейчас утечка памяти в композитных строках и расширенном использовании устранена. После работы программы счетчик строк=0.

Другим важным изменением стало решение вынести некоторые Unit в качестве отдельных независимых библиотек - это должно улучшить процесс обновления для нескольких исполняемых файлов при изменении модулей и добавить некоторую совместимость для других языков программирования (конвенции пока не указаны, так что совместимость минимальна. Также библиотеки много сообщений выводят на консоль, то есть сейчас их нельзя использовать с консольными программами без консоли). Соответственно, будет странно, если в каждой библиотеке будет свой мини-менеджер для композитных строк. Поэтому мини-менеджер тоже вынесен в отдельную библиотеку lstrmem.dll. Конечно, это имеет свои минусы, но они пока не проявились. С остальными функциями работы с композитными строками пока не вышло, так как: 1) для библиотеки требуются функции с уникальными именами, а у меня много в модуле композитных строк много "перегруженных функций", которые имеют одинаковое имя, но разные списки параметров; 2) там еще и предыдущие опробованные типы строк определены, так что дублей имен функций из-за них еще больше. Так что пока часть модуля в единой библиотеке, часть дублируется в каждой. Если подводить под совместимость с другими языками программирования - дублирующую часть нужно сократить до минимума, поэтому все же как-нибудь найду время и разберусь с одинаковыми именами и сделаю еще библиотеку (только для композитных строк, другие строки перенесу в другой модуль).
Дескрипторы теперь тоже в отдельной библиотеке handles2.dll - она предназначена для замены адресов объектов внутри библиотек (как уже обсуждали, передача ссылки на объект между библиотекой и программой, между разными средами программирования проблематична) на номер по которому этот адрес можно найти. Тут тоже желательна единая таблица между библиотекой и программой. поэтому вынесено в отдельную библиотеку.

Первой библиотекой использующей их стала canonic.dll - версия модуля каконикализации в формате библиотеки. Для типовых текстов SOAP уже работает, но до полного соответствия стандарту еще далеко. Размер трех библиотек чуть более 100 Кб без отладочных символов (плюс программа около 900 Кб включая отладочные номера строк), много меньше размера dotNet.

Из нового в библиотеку вошли - возможность делить SOAP на части тегами soap:Header soap:Body, загружать из первой части (до soap:Header включительно) контекст предков для тегов wsse:Security и ds:Signature, вставлять soap:Header если отсутствует, вставлять в soap:Header дополнительную подпись (в начало) и дополнительные данные подписи (в конец). Загрузить контекст предков для подписи внутри Body также возможно, но деление текста пока не реализовано. Добавлено преобразование контекста предков в фиксированный список ключей пространств имен для формирования ЭП (по фиксированным адресам пространств, urn пока не поддерживаются). Если нужные пространства отсутствуют в контексте, то они будут добавлены в контекст с ключами по умолчанию. Планирую еще добавить возможность задания ключей по умолчанию.

Кстати, перечитал примеры в стандарте - все же пространства имен сортируются по ключу, так что я ошибался. Но ошибался не полностью - все интереснее: несмотря на это атрибуты с указанным пространством имен сортируются по адресу пространства!! dash2 У меня пока сортировка атрибутов в том же порядке что и пространств имен, для атрибутов одного пространства нет проблем, но возможно несоответствие стандарту, если будут атрибуты разных пространств.
Также стало яснее с символами в виде &...; - сначала все подобные записи символов переводятся в код в кодировке Юникод (или UTF-8), затем определенные по списку символы преобразуются обратно в &...; (в форму числового шестадцатиричного заглавного кода символа). Пока не реализовал.

Далее предполагается вынесение подписи и взаимодействия по HTTP также в отдельные библиотеки. Возможно также придется поделить unit подписи на части (сертификаты отдельно, взаимодействие с Майкросрофтовским провайдером отдельно) - сейчас получается слишком много кода.
#40
0 0
За выходной перенес работу с композитными строками в библиотеку. Много заморочек вышло с переименованием функций, в том плане, что переименовал функции, которых было 3, а в интерфейсном модуле (аналог заголовочного файла Си) названия остались те же, в итоге во все три получили адрес совпадающей со старым названием при импорте из библиотеки. Преимущественно с этим разобрался, но еще перепроверю. Текущий статус: 4 библиотеки без отладочных символов + приложение с отладочными 1001 Кб.
#41
0 0
В четверг придумал новую идею - сделать библиотеку-основу для генерации XML и к ней подключать библиотеки-плагины с описанием определителя адреса сервиса, конкретных сервисов и частей сервисов. Предполагается встроенная поддержка тестового сервиса СМЭВ. Регистрацию плагинов сделал, дело за их перечислением и загрузкой. Количество библиотек явно возрастет. 4 библиотеки без отладочных символов (182 Кб) + приложение с отладочными (825 Кб) = 1007 Кб. Основа для генерации - 90 Кб, не сплюсована, потому что частично дублирует программу.
С длинными строками эпопея продолжается - попробовал подключить FindFirstFileA копированием декларации из модуля windows (так как там все и сразу - много ненужного) - не взлетело, Access Violation. Сначала подумал, что функции ядра не принимают память выделенную процессу, углубился в это и не нашел ничего необычного, через кучу промежуточных вызовов и коррекций размера дело пришло к HeapAlloc(GetProcessHeap(),0,size), то есть используется куча по-умолчанию, а не какая-то другая и приватная. Память из стека или из программы тоже не сработала.
Потом подключил весь модуль windows целиком - взлетело. Путем разбора деталей выяснилось, что все просто - в исходниках модуля windows проставлено stdcall по умолчанию для всех функций, а в декларации каждой отдельной stdcall не написано. В моей программе по умолчанию не stdcall и потому его нужно указывать. Дописал в скопированную строчку stdcall; и тадам - теперь файл читается не вслепую, а с учетом информации о его существовании и размере. Попутно починил и другие скопированные декларации, как ни удивительно, некоторые функции каким-то чудом работали и без этого.
#42
0 0
За прошедший месяц внес некоторые изменения в схему - вынес в отдельные библиотеки работу с HTTP, алгоритмами ГОСТ и пространствами имен. Подписание тоже вынесено в библиотеку. Суммарно вышло 11 библиотек, при проверке подписи используются 7 из них; 3 отвечают за генерацию; 1 за HTTP. Базовые адреса им назначил разные, теперь смотрю как их по памяти оптимизировать.

Идея с основой для соап и подключаемыми библиотеками тоже в некоторой степени реализована, но еще не до конца, продолжаю менять форму и форматы. На текущий момент предполагается 3-4 уровня надстроек над основой - 1) концентратор сервисов (пространство узлов на которых сервисы совпадают, но могут отличаться по количеству сервисов, например, ГИС ЖКХ и СМЭВ), тут реализуются процедуры адресации и базовые части для всех сервисов одного концентратора; 2) сервис и операция (формирование сервисного тега); 3) подсервис - формирование внутреннего содержания сервисного тега. Естественно будут еще процедуры для формирования повторяющихся в сервисе тегов, но они будут вызываться внутри подсервиса и не регистрирутся. Уровня 3 или 4 пока не ясно - не могу понять стоит ли выделять операцию в отдельный уровень.
Предполагается, что уровни взаимодействуют через основу, в которой регистрируются адреса процедур, поэтому уровни могут быть как в одной библиотеке, так и в разных. Также основа отвечает за базовое формирование конверта SOAP, настройку взаимодействия с адресом сервиса по http и прочие базовые операции (вроде формирования guid). Плюс предполагается функция-комбайин, которая будет принимать указатели на стируктуры параметры для разных уровней, потом собирать из этого XML, вызывая зарегистрированные адреса концентраторов, сервисов и подсервисов.

В ходе проектирования этой структуры пришел к объединению контекста предков и списка ключей частоиспользуемых пространств в 1 структуру (не мог решить что лучше - оставил оба варианта) и набросал процедуры синхронизации частей структуры. С другой стороны, несколько структур поделил из соображений принадлежности к разным уровням.

В плане алгоритмов попробовал проверить подпись для гис жкх и не смог, так как у меня более-менее отлажена эксклюзивная каноникализация, а там - то вообще не указана никакая, то указана не-эксклюзивная. Полистал примеры не-эксклюзивной - по примерам весь контекст предков включается в тег верхнего уровня фрагмента. Не могу понять, что делать если вообще не указана. Оставить без изменений нельзя, потому что тогда во фрагменте нет определения пространств имен (и контекста предков вообще), но по не-эксклюзивной тоже сумма не выходит.
#43
0 0
За прошедший месяц - не было особо времени на библиотеки, понемногу отлаживал соединение измененной структуры библиотек: тестовый сервис СМЭВ - тело формируется и проверяется правильно, а вот с конвертом замечены странности.

Немного разобрался как FreePascal трассирует стек при ошибках. Теперь при объявлении композитной строки мини-менеджер еще и запрашивает строку (номер строки и имя файла по адресу в фрейме стека, в котором произошло объявление) и записывает ее в контрольную таблицу. Чтобы выводило отладочную информацию нужно чтобы и библиотека строк и библиотека в которой объявление были собраны с отладочной информацией. Если собраны, то просто в конце программы вызываю статистику по оставшимся строкам и вижу где объявлены строки которые "утекли". Имена функций которые задействованы в самом объявлении и объявлении составных типов исключаются (трассировка переходит к вызвавшей их функции).

По другому поводу (для входа в ЕГИССО) попробовал установить Vipnet CSP 4.2 (ЕГИССО видите ли TLS 1.2 требует, а криптопро 3.6 только 1.0 в большинстве случаев дает) - в итоге сломался вход на госзакупки (нарушилась работа криптопро). После попыток настроить на работу с криптопро, снес випнет (госзакупки не починились) и заодно обновился до криптопро 4.0 (тут починились и ЕГИССО тоже заработал). Как и предполагал - обновление с 3.6 на 4.0.9842 (сертифицированную) прошло не очень гладко для библиотеки формирования подписи. Особым шоком стало, что эта версия иногда не возвращает длину записанной строки - передаешь буффер 1024 байт, запрашиваешь, например, оид хэша, криптопро пишет около 20 байт и #0, но длина остается 1024. Пришлось отлавливать #0 у строк. При этом длина бинарных данных, например сертификата (который может содержать #0 в середине), возвращается корректно.
Судя по протоколу изменений позже ошибку исправили, но версия с исправлением еще не сертифицирована.

Стартовая проверка на доступность криптопровайдеров тоже идет странно - на все типы 75,80,81 (доступные в криптопро 4.0) возвращает ошибку "Плохая подпись", хотя там еще и подписи нет, но потом с хэшем и подписью нормально работает.

Отправлено спустя 14 минуты 48 секунды:
Разобрался как получить хэш сертификата (для поиска в хранилище), но пока не искал. Заодно получил идентификатор ключа (хэш от открытого ключа).
Сейчас на форуме никого нет :(
Сейчас на форуме никого нет :(

Для улучшения работы сайта и его взаимодействие с пользователями мы используем файлы cookie. Продолжая пользоваться сайтом, вы соглашаетесь с использованием файлов cookie. Вы всегда можете отключить файлы cookie в настройках браузера.

Подпишись на рассылку новостей ЖКХ, а также наших статей!

Спасибо, вы успешно подписались на рассылку!