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

И специализированное программное обеспечение используется для выполнения всех этих задач, включая подписание и шифрование. Стандартные программы, созданные независимыми предприятиями для этой цели, могут использоваться в качестве универсальных утилит, или вы можете использовать свое собственное создание. Тем не менее, вы все равно будете использовать библиотеки и инструменты компании с тем же названием, независимо от того, пишете ли вы необходимый код самостоятельно или используете библиотеки и инструменты криптографических компаний (как правило, лицензированные из «соответствующих» органов власти).

CryptoPro — один из таких бизнесов. Это не реклама; продукты были выбраны еще до того, как я начал там работать. Я просто один из пользователей продукта. Эта компания производит библиотеки и криптографические продукты, которые позволяют подписывать документы алгоритмами ГОСТ. Версии программного обеспечения доступны для Windows и Linux. Есть продукты, разработанные специально для использования с Java, например, Click Up в программах, построенных на JavaScript или HTML5.

Все это замечательно, но есть одна оговорка. Вопрос их совместимости — это система обмена защищенными документами. Кроме «КриптоПро» есть и другие компании, производящие криптографическое программное обеспечение. Во-вторых, в линейке есть продукты для различных операционных систем и языков программирования. Кроме того, каждая система имеет уникальную реализацию криптографической подсистемы, а также структуру. Кроме того, никто не отменял течение времени: системы были написаны как в прошлом, так и в настоящем. Более того, единственная причина, по которой эти системы могут быть заменены, заключается в том, что они просуществовали некоторое время и завоевали доверие пользователей. Кроме того, найти авторов очень сложно.

Ситуация, описанная в этой статье, когда необходимо было обеспечить совместимость между недавно разработанным программным обеспечением и надежным, старым программным обеспечением, разработчики которого прекратили поддержку, но пользователи все еще держатся за него.

Базовый уровень. Некоторое программное обеспечение было создано в 2007 году с использованием системной библиотеки Microsoft CAPICOM и Delphi (версия 2005). Новое программное обеспечение использует CryptoProJava CSP для обработки криптографии и совместимо с Java и Windows. Следует отметить, что новое дело также поддерживает «съемную» подпись старого ПО. Вы можете видеть, что зверинец в итоге получился хорошим.

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

Шаг 1. Был написан Java-код для подписи файла с использованием соответствующего сертификата и ключей. Поскольку в КриптоПро есть многочисленные примеры использования (и это), здесь было не так много. После получения подписи он был успешно проверен на сайте Госуслуг, чтобы посмотреть, насколько хорошо он справился с заданием по решению проблемы. Святая простота! Я бы назвал это наивностью. Попытка использовать для проверки подписи программу, написанную на Delphi, не увенчалась успехом.

Шаг 2. Важно определить «странные» функции программного обеспечения. Я сделал образованное предположение. Я удаляю подписанный файл и его подпись из программного обеспечения (их невозможно сразу же удалить, потому что программное обеспечение удаляет документ подписи после проверки). Я проверяю подпись на веб -сайте общественных услуг, и она не проходит тест!

Шаг №3 — понять, что же именно приводит к таким разным результатам, вроде бы, одного и того же действия. И тут на помощь пришел наработанный ранее опыт. Дело в том, что некоторое время назад решалась очень похожая задача — обеспечить совместимость подписи, устанавливаемой при помощи нашего ПО, написанного на Delphi, с требованиями сайта Гос. Услуг. Проблема была очень похожей, но дело облегчалось наличием исходных текстов. Довольно быстро стало понятно, что пресловутая несовместимость обусловлена взаимодействием Delphi и CAPICOM. При написании софта использовалась Delphi 6 (да, ПО довольно возрастное), строки в этой версии — однобайтовые: один символ — один байт. CAPICOM же работает с UNICODE строками: один символ — два байта. И, хотя, в CAPICOM предусмотрена специальная функция, позволяющая преобразовать «правильным» образом однобайтовую строку в двухбайтовую (
Utilities.ByteArrayToBinaryString), наше ПО эту функцию не использовало. Ну а раз так, то преобразование строки Delphi в строку CAPICOM происходило методом «по умолчанию» — каждый байт превращался в два. При использовании же упомянутого метода, он, скорее всего, «упаковывал» бы два символа строки Delphi в один символ UNICODE строки. Таким образом, скложилась интересная ситуация — в зависимости от того, использовалась, или нет, функция Utilities.ByteArrayToBinaryString подписывалась разная информация. И, надо сказать, что при использовании метода CAPICOM, подписывалась «истинные» данные, а вот при преобразовании «по умолчанию» подписывалась слегка измененная версия первоначального документа. Все эти умозаключения довольно быстро нашли свое практическое доказательство — как только добавили вызов метода Utilities.ByteArrayToBinaryString, подпись стала проходить проверку на сайте Гос. Услуг. (Справедливости ради надо сказать, что вызов метода Utilities.ByteArrayToBinaryString в нашем ПО все-таки присутствовал, но зависил он от значения флага, который должен был обеспечить обратную совместимость с более ранними версиями, в котором этого вызова не было).

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

Шаг 4: Мы должны каким -то образом преобразовать данные в Java, чтобы окончательный результат соответствовал окончательным результатам в Delphi и Capicom. И вот где возникли проблемы. Эти проблемы возникли, потому что я не совсем осознавал, как изменить однобайтовые символы Delphi на двойные символы Capicom. Кроме того, без этого преобразования нельзя повторить.

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

До тех пор, пока не будет представлен кириллический текст, этот точный процесс продолжался. Вторая попытка проверить подписи на таких данных не удалась. Я вернулся к своим тестам с неразборчивой подписью, которая показала, что кириллические символы даже получили 0x04 в качестве второго байта. На самом деле это причина. При отображении в файле UTF-16 на компьютере Windows 1251, кириллические символы имеют точно так же, как и английские символы. Российские персонажи имеют код 0x04, в то время как английские персонажи сохраняют предыдущий персонаж. Российский персонаж 01. и английский персонаж A имеет тот же код, 0x0041. Все в Интернете можно найти в Википедии.

Поэтому можно предположить, что Capicom Windows использует текущую (используемую) кодовую страницу, преобразуя однобайтовые символы строк Delphi в двухбайтовые. какую страницу можно открыть в Windows, несмотря на то, что Unicode только недавно вошел в обиход. Не упустите из виду настройку кодовой страницы для программ, которые не поддерживают Unicode. Она показана здесь, и мы указываем на нее:

ctrlpnlregion

Если это так, это очень просто: байты, которые необходимо подписаны, представляют собой строку символов, кодируемых в Windows-1251. Мы создадим код и проверим его функциональность. Оно работает!

Похоже, что проблема была решена. Тем не менее, «Опыт», продукт усвоенных уроков, «подсказывает: нужно взять файл большего размера». Архивный файл, однако, оказался небольшим и несжатым; стандартная программа просмотра текста может его просмотреть. Я использую здоровый архивный файл размером 100 мегабайт и подвергаю его испытанию. И» дело, Бог изобретатель» приводит к позорному результату — проверка подписи проваливается.

Что ж, именно здесь начинается анализ неразделимых подписей программы, которые должны быть записаны в программу, которая, как известно, должна подписать данные правильно (с точки зрения программного обеспечения). Мы довольно быстро определяем корень проблемы. Представляем шестнадцатеричный характер 0x98. Исходный файл отражает это.0xfdfa занимает свое место в преобразованном алгоритме, который был специально создан для этого метода. Справочная программа выводит 0x0098.«Подготовленный» файл имеет значение 0xfd, в то время как исходный файл имеет значение 0x9800. Что произошло?!

Более того, Википедия действительно объясняет, что происходит. Во-вторых, в таблице символов windows-1251 символ 0x98 указан как непригодный для использования. Почему нет символа, который можно было бы отобразить, меня озадачивает. В-третьих, «несимвольные» коды в UTF-16 используются для обозначения «неиспользуемых» символов. Теперь все встало на свои места. Несмотря на то, что есть сомнения.

Но сначала давайте убедимся, что предпосылка верна! Я убеждаюсь, что 1 x8 было заменено на каждый экземпляр комбинации байтов 0xFD-0x9800. Я подписываю результат и делаю это. К счастью, проверка оказалась верной. Шляпы в воздух, фанфары.

В чем здесь урок? Мой вывод заключается в том, что для реализации механизмов, которые предлагает инструмент CAPICOM, следует использовать метод Utilities. После этого используйте ByteArrayTo BinaryString. и трудности, которые трудно преодолеть. Но даже несмотря на то, что мне удалось проверить подписи и смоделировать преобразование данных, все равно остается некоторая неуверенность в том, что это всегда будет работать. На каком компьютере происходит создание и проверка электронной подписи на втором компьютере? На коронавирус ли он будет проверять? У меня есть сомнения. Поскольку я собираю информацию, основываясь на определенных презумпциях (что региональные настройки настроены определенным образом), если эти презумпции окажутся неверными, вся «стройная» конструкция развалится.