Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline test.user  
#1 Оставлено : 11 июля 2023 г. 11:16:37(UTC)
test.user

Статус: Активный участник

Группы: Участники
Зарегистрирован: 11.12.2019(UTC)
Сообщений: 30

Сказал(а) «Спасибо»: 11 раз
Добрый день!
Есть необходимость проверки файлов, подписанных КЭП, сама подпись выполняется через веб-плагин Крипто-про Extension for CAdES.
Плагин формирует для загруженного файла хеш и если я правильно понимаю, подписывает именно сам хеш, а не выбранный файл.
Т.е. мы загрузили картинку, посчитали ее хеш и подписали. Кажется есть возможность подписать и сам файл, но обычно достаточно подписать просто хеш (по крайней мере в нашем случае). Плюс сертификат подписанта может быть включен в подпись, а может не быть. Поясните пожалуйста, от чего это зависит и в чем разница с точки зрения кода проверки?

Для проверки подписи используем примерно такой код:
Код:

CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCmsFromPluginOutput), hashAsStringToBytes, null);
cadesSignature.verify(chain);
Configuration.printSignatureInfo(cadesSignature);


подпись закодирована в base64, поэтому сначала ее декодируем, объект cadesSignature успешно формируется, внутри него доступна информация о тех кто его подписал. Т.к. мы подписывали хеш, то в поле data указан именно он (пробовали и интерпретировать сам хеш как набор 16ричных значений через DatatypeConverter.parseHexBinary(hash), но результат тот же). При вызове метода verify получаем ошибку:
message-digest attribute value does not match calculated value. В т.ч. если передавать всех acceptedIssuers из trustStore (все сертификаты) или не передавать никаких, т.е. verify(null).

Однако, если в chain добавить сертификат того кто подписал файл, т.е. тот сертификат, который был выбран для подписи файла, то проверка проходит (ошибок в verify нет).
Помогите разобраться как это должно работать? При проверке подписи например на ресурсе https://www.gosuslugi.ru/pgu/eds/order, проверка подписи того же файла проходит успешно, отображается имя подписанта. И очевидно на госуслугах нет сертификата подписанта, т.е. он не попадает в chain при проверке подписи. Но если выполнять проверку локально, то проверка проходит только при условии что сертификат подписанта добавлен в цепочку.
Offline Евгений Афанасьев  
#2 Оставлено : 12 июля 2023 г. 11:39:18(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,963
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Здравствуйте.
Скорее всего, у вас 2 проблемы с проверкой подписи.
1. message-digest attribute value does not match calculated value - ошибка, связанная с тем, что хэш от тех данных, что вы передали в CAdESSignature, не совпадает с хэшом данных в поле message-digest в подписанных атрибутах.
А) Вы используете
Цитата:

CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCmsFromPluginOutput), hashAsStringToBytes, null);

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

public CAdESSignature(byte[] signature, byte[] data, Integer signatureType, boolean useRawDigest)
public CAdESSignature(InputStream signatureStream, final InputStream dataStream, Integer signatureType, boolean useRawDigest)

передав последним параметром true.
Б) если подпись формировалась в плагине и вы сами считаете хэш, то, скорее всего, надо использовать для данных кодировку UTF-16LE: https://support.cryptopr...etsja-v-kriptoarmcryptcp
2. "сертификат подписанта может быть включен в подпись, а может не быть. Поясните пожалуйста, от чего это зависит и в чем разница с точки зрения кода проверки?" - сертификат подписи или цепочка могут быть добавлены в подпись и при проверке будут использоваться. Плагин по умолчанию добавляет сертификат, CAdES.jar - нет. Добавить сертификат можно с помощью метода setCertificateStore, он принимает X509CertificateHolder. Или можно найти метод addSigner с последним параметром addCertificateChain, он добавит всю цепочку в подпись при формировании.
Наличие сертификата облегчает проверку на стороне проверяющего.
"если выполнять проверку локально, то проверка проходит только при условии что сертификат подписанта добавлен в цепочку." видимо, с помощью CAdESSignature.
"Однако, если в chain добавить сертификат того кто подписал файл, т.е. тот сертификат, который был выбран для подписи файла, то проверка проходит (ошибок в verify нет)." - да, см. выше про добавление сертификата в CAdESSignature.
thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
test.user оставлено 25.07.2023(UTC)
Offline test.user  
#3 Оставлено : 17 июля 2023 г. 0:42:15(UTC)
test.user

Статус: Активный участник

Группы: Участники
Зарегистрирован: 11.12.2019(UTC)
Сообщений: 30

Сказал(а) «Спасибо»: 11 раз
попробовали советы, но все равно проверка не проходит:
1) подпись делается через плагин, т.е. сертификат и цепочка скорее всего добавляются, по крайней мере вся информация о том кто подписывал доступна если просматривать объект CAdESignature через отладчик.
А) добавили последний параметр true:
Цитата:
CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCms), hash, null, true);

Б) data второй параметр из строки хеша получаем сейчас так:
Код:
hashString.getBytes(StandardCharsets.UTF_16LE)

2) если в подписи должен быть сертификат (т.к. подпись была через плагин), то какие сертификаты нужно добавлять в цепочку для проверки (и нужно ли вообще)?
сейчас даже если передать все корневые сертификаты или null, то по прежнему ошибка с message-digest attribute value does not match calculated value:
Код:

CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCms), hash, null, true);
cadesSignature.verify(null);
Configuration.printSignatureInfo(cadesSignature);
Offline test.user  
#4 Оставлено : 23 июля 2023 г. 16:58:34(UTC)
test.user

Статус: Активный участник

Группы: Участники
Зарегистрирован: 11.12.2019(UTC)
Сообщений: 30

Сказал(а) «Спасибо»: 11 раз
есть какие то способы понять в чем может быть проблема? возможно есть какие то примеры как можно именно подписанную через плагин подпись провалидировать? Идеи\варианты что можно попробовать закончились, куда копать понимания нет (
Offline Евгений Афанасьев  
#5 Оставлено : 24 июля 2023 г. 15:35:37(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,963
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
На счет п.2 не понял:
хэш должен считаться с помощью MessageDigest от данных, как dataString.getBytes(StandardCharsets.UTF_16LE). Длина hash должна быть 32 байта для ГОСТ 2001 или 2012 (256) и 64 для ГОСТ 2012 (512).
Если hashString - это base-64 строка (с хэшом), то декодируйте строку из Base64 в binary и передайте в CAdESSignature.
thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
test.user оставлено 25.07.2023(UTC)
Offline test.user  
#6 Оставлено : 24 июля 2023 г. 23:49:47(UTC)
test.user

Статус: Активный участник

Группы: Участники
Зарегистрирован: 11.12.2019(UTC)
Сообщений: 30

Сказал(а) «Спасибо»: 11 раз
Если правильно понял, то CAdESignature умеет работать как с самими данными, так и с хешом на эти данные, но хеш при этом она считает сама, т.е. передаются данные, а внутри происходит сравнение подписи и хеша, вычисленного от данных.
В данном случае, хеш мы считаем сами, т.е. он и есть данные, которые подписывались в браузерном плагине.
Сейчас это выглядит так:
Код:

byte[] hash = "124433af998e15515b11c58d367add9472ccfb52226c50ee11438699d1db1234".getBytes(StandardCharsets.UTF_16LE);
CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCms), hash, null, true);
cadesSignature.verify(null);
Configuration.printSignatureInfo(cadesSignature);

первый параметр это Base64 подпись, которая была в output плагина при подписи строки хеша, который выше.
Пробовал также без rawDigest (со всеми сертами и без):
Код:

CAdESSignature cadesSignature = new CAdESSignature(Base64.decode(cadesCms), hash, null); //true
cadesSignature.verify(chain);

результат всегда один (
Offline Евгений Афанасьев  
#7 Оставлено : 25 июля 2023 г. 10:09:51(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,963
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
124433af998e15515b11c58d367add9472ccfb52226c50ee11438699d1db1234 - это hex-строка. Конвертируйте hex в binary (https://tomeko.net/online_tools/hex_to_file.php?lang=en) без getBytes(StandardCharsets.UTF_16LE), должен быть получен массив длиной 32 байта. Вот его передайте в CAdESSignature.
thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
test.user оставлено 25.07.2023(UTC)
Offline test.user  
#8 Оставлено : 25 июля 2023 г. 13:52:05(UTC)
test.user

Статус: Активный участник

Группы: Участники
Зарегистрирован: 11.12.2019(UTC)
Сообщений: 30

Сказал(а) «Спасибо»: 11 раз
спасибо огромное, работает! Единственное - проверка почему то выполняется очень долго, около 20 секунд
Offline Евгений Афанасьев  
#9 Оставлено : 25 июля 2023 г. 18:28:19(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,963
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Автор: test.user Перейти к цитате
спасибо огромное, работает! Единственное - проверка почему то выполняется очень долго, около 20 секунд

Включите логи JCPLogger уровня FINER или ALL, как тут https://support.cryptopr...nlirovnija-kriptopro-jcp
Возможно, имеется рассинхронизация времени служб TSP и OCSP.

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.