CRM-система для УК и ТСЖ

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

Будете спамить рекламой - будем нещадно банить)))
Сообщение
Автор
Sergey Cheban
Стажер
Сообщений: 112
Зарегистрирован: 05 ноя 2016, 07:45
Благодарил (а): 55 раза
Поблагодарили: 60 раза

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

#31 Сообщение Sergey Cheban » 22 авг 2017, 12:56

two_oceans писал(а):Могу понять почему не указан массив - если установить массив более чем из одного элемента компилятор изменит размер структуры, а если объявить как массив из одного элемента (как обычно делается для массива неизвестной длины), то нужно отключать проверку индексов массива при работе со структурой (иначе вылетит исключение). Так что явно придется менять описание структуры.
Есть еще одна мысль, где искать ошибку - возможно в описании еще и перепутаны одноименные A и W функции и на самом деле надо передать Юникод строку (да еще с двойным нулем в качестве завершающего символа).

Насчёт unicode - вряд ли. Он описан как LPSTR *, а не как LPTSTR * или LPWSTR *. Да и функция CertFindCertificateInStore - одна, без A и W версий.
Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#32 Сообщение two_oceans » 23 авг 2017, 13:00

Sergey Cheban писал(а):Источник цитаты Насчёт unicode - вряд ли.
И это странно, так как функция ищет в том числе и по именам субъекта или издателя, и они могут быть в utf-8 для отображения кириллицы.
Sergey Cheban писал(а):Источник цитаты Про описание структуры - это какая-то паскалевская специфика, я её, увы, не знаю.
Похоже что так, Паскалевская специфика, а именно "мутный" тип Pchar в который можно присвоить и строковую константу и адрес и нетипизированный указатель (аналог void*), но нельзя типизированный указатель (на какую либо структуру, даже на массив символов). Должен представлять как раз таки указатель на массив символов с нулем в конце. Все должно преобразовываться автоматически, но похоже автоматикой где-то лишний раз берется адрес.

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

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

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#33 Сообщение two_oceans » 25 авг 2017, 09:17

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

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

По составным частям пока при взятии тега по id один символ пропадает и хэш не сходится. Далее планирую поправить проверку так, чтобы после нее были выполнены приготовления для переподписания (либо замены либо добавления еще одной подписи).

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#34 Сообщение two_oceans » 31 авг 2017, 09:33

За неделю: проверил подписанный файл на техническом портале СМЭВ - там меня обрадовали, что документ соответствует методическим рекомендациям 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, то нужно добавить модификатор формата, выглядит как

Код: Выбрать все

FORMAT:UTF8,UTF8:Строка
При этом двойное перекодирование отменяется, но 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 с поддержкой ГОСТ.

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#35 Сообщение two_oceans » 04 сен 2017, 05:57

Разбирался выходные с переводами строк: все же, как и предполагалось можно без опасений удалить переводы строк из 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.

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#36 Сообщение two_oceans » 05 сен 2017, 11:26

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

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

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

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#37 Сообщение two_oceans » 07 сен 2017, 04:42

Итак, разобрался с файлом в котором все объявления пространств идут на пространство по умолчанию. 3 подписи проверяются (были небольшие проблемы с определением какой сертификат к какой подписи - второй и третий сертификат не добавлялись). Казалось бы отлично, но проверка на наличие четвертой вываливается с ошибкой "Недостаточно памяти". В системе-то память есть, но видимо heap закончился.

Глянул сколько памяти и остался в недоумении - после третьей подписи Виндоуз показывает порядка 648 Мб (из них 112 Мб Working Set (в оперативке), остальное в подкачке), мини-менеджер памяти по суммированию выделения и освобождения - 612 Мб (разница в 30 с небольшим Мб вполне может быть на статические переменные и выдедение на иной памяти кроме компзитных строк), сумма размеров по зафиксированным в мини-менеджере адресам - 43 Мб. Как я понимаю, с такими симптомами... утечка в самом мини-менеджере, буду искать. Вчера вроде бы разобрался с неявными присвоениями, но особо ситуация не изменилась.

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#38 Сообщение two_oceans » 15 сен 2017, 13:13

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

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#39 Сообщение two_oceans » 27 сен 2017, 07:48

Подправил композитные строки еще раз - теперь при освобождении не нужно указывать адрес старой переменной, есть возможность исправить адрес старой переменной на адрес временной переменной. Дубли теперь определяются как по адресу буфера, так и по адресу переменной - если адрес переменной используется с новым буфером и на прежний буфер не зарегистрировано других переменных делается попытка его освободить. Поэтому добавлено еще одно поле в мини-менеджер: условный тип переменной. Фиксировано значение 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 подписи на части (сертификаты отдельно, взаимодействие с Майкросрофтовским провайдером отдельно) - сейчас получается слишком много кода.

two_oceans
Бывалый
Сообщений: 432
Зарегистрирован: 30 сен 2016, 17:17
Благодарил (а): 383 раза
Поблагодарили: 351 раза

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

#40 Сообщение two_oceans » 02 окт 2017, 13:17

За выходной перенес работу с композитными строками в библиотеку. Много заморочек вышло с переименованием функций, в том плане, что переименовал функции, которых было 3, а в интерфейсном модуле (аналог заголовочного файла Си) названия остались те же, в итоге во все три получили адрес совпадающей со старым названием при импорте из библиотеки. Преимущественно с этим разобрался, но еще перепроверю. Текущий статус: 4 библиотеки без отладочных символов + приложение с отладочными 1001 Кб.


Вернуться в «ГИС ЖКХ. Форум разработчиков программного обеспечения и всего, что с ним связано»

Кто сейчас на форуме

Количество пользователей, которые сейчас просматривают этот форум: нет зарегистрированных пользователей и 1 гость