logo
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Kilya  
#1 Оставлено : 19 апреля 2019 г. 9:59:05(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Добрый день. Суть задачи.
Есть сервер, где хранятся файлы (данные).
На клиенте производится подпись. Чтобы не гонять большие данные, на сервере высчитывается хэш (с помощью .Net Sharpei) и отправляется на клиента.
Клиент подписывает хэш с помощью Browser plug-in, и отправляет подписанный хэш на сервер.
На сервере у ServiceProvider, к примеру у Gost3410_2012_256CryptoServiceProvider, в методе VerifyHash я могу передать только хэш и подписанный хэш. Сертификат я не могу указать.
Правильно ли я понимаю, что:
1) В подписанном хэше уже есть информация об сертификате и поэтому сам сертификат с клиента присылать на сервер не требуется и для проверки сертификат не требуется?
2) Gost3410_2012_256CryptoServiceProvider (и др.) должны быть такие же на сервере, которыми подписывался хэш на клиенте? Как это лучше обеспечить? Может с клиента отправлять на сервер сертификат и из него можно как-то получить алгоритм для хэша?
3) Подписанный хэш я могу просто сохранить в текстовый файл с расширением .sig - и это будет моя открепленная подпись документа?

Отредактировано пользователем 19 апреля 2019 г. 10:11:03(UTC)  | Причина: Не указана

Offline Артём Макаров  
#2 Оставлено : 19 апреля 2019 г. 12:34:38(UTC)
Артём Макаров

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

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

Поблагодарили: 14 раз в 14 постах
Добрый день.

Объекты *CryptoServiceProvider характеризуют открытый или закрытый ключ сертификата.

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

В хэше никакой информации нет, это лишь последовательность байт с хэш значением для документа.
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Артём Макаров за этот пост.
Kilya оставлено 19.04.2019(UTC)
Offline Kilya  
#3 Оставлено : 19 апреля 2019 г. 12:55:52(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Автор: Артём Макаров Перейти к цитате
Добрый день.

Объекты *CryptoServiceProvider характеризуют открытый или закрытый ключ сертификата.

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

В хэше никакой информации нет, это лишь последовательность байт с хэш значением для документа.


У меня от клиента на сервер пришел ПОДПИСАННЫЙ хэш. Там же есть информация о сертификате? Иначе как метод
Код:
public bool VerifyHash(byte[] hash, byte[] signature);

проверку осуществляет?

И все остался вопрос, как мне подписанный хэш привратить в открепленную подпись (файл *.sig)?
Offline two_oceans  
#4 Оставлено : 19 апреля 2019 г. 13:04:15(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 519
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 28 раз
Поблагодарили: 117 раз в 112 постах
По схеме нюанс - если в сертификате есть фио, снилс, то пользователю надо показать подписываемое в каком-либо виде иначе это будет идти в разрез с законодательством.

По вопросам - принципе все так и есть. Разве что надо уточнить, что есть "значение подписи" (для ГОСТ оно в 2 раза длинее чем значение хэша, то есть 64-128 байт, используется на уровне низкоуровневого CryptoAPI, по сути это зашифрованное закрытым ключом значение хэша) и есть подпись "в сборе" (отличимо длинее обычно от 500 байт до нескольких килобайт) - включающая значение подписи и еще много чего: может включать сертификат, может включать цепочку сертификатов без корневого или с корневым, дополнительные данные (например, штамп доверенного времени, списки отзыва на момент подписания), могут даже включаться исходные данные. Если исходные данные присутствуют, то это присоединенная подпись, если данные отсутствуют, то отсоединенная (открепленная) подпись. Похоже что под "подписанный хэш" Вы имеете в виду "подпись в сборе".

1) Если содержится сертификат в "подписи в сборе", то отдельно его передавать нет необходимости. Если только "значение подписи" в низкоуровневые функции, то нужно передавать дескриптор открытого ключа, полученный импортом кусочка с открытым ключом из контекста сертификата.

2) Да, для ГОСТ есть однозначное соответствие между алгоритмом хэширования и алгоритмом подписи. В сертификате/контексте сертификата есть поле оида алгоритма открытого ключа и к нему 2 поля параметров: оид параметров алгоритма хэширования и оид параметров алгоритма подписи. Не вдаваясь в подробности - у алгоритмов открытого ключа значений меньше, поэтому я бы посоветовал ориентироваться на него. Подробнее я уже на этом форуме уточнял, наверно это четвертый или пятый подобный вопрос с августа прошлого года.

Обратите внимание, что в сертификате есть еще поля алгоритм подписи и алгоритм хэширования, их не нужно использовать, так как они указывают на алгоритмы ключа удостоверяющего центра (УЦ) и теоретически могут отличаться от алгоритма ключа самого сертификата. У аккредитованных УЦ ФСБ и Минкомсвязь принудительно ввели соответствие, но любые неаккредитованные УЦ (для тестовых сертификатов и т.д.) могут подписать сертификат клиента ГОСТ-2012 сертификатом УЦ ГОСТ-2001 и ввести в заблуждение программы, смотрящие не то поле.

3) Если получили "подпись в сборе", то в целом да. Если получили только значение, то нет.

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

Присоединенная подпись всегда больше чем исходные данные, так как их содержит. Поэтому если получили "подпись в сборе" и она меньше исходных данных, то это отсоединенная подпись.

Отредактировано пользователем 19 апреля 2019 г. 13:07:20(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
Kilya оставлено 19.04.2019(UTC)
Offline Kilya  
#5 Оставлено : 19 апреля 2019 г. 13:49:30(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Автор: two_oceans Перейти к цитате

Спасибо за развернутый ответ. Почти все понял.

Документация по криптопро .net скудная, поэтому я не совсем понимаю что получаю на каком этапе. Попробую еще раз расписать.
1) На сервере есть файл, к примеру pdf. Я его считываю как массив байт. На сервере из этого массива байт я формирую хэш в массив и преобразую в строку

Код:
private string TestMethod(byte[] content)
{
    var algorithm = new Gost3411CryptoServiceProvider();
    byte[] hash = algorithm.ComputeHash(content);            
    StringBuilder hex = new StringBuilder(hash.Length * 2);
    foreach (byte b in hash)
        hex.AppendFormat("{0:x2}", b);
    return hex.ToString();
}


2) На клиент пришла строка хэша. Мы ее подписываем согласно примеру пример
По примеру на руках в итоге имеем подписанное сообщение
Код:
var sSignedMessage = yield oSignedData.SignCades(oSigner, CADESCOM_CADES_BES);


Как я понимаю, т.к. тут нет самого файла pdf, а только хэш, то мы получили как результат "открепленную подпись", верно?
Она содержит в себе подписанный хэш и информацию о сертификате. Так?

3) Результат шага 2 отправляем на сервер. Надо ли отправлять и сертификат?
Результат (подписанный хэш) надо проверить на подлинность (тут пока не разобрался до конца как это сделать). И если все хорошо, то сохранить рядом с исходным файлом как открепленную подпись, т.к. файл *.sig.
Верно я понимаю, что результат шага 2 я могу просто сохранить в файл *.sig? Это же есть моя открепленная подпись?

Отредактировано пользователем 19 апреля 2019 г. 14:21:21(UTC)  | Причина: Не указана

Offline Андрей Писарев  
#6 Оставлено : 19 апреля 2019 г. 14:12:40(UTC)
Андрей Писарев

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,199
Мужчина
Российская Федерация

Сказал «Спасибо»: 277 раз
Поблагодарили: 1145 раз в 908 постах
Здравствуйте.

В указанном примере не используется вызов SignCades.


Цитата:
а только хэш, то мы получили как результат "открепленную подпись", верно?


Если правильно использован пример - на выходе отсоединенная подпись.

Теперь Вы можете проверить её, используя исходный pdf и, например, КриптоАРМ.

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей Писарев за этот пост.
Kilya оставлено 19.04.2019(UTC)
Offline Kilya  
#7 Оставлено : 19 апреля 2019 г. 14:23:59(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Автор: Андрей Писарев Перейти к цитате
Здравствуйте.

В указанном примере не используется вызов SignCades.


Цитата:
а только хэш, то мы получили как результат "открепленную подпись", верно?


Если правильно использован пример - на выходе отсоединенная подпись.

Теперь Вы можете проверить её, используя исходный pdf и, например, КриптоАРМ.



Изменил ссылку, не туда указал. Другой пример используем, где используется SignCades.
А могу я проверить подпись полученную, используя исходный pdf, но не КриптопроАрм, а средствами Криптопро .Net? Правильно смотрю на .Net SDK\Examples\simple\CMS\VerifyDetached ?
Offline Андрей Писарев  
#8 Оставлено : 19 апреля 2019 г. 15:18:49(UTC)
Андрей Писарев

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,199
Мужчина
Российская Федерация

Сказал «Спасибо»: 277 раз
Поблагодарили: 1145 раз в 908 постах
Автор: Kilya Перейти к цитате

Изменил ссылку, не туда указал. Другой пример используем, где используется SignCades.


Должны использовать: Вычисление подписи по хэш-значению

SignCades будет от данных (в данном случае уже вами вычисленный на сервере хеш)
вычислять хеш и именно его подписывать.
Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей Писарев  
#9 Оставлено : 19 апреля 2019 г. 15:19:42(UTC)
Андрей Писарев

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,199
Мужчина
Российская Федерация

Сказал «Спасибо»: 277 раз
Поблагодарили: 1145 раз в 908 постах
Цитата:
А могу я проверить подпись полученную, используя исходный pdf, но не КриптопроАрм, а средствами Криптопро .Net? Правильно смотрю на .Net SDK\Examples\simple\CMS\VerifyDetache


Да, если правильно использовали подписание по хешу, а не через SignCades.
Техническую поддержку оказываем тут
Наша база знаний
Offline Kilya  
#10 Оставлено : 19 апреля 2019 г. 16:00:12(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Автор: Андрей Писарев Перейти к цитате
Цитата:
А могу я проверить подпись полученную, используя исходный pdf, но не КриптопроАрм, а средствами Криптопро .Net? Правильно смотрю на .Net SDK\Examples\simple\CMS\VerifyDetache


Да, если правильно использовали подписание по хешу, а не через SignCades.


Пытаемся подписать хэш
Код:
const sSignedMessage = yield oSignedData.SignHash(cfg.hashAlg, oSigner, CADESCOM_CADES_BES);


Получаем ошибку:
Цитата:
Uncaught (in promise) Failed to create signature. Error: Параметр задан неверно. (0x80070057)
Offline Kilya  
#11 Оставлено : 22 апреля 2019 г. 13:42:26(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Ошибка та же.
Но понятна причина стала. Если я на клиенте вызываю
Код:
oHashedData.Hash(dataToSign);

, то полученный хэш успешно подписывается.

А вот если я хэш получаю с сервера в виде строки, сформированный как
Код:
return System.Convert.ToBase64String(hash);

, то получаю ошибку.

Что я делаю не так, что особенного с данными делает
Код:
oHashedData.Hash(dataToSign);
?
Offline Kilya  
#12 Оставлено : 6 мая 2019 г. 12:48:34(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Отвечу сам на свой же вопрос. На сервере после вычисления хэша методом ComputeHash, надо приводить его к строке не мотодом конвертации
Код:
return System.Convert.ToBase64String(hash);


а с помощью цикла

Код:
StringBuilder builder = new StringBuilder();
for (int i = 0; i < hash.Length; i++) {
   builder.Append(hash[i].ToString("X2"));
}
return builder.ToString();


У меня есть пара вопросов других.
Когда я на сервере имею вычисленный хэш и полученный от клиента подписанный хэш, мне достаточно проверить их между собой на корректность?
Или я еще должен проверять сертификат, которым был подписан хэш а клиенте?
Если должен, то могу ли я проверить сертификат по подписанному хэшу, т.е. не пересылась сам сертификат с клиента?
Offline two_oceans  
#13 Оставлено : 8 мая 2019 г. 8:34:03(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 519
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 28 раз
Поблагодарили: 117 раз в 112 постах
Добрый день. Если все еще не разобрались что получаете, то наверно надо просто посмотреть что там вышло и присутствует ли сертификат в результате. Если присутствует, то ничего отдельно передавать не нужно. Если отсутствует, то наверно надо указать какие-то еще что-то при подписании. Для проверки, например, взять некий тестовый небольшой pdf без критичной информации, подписать по Вашему методу, заархивировать исходный файл и полученную предположительно отсоединенную подпись, залить архив на Яндекс диск, открыть доступ и написать ссылку сюда.

Либо посмотрите наличие сертификата в результате сами - для этого нужно убедиться что результат (и сертификат для сравнения) декодирован из Base64 в двоичный вид, сначала можно сравнить размер. Если "подписанный хэш" меньше размера сертификата, то естественно никакого сертификата там нет. Если больше - нужно смотреть, для этого нужна программа просмотра ASN.1 кодировки, я использую Asn1Editor, но есть и другие программы. Там уже можно найти характерные для сертификата структуры визуально. Если программа не открывает файл, значит перекодировка сделана неправильно. Некоторые программы сами перекодируют, ими можно Base64 открыть.

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

По второму этапу строится цепочка сертификатов удостоверяющих центров до самоподписаного (корневого) сертификата, проверяется что все сертификаты имеют верную математическую подпись, проверяется что корневой сертификат указан в списках доверенных сертификатов, проверяется что на дату подписи все сертификаты цепочки (и УЦ и конечный) были действующими по дате, проверяется что сертификаты не были отозваны (кроме корневого, проверка может быть по протоколу OCSP, по установленному списку отзыва и скачиванием списка отзыва при проверке). Этот этап удостоверяет, кто именно владеет ключом, которым подписан файл и какой удостоверяющий центр заверил факт владения. Если дата подписи не указана, то проверяется на время проверки, то есть подпись получится недействительна при проверке после истечения сертификата.

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

Если кроме подписи файлы будут еще и шифроваться, то при смене сертификата желательно предусмотреть возможность перешифрования на новый сертификат. Подразумевается шифрование симметричным ключом полученным по схеме обмена ключами между 2 абонентами. В этом случае каждый файл смогут расшифровать 2 абонента и если сертификат одного абонента закончился можно расшифровать файл от другого абонента и зашифровать снова уже замененным сертификатом первого.
thanks 2 пользователей поблагодарили two_oceans за этот пост.
Андрей Писарев оставлено 08.05.2019(UTC), Kilya оставлено 08.05.2019(UTC)
Offline Kilya  
#14 Оставлено : 8 мая 2019 г. 11:04:38(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Сам прочитал, что метод CheckSignature может идти с параметром false и тогда идет проверка цепочки сертификатов.
Подписанный файл из .sig переименовал в .p7b и увидел что это за сертификат вложен.
Спасибо за развернутый ответ.
Offline Kilya  
#15 Оставлено : 14 мая 2019 г. 13:03:38(UTC)
Kilya

Статус: Участник

Группы: Участники
Зарегистрирован: 13.11.2015(UTC)
Сообщений: 20
Российская Федерация

Сказал(а) «Спасибо»: 14 раз
Дабы не плодить темы, спрошу тут.
Искал в интернете "как подписать пакет документов", "как подписать папку". Все что нашел - КриптоПроАрм позволяет подписывать папки.
Но как реализован данный механизм?

В моей ситуации с кэшем как мне быть с папкой/пакетом документов/несколькими файлами.
Я не хочу подписывать каждый файл отдельно.

Мое понимание:
1) Собрать архив из всех файлов
2) Работать с архивом как с одним файлом (вычислять его хэш, подписывать этот вычисленный хэш)

Или есть другой способ?
Offline two_oceans  
#16 Оставлено : 15 мая 2019 г. 7:11:07(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 519
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 28 раз
Поблагодарили: 117 раз в 112 постах
Если я правильно понял о какой программе речь, то обратите внимание что "КриптоАрм" пишется без части "Про" в серединет, так как это программа не разработка КриптоПро, а совсем другой компании. К слову, у меня в контекстном меню папки нет пункта КриптоАрм, а у файлов есть, то есть подписать папку можно только из основного окна программы - при этом подписывается каждый файл в папке отдельно, просто нет необходимости выбрать каждый файл, перечисление файлов из папки в список для подписания автоматическое.

В информационных системах применяются оба подхода как подписание каждого файла и прикрепление парами файл подпись, так и прикрепление одного архива + подписи архива. Понятно, что во многих случаях архив еще место на диске экономит. Однако вВажен вопрос удобства изменения части пакета документов - если понадобится изменить один файл в архиве, то это будет означать что все файлы архива стали подписаны более поздней датой или будете хранить несколько версий архива. В то же время при подписании каждого файла можно более гибко прикрепить новую версию одного файла и новую подпись, при необходимости сохранив и старую подписанную версию для полной истории. Поэтому "не хочу" тут аргумент слабый, лучше ориентироваться на возможность потенциальной замены части пакета документов: если частичная замена не предполагается, то архивом, иначе каждый файл отдельно.
thanks 1 пользователь поблагодарил two_oceans за этот пост.
Kilya оставлено 15.05.2019(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.