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

Уведомление

Icon
Error

10 Страницы«<8910
Опции
К последнему сообщению К первому непрочитанному
Offline bankir1980  
#181 Оставлено : 9 сентября 2021 г. 11:24:33(UTC)
bankir1980

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

Группы: Участники
Зарегистрирован: 20.12.2012(UTC)
Сообщений: 26
Откуда: Москва

Сказал(а) «Спасибо»: 1 раз
Подскажите, как и для чего используются pycades.Store().Name() и pycades.Store().Location()?

Обе эти функции вываливают ошибки.

Есть скрипт:

Код:

import sys
import pprint
sys.path.append('/opt/pycades/')
import pycades

certThumb = '610A3........7CB647';
store = pycades.Store();
store.Open(pycades.CADESCOM_LOCAL_MACHINE_STORE, pycades.CAPICOM_MY_STORE, pycades.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
#print(store.Name());
#print(store.Location());

certs = store.Certificates

inData = ''

for line in sys.stdin:
   inData = inData + line

for i in range(certs.Count):
   cert = certs.Item(i + 1)
   if cert.Thumbprint == certThumb:
      envelopedData = pycades.EnvelopedData()
      envelopedData.Content = inData
      envelopedData.Recipients.Add(cert)
      encryptedMessage = envelopedData.Encrypt(pycades.CADESCOM_ENCODE_BASE64)
      print(encryptedMessage)


Всё настроено, сообщения шифруются и расшифровываются (другим скриптом)

Однако, если раскоментировать один из #print, то вываливается ошибка

Код:
Traceback (most recent call last):
  File "encrypt.py", line 10, in <module>
    print(store.Name());
TypeError: 'str' object is not callable



Такая же ошибка и для Location

Отредактировано пользователем 9 сентября 2021 г. 11:45:02(UTC)  | Причина: Не указана

Offline two_oceans  
#182 Оставлено : 9 сентября 2021 г. 12:07:56(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 90 раз
Поблагодарили: 319 раз в 300 постах
https://docs.cryptopro.r...com/cadescom_class/store
Полагаю там просто лишние скобочки, ведь к store.Certificates обращаетесь без скобок?
Код:
print(store.Name);
print(store.Location);
Так не пробовали?

Цитата:
Но судя по комментариям разработки принимающего продукта, у них формирование происходит именно по изначальному документа. Учитывая, что у них используется JCP, судя по всему выполняется что-то подобное JCPxml.dsig.internal.xmldsigri.tests.SignFileExample.

Вопрос: можно ли что-то аналогичное реализовать на pycades?
Есть какой-то эталонный пример от них? Скорее всего нужно немного перебирать параметры в стандартном примере.
https://docs.cryptopro.r.../pycades-sign-verify-xml

Отредактировано пользователем 9 сентября 2021 г. 12:09:01(UTC)  | Причина: Не указана

Offline Dmitriy Chernyshov  
#183 Оставлено : 9 сентября 2021 г. 12:18:30(UTC)
Dmitriy Chernyshov

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Автор: two_oceans Перейти к цитате
https://docs.cryptopro.ru/cades/reference/cadescom/cadescom_class/store
Полагаю там просто лишние скобочки, ведь к store.Certificates обращаетесь без скобок?
Код:
print(store.Name);
print(store.Location);
Так не пробовали?

Цитата:
Но судя по комментариям разработки принимающего продукта, у них формирование происходит именно по изначальному документа. Учитывая, что у них используется JCP, судя по всему выполняется что-то подобное JCPxml.dsig.internal.xmldsigri.tests.SignFileExample.

Вопрос: можно ли что-то аналогичное реализовать на pycades?
Есть какой-то эталонный пример от них? Скорее всего нужно немного перебирать параметры в стандартном примере.
https://docs.cryptopro.r.../pycades-sign-verify-xml


Пример подписи выглядит вот так:
Код:
<?xml version="1.0" encoding="UTF-8"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
   <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256" />
      <Reference URI="">
         <DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256" />
         <DigestValue>WHK6jue2Wj/NULNiQv2yMyc2j+zMMI9EOuNKSQ4MCZU=</DigestValue>
      </Reference>
   </SignedInfo>
   <SignatureValue>6jmckUC/XFmmcE0xPq2ZS3x2XjRhyhp22eer2mNq9CeHccWHHoTv9aWQT+HAlQl85V3EfWvEZoBN1lOMUcVqew==</SignatureValue>
   <KeyInfo>
      <X509Data>
         <X509Certificate>MIIDYzCCAxKgAwIBAgITEgBXp+ja4olD1vlmtQABAFen6DAIBgYqhQMCAgMwfzEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFzAVBgNVBAoTDkNSWVBUTy1QUk8gTExDMSEwHwYDVQQDExhDUllQVE8tUFJPIFRlc3QgQ2VudGVyIDIwHhcNMjEwODE5MDkzNjAyWhcNMjExMTE5MDk0NjAyWjBpMSIwIAYJKoZIhvcNAQkBFhNmc3NwbnNvNTRAZ21haWwuY29tMRkwFwYDVQQDDBBiYXJzX3Rlc3RfaXZhbm92MQswCQYDVQQLDAJQUDENMAsGA1UECgwEQmFyczEMMAoGA1UEBwwDTnNrMGYwHwYIKoUDBwEBAQEwEwYHKoUDAgIkAAYIKoUDBwEBAgIDQwAEQIq8QBY4b8lt/WUkYOrugNgvj2luOE0H1U5m3iEE9od4BknQcZN31MpZRHf7i7hCf/uIdZKkSGF7LYD6IL0PToSjggF2MIIBcjAOBgNVHQ8BAf8EBAMCBPAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFCqbX3NAwMmNvTdxEQgGaeMqHI1hMB8GA1UdIwQYMBaAFE6DPhRp7+xdepUrXxH+NzIWSVUrMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJvbGwvQ1JZUFRPLVBSTyUyMFRlc3QlMjBDZW50ZXIlMjAyKDEpLmNybDCBrAYIKwYBBQUHAQEEgZ8wgZwwZAYIKwYBBQUHMAKGWGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJvbGwvdGVzdC1jYS0yMDE0X0NSWVBUTy1QUk8lMjBUZXN0JTIwQ2VudGVyJTIwMigxKS5jcnQwNAYIKwYBBQUHMAGGKGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L29jc3Avb2NzcC5zcmYwCAYGKoUDAgIDA0EAQeupGwzoecSEV2Z0cBE8n7zyM8Ctxzh6Rw7p33/QIKBoLTiy8V0j7tkrbApc1ivuUn5ohQWV4pB2jMsbIxwonA==</X509Certificate>
      </X509Data>
   </KeyInfo>
</Signature>


Я уже посмотрел исходники, которые они прислали и получается, что они не используют cades, а через JCP создают отдельно DigestValue, SignatureValue и X509Certificate. И если я правильно понимаю, в таком случае именно через подписание XML такой структуры от pycades не добиться. Поэтому возникает вопрос: можно ли с помощью pycades отдельно создать DigestValue и SignatureValue? Сейчас смотрю примеры по обычному подписанию строк, но если есть еще мысли, как сделать более правильно - буду благодарен за совет!
Offline two_oceans  
#184 Оставлено : 9 сентября 2021 г. 13:15:51(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 90 раз
Поблагодарили: 319 раз в 300 постах
Данный пример является некорректным в плане того, что: 1) когда подпись в отдельном файле по стандарту в URI должен указываться исходный файл; 2) не указан трансформ каноникализации подписываемого фрагмента. Считают как есть хэш файла? Такой вариант может применяться для xmldsig подписи двоичного файла, но немного натянут для исходного файла в формате xml. В том смысле, что парсер просто при загрузке xml файла его может изменить, например, откорректировав переводы строк.

Либо я неправильно понял и подписывается действительно двоичный файл? Для двоичного файла хэш можно посчитать через https://docs.cryptopro.r...scom_class/cphasheddata, но будет много хлопот чтобы загрузить файл без искажения, например придется кодировать в base64.

Raw подпись можно вычислить через https://docs.cryptopro.r...escom_class/rawsignature
Однако если делать вручную надо еще и вручную каноникализировать SignedInfo. Как это сделать на питоне я не смогу подсказать.


Как близкое приближение для xml на ум приходит: сделать ENVELOPED подпись копии всего исходного файла, из результата вырезать тег Signature в отдельный файл. Передать вырезанный Signature в паре с исходным файлом, а не с тем что получилось после подписи. Там будет "лишний" относительно примера трансформ enveloped_signature, но он будет работать "вхолостую" в случае отдельного файла (ничего не поменяет).

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

Отредактировано пользователем 9 сентября 2021 г. 13:23:52(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
Dmitriy Chernyshov оставлено 10.09.2021(UTC)
Offline Dmitriy Chernyshov  
#185 Оставлено : 10 сентября 2021 г. 13:30:43(UTC)
Dmitriy Chernyshov

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Автор: two_oceans Перейти к цитате
Данный пример является некорректным в плане того, что: 1) когда подпись в отдельном файле по стандарту в URI должен указываться исходный файл; 2) не указан трансформ каноникализации подписываемого фрагмента. Считают как есть хэш файла? Такой вариант может применяться для xmldsig подписи двоичного файла, но немного натянут для исходного файла в формате xml. В том смысле, что парсер просто при загрузке xml файла его может изменить, например, откорректировав переводы строк.

Либо я неправильно понял и подписывается действительно двоичный файл? Для двоичного файла хэш можно посчитать через https://docs.cryptopro.r...scom_class/cphasheddata, но будет много хлопот чтобы загрузить файл без искажения, например придется кодировать в base64.

Raw подпись можно вычислить через https://docs.cryptopro.r...escom_class/rawsignature
Однако если делать вручную надо еще и вручную каноникализировать SignedInfo. Как это сделать на питоне я не смогу подсказать.


Как близкое приближение для xml на ум приходит: сделать ENVELOPED подпись копии всего исходного файла, из результата вырезать тег Signature в отдельный файл. Передать вырезанный Signature в паре с исходным файлом, а не с тем что получилось после подписи. Там будет "лишний" относительно примера трансформ enveloped_signature, но он будет работать "вхолостую" в случае отдельного файла (ничего не поменяет).

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


Спасибо большое за ответы!

Сейчас разбор дошел до следующего - на принимающей стороне есть код:
Код:

private fun messageDigest(): MessageDigest {
    return MessageDigest.getInstance(GOST3411_2012_256, JCP_PROVIDER)
}

private fun hash(data: ByteArray): ByteArray {
    val messageDigest = messageDigest()
    messageDigest.update(data)
    return messageDigest.digest()
}


Повторить массив байтов data получается. Если делать на стороне pycades что-то аналогичное:
Код:

hashedData = pycades.HashedData()
hashedData.Algorithm = pycades.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_256
hashedData.Hash('<languages>\n</languages>')

print(hashedData.Value)


то получается совсем другой результат.

Вопрос: есть ли какая-то возможность повторить алгоритм из примера на java в pycades?
Offline two_oceans  
#186 Оставлено : 13 сентября 2021 г. 8:31:33(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 90 раз
Поблагодарили: 319 раз в 300 постах
Посмотрите, не получилась ли перевернутая строка, при необходимости просто переверните. Первый байт с последним, второй с предпоследним. Если результат объявлен как массив байтов и размер массива совпадает с размером результата, то reverse массива делает как раз что нужно.

Это, может показаться странным, но сам по себе гост не регламентирует форму выдачи результата - младший байт по младшему адресу или старший байт по младшему адресу, нужно смотреть в инструкции какую форму выдает конкретное средство расчета хэша. В самом гост числа записаны одной строкой по аналогии с десятичной системой счисления, то есть старший байт в начале записи. Для указания в файле xml двоичных криптографических данных зарубежным стандартом также предлагается такой формат записи. Однако, для процессоров Intel исторически используется принцип хранения данных в памяти младший байт по младшему адресу. Разные средства используют разный подход.

Можно использовать стандартные примеры из стандарта гост-2012 для калибровки в какой форме возвращен результат. Навскидку правда я не нашел тестовые файлики с нужными строками. Для строки, что приведена в примере у меня получаются такие результаты:
Код:
1) \n остался как есть, не переведен в перевод строки:
997D40716B671649DB3D386EFAF2B4E6756DC8F2F294D3929FB81FFF5050ADC2
mX1AcWtnFknbPThu+vK05nVtyPLylNOSn7gf/1BQrcI=
С переворотом:
C2AD5050FF1FB89F92D394F2F2C86D75E6B4F2FA6E383DDB4916676B71407D99
wq1QUP8fuJ+S05Ty8shtdea08vpuOD3bSRZna3FAfZk=
2) \n заменен на символы 13 10
A990408559D02FBFBD79C66BA8ED0BCFFC81AB56D8E5B7C717A8B3F64F6884EA
qZBAhVnQL7+9ecZrqO0Lz/yBq1bY5bfHF6iz9k9ohOo=
С переворотом:
EA84684FF6B3A817C7B7E5D856AB81FCCF0BEDA86BC679BDBF2FD059854090A9
6oRoT/azqBfHt+XYVquB/M8L7ahrxnm9vy/QWYVAkKk=
3) \n заменен на символ 10
DC4A10B5F800D5BB2BF0CCDC00BF7C0C8B064ED38EAEE63F5F80AD9F79697B3B
3EoQtfgA1bsr8MzcAL98DIsGTtOOruY/X4Ctn3lpezs=
С переворотом:
3B7B69799FAD805F3FE6AE8ED34E068B0C7CBF00DCCCF02BBBD500F8B5104ADC
O3tpeZ+tgF8/5q6O004Giwx8vwDczPAru9UA+LUQStw=
Если не получился ни один вариант, то возможно передача строки некорректная. Если получились варианты с переворотом, не забудьте перевернуть. Насчет преобразования перевода строки - вопрос немного другой, к плагину/расширению отношения не имеет, зависит от самого языка программы.
Offline Dmitriy Chernyshov  
#187 Оставлено : 14 сентября 2021 г. 10:57:13(UTC)
Dmitriy Chernyshov

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Автор: two_oceans Перейти к цитате
Посмотрите, не получилась ли перевернутая строка, при необходимости просто переверните. Первый байт с последним, второй с предпоследним. Если результат объявлен как массив байтов и размер массива совпадает с размером результата, то reverse массива делает как раз что нужно.

Это, может показаться странным, но сам по себе гост не регламентирует форму выдачи результата - младший байт по младшему адресу или старший байт по младшему адресу, нужно смотреть в инструкции какую форму выдает конкретное средство расчета хэша. В самом гост числа записаны одной строкой по аналогии с десятичной системой счисления, то есть старший байт в начале записи. Для указания в файле xml двоичных криптографических данных зарубежным стандартом также предлагается такой формат записи. Однако, для процессоров Intel исторически используется принцип хранения данных в памяти младший байт по младшему адресу. Разные средства используют разный подход.

Можно использовать стандартные примеры из стандарта гост-2012 для калибровки в какой форме возвращен результат. Навскидку правда я не нашел тестовые файлики с нужными строками. Для строки, что приведена в примере у меня получаются такие результаты:
Код:
1) \n остался как есть, не переведен в перевод строки:
997D40716B671649DB3D386EFAF2B4E6756DC8F2F294D3929FB81FFF5050ADC2
mX1AcWtnFknbPThu+vK05nVtyPLylNOSn7gf/1BQrcI=
С переворотом:
C2AD5050FF1FB89F92D394F2F2C86D75E6B4F2FA6E383DDB4916676B71407D99
wq1QUP8fuJ+S05Ty8shtdea08vpuOD3bSRZna3FAfZk=
2) \n заменен на символы 13 10
A990408559D02FBFBD79C66BA8ED0BCFFC81AB56D8E5B7C717A8B3F64F6884EA
qZBAhVnQL7+9ecZrqO0Lz/yBq1bY5bfHF6iz9k9ohOo=
С переворотом:
EA84684FF6B3A817C7B7E5D856AB81FCCF0BEDA86BC679BDBF2FD059854090A9
6oRoT/azqBfHt+XYVquB/M8L7ahrxnm9vy/QWYVAkKk=
3) \n заменен на символ 10
DC4A10B5F800D5BB2BF0CCDC00BF7C0C8B064ED38EAEE63F5F80AD9F79697B3B
3EoQtfgA1bsr8MzcAL98DIsGTtOOruY/X4Ctn3lpezs=
С переворотом:
3B7B69799FAD805F3FE6AE8ED34E068B0C7CBF00DCCCF02BBBD500F8B5104ADC
O3tpeZ+tgF8/5q6O004Giwx8vwDczPAru9UA+LUQStw=
Если не получился ни один вариант, то возможно передача строки некорректная. Если получились варианты с переворотом, не забудьте перевернуть. Насчет преобразования перевода строки - вопрос немного другой, к плагину/расширению отношения не имеет, зависит от самого языка программы.


Пробую сейчас сделать приведенные варианты. И почему-то ни один у меня по хэшу не совпадает. Можете показать пример того, как получается хэш в Вашем случае?

UPD: Прочитал определенный блок документации, первый пример получился, буду идти дальше. Спасибо!

Отредактировано пользователем 14 сентября 2021 г. 11:54:15(UTC)  | Причина: Не указана

Offline Emin Aliev  
#188 Оставлено : 15 сентября 2021 г. 17:34:51(UTC)
Emin Aliev

Статус: Новичок

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

Добрый день! Подскажите как снять(не проверка, а именно снять) подпись PKCS7 с помощью pycades?
Offline Dmitriy Chernyshov  
#189 Оставлено : 16 сентября 2021 г. 14:50:12(UTC)
Dmitriy Chernyshov

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Автор: Dmitriy Chernyshov Перейти к цитате
Автор: two_oceans Перейти к цитате
Посмотрите, не получилась ли перевернутая строка, при необходимости просто переверните. Первый байт с последним, второй с предпоследним. Если результат объявлен как массив байтов и размер массива совпадает с размером результата, то reverse массива делает как раз что нужно.

Это, может показаться странным, но сам по себе гост не регламентирует форму выдачи результата - младший байт по младшему адресу или старший байт по младшему адресу, нужно смотреть в инструкции какую форму выдает конкретное средство расчета хэша. В самом гост числа записаны одной строкой по аналогии с десятичной системой счисления, то есть старший байт в начале записи. Для указания в файле xml двоичных криптографических данных зарубежным стандартом также предлагается такой формат записи. Однако, для процессоров Intel исторически используется принцип хранения данных в памяти младший байт по младшему адресу. Разные средства используют разный подход.

Можно использовать стандартные примеры из стандарта гост-2012 для калибровки в какой форме возвращен результат. Навскидку правда я не нашел тестовые файлики с нужными строками. Для строки, что приведена в примере у меня получаются такие результаты:
Код:
1) \n остался как есть, не переведен в перевод строки:
997D40716B671649DB3D386EFAF2B4E6756DC8F2F294D3929FB81FFF5050ADC2
mX1AcWtnFknbPThu+vK05nVtyPLylNOSn7gf/1BQrcI=
С переворотом:
C2AD5050FF1FB89F92D394F2F2C86D75E6B4F2FA6E383DDB4916676B71407D99
wq1QUP8fuJ+S05Ty8shtdea08vpuOD3bSRZna3FAfZk=
2) \n заменен на символы 13 10
A990408559D02FBFBD79C66BA8ED0BCFFC81AB56D8E5B7C717A8B3F64F6884EA
qZBAhVnQL7+9ecZrqO0Lz/yBq1bY5bfHF6iz9k9ohOo=
С переворотом:
EA84684FF6B3A817C7B7E5D856AB81FCCF0BEDA86BC679BDBF2FD059854090A9
6oRoT/azqBfHt+XYVquB/M8L7ahrxnm9vy/QWYVAkKk=
3) \n заменен на символ 10
DC4A10B5F800D5BB2BF0CCDC00BF7C0C8B064ED38EAEE63F5F80AD9F79697B3B
3EoQtfgA1bsr8MzcAL98DIsGTtOOruY/X4Ctn3lpezs=
С переворотом:
3B7B69799FAD805F3FE6AE8ED34E068B0C7CBF00DCCCF02BBBD500F8B5104ADC
O3tpeZ+tgF8/5q6O004Giwx8vwDczPAru9UA+LUQStw=
Если не получился ни один вариант, то возможно передача строки некорректная. Если получились варианты с переворотом, не забудьте перевернуть. Насчет преобразования перевода строки - вопрос немного другой, к плагину/расширению отношения не имеет, зависит от самого языка программы.


Пробую сейчас сделать приведенные варианты. И почему-то ни один у меня по хэшу не совпадает. Можете показать пример того, как получается хэш в Вашем случае?

UPD: Прочитал определенный блок документации, первый пример получился, буду идти дальше. Спасибо!



В итоге, победил первую часть, сошлись на замене \n. Но сейчас пошла вторая часть - у нас есть digest, теперь нужно получить подпись. И здесь я опять не совсем понимаю, что происходит в jcp:
Код:

fun makeSign(
    // Здесь получили digest
    val dataDigestValueBase64 = toBase64(dataDigestValue)
    // Здесь сформировали xml-строку
    val signInfoXml = formatSignedInfoXml(dataDigestValueBase64)
    // Здесь сформировали "базу" для подписи
    val signature = getSignature()
    val privateKey = getPrivateKey(currentCert.encoded)

    signature.initSign(privateKey)
    signature.update(signInfoXml.toByteArray())

    val sign = signature.sign()


private fun formatSignedInfoXml(digestValue: String): String {
        return "<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><CanonicalizationMethod Algorithm=\"$CANONICALIZATION_ALGORITHM\"></CanonicalizationMethod><SignatureMethod Algorithm=\"$GOSTR34102012_GOSTR34112012_256_URN\"></SignatureMethod><Reference URI=\"\"><DigestMethod Algorithm=\"$GOSTR34112012_256_URN\"></DigestMethod><DigestValue>$digestValue</DigestValue></Reference></SignedInfo>"
    }

private fun getSignature(): Signature {
        return Signature.getInstance("GOST3411_2012_256withGOST3410DH_2012_256", JCP_PROVIDER)
    }



Вот в момент получения getSignature мне непонятно, что это в итоге за подпись будет? Cades-BES? Или это RawSignature? И можно ли аналоги сделать на pycades?

Если судить дальше по примеру полученного base64 от подписи - это не Cades-BES:
Код:

6jmckUC/XFmmcE0xPq2ZS3x2XjRhyhp22eer2mNq9CeHccWHHoTv9aWQT+HAlQl85V3EfWvEZoBN1lOMUcVqew==

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

Offline Dmitriy Chernyshov  
#190 Оставлено : 17 сентября 2021 г. 0:00:51(UTC)
Dmitriy Chernyshov

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Автор: Dmitriy Chernyshov Перейти к цитате
Автор: Dmitriy Chernyshov Перейти к цитате
Автор: two_oceans Перейти к цитате
Посмотрите, не получилась ли перевернутая строка, при необходимости просто переверните. Первый байт с последним, второй с предпоследним. Если результат объявлен как массив байтов и размер массива совпадает с размером результата, то reverse массива делает как раз что нужно.

Это, может показаться странным, но сам по себе гост не регламентирует форму выдачи результата - младший байт по младшему адресу или старший байт по младшему адресу, нужно смотреть в инструкции какую форму выдает конкретное средство расчета хэша. В самом гост числа записаны одной строкой по аналогии с десятичной системой счисления, то есть старший байт в начале записи. Для указания в файле xml двоичных криптографических данных зарубежным стандартом также предлагается такой формат записи. Однако, для процессоров Intel исторически используется принцип хранения данных в памяти младший байт по младшему адресу. Разные средства используют разный подход.

Можно использовать стандартные примеры из стандарта гост-2012 для калибровки в какой форме возвращен результат. Навскидку правда я не нашел тестовые файлики с нужными строками. Для строки, что приведена в примере у меня получаются такие результаты:
Код:
1) \n остался как есть, не переведен в перевод строки:
997D40716B671649DB3D386EFAF2B4E6756DC8F2F294D3929FB81FFF5050ADC2
mX1AcWtnFknbPThu+vK05nVtyPLylNOSn7gf/1BQrcI=
С переворотом:
C2AD5050FF1FB89F92D394F2F2C86D75E6B4F2FA6E383DDB4916676B71407D99
wq1QUP8fuJ+S05Ty8shtdea08vpuOD3bSRZna3FAfZk=
2) \n заменен на символы 13 10
A990408559D02FBFBD79C66BA8ED0BCFFC81AB56D8E5B7C717A8B3F64F6884EA
qZBAhVnQL7+9ecZrqO0Lz/yBq1bY5bfHF6iz9k9ohOo=
С переворотом:
EA84684FF6B3A817C7B7E5D856AB81FCCF0BEDA86BC679BDBF2FD059854090A9
6oRoT/azqBfHt+XYVquB/M8L7ahrxnm9vy/QWYVAkKk=
3) \n заменен на символ 10
DC4A10B5F800D5BB2BF0CCDC00BF7C0C8B064ED38EAEE63F5F80AD9F79697B3B
3EoQtfgA1bsr8MzcAL98DIsGTtOOruY/X4Ctn3lpezs=
С переворотом:
3B7B69799FAD805F3FE6AE8ED34E068B0C7CBF00DCCCF02BBBD500F8B5104ADC
O3tpeZ+tgF8/5q6O004Giwx8vwDczPAru9UA+LUQStw=
Если не получился ни один вариант, то возможно передача строки некорректная. Если получились варианты с переворотом, не забудьте перевернуть. Насчет преобразования перевода строки - вопрос немного другой, к плагину/расширению отношения не имеет, зависит от самого языка программы.


Пробую сейчас сделать приведенные варианты. И почему-то ни один у меня по хэшу не совпадает. Можете показать пример того, как получается хэш в Вашем случае?

UPD: Прочитал определенный блок документации, первый пример получился, буду идти дальше. Спасибо!



В итоге, победил первую часть, сошлись на замене \n. Но сейчас пошла вторая часть - у нас есть digest, теперь нужно получить подпись. И здесь я опять не совсем понимаю, что происходит в jcp:
Код:

fun makeSign(
    // Здесь получили digest
    val dataDigestValueBase64 = toBase64(dataDigestValue)
    // Здесь сформировали xml-строку
    val signInfoXml = formatSignedInfoXml(dataDigestValueBase64)
    // Здесь сформировали "базу" для подписи
    val signature = getSignature()
    val privateKey = getPrivateKey(currentCert.encoded)

    signature.initSign(privateKey)
    signature.update(signInfoXml.toByteArray())

    val sign = signature.sign()


private fun formatSignedInfoXml(digestValue: String): String {
        return "<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><CanonicalizationMethod Algorithm=\"$CANONICALIZATION_ALGORITHM\"></CanonicalizationMethod><SignatureMethod Algorithm=\"$GOSTR34102012_GOSTR34112012_256_URN\"></SignatureMethod><Reference URI=\"\"><DigestMethod Algorithm=\"$GOSTR34112012_256_URN\"></DigestMethod><DigestValue>$digestValue</DigestValue></Reference></SignedInfo>"
    }

private fun getSignature(): Signature {
        return Signature.getInstance("GOST3411_2012_256withGOST3410DH_2012_256", JCP_PROVIDER)
    }



Вот в момент получения getSignature мне непонятно, что это в итоге за подпись будет? Cades-BES? Или это RawSignature? И можно ли аналоги сделать на pycades?

Если судить дальше по примеру полученного base64 от подписи - это не Cades-BES:
Код:

6jmckUC/XFmmcE0xPq2ZS3x2XjRhyhp22eer2mNq9CeHccWHHoTv9aWQT+HAlQl85V3EfWvEZoBN1lOMUcVqew==



UPD: Попробовал разные варианты, и если я правильно понимаю, то это RawSignature, в которой подписали хеш SignedInfo. Так ли это?
Offline two_oceans  
#191 Оставлено : 17 сентября 2021 г. 13:31:29(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 90 раз
Поблагодарили: 319 раз в 300 постах
Цитата:
UPD: Попробовал разные варианты, и если я правильно понимаю, то это RawSignature, в которой подписали хеш SignedInfo. Так ли это?
Добрый день. По стандарту да.
Подпись гост включает в себя случайное значение, так что меняется каждый раз даже если данные и ключ не изменились. Более того, для гост не описан алгоритм как по значению подписи восстановить хэш (проверка подписи основана на другом принципе), поэтому и промежуточный хэш от SignedInfo заранее нам неизвестен.
Что происходит у них - неизвестно, так как Java класс могли переопределить и там может произойти все что угодно. Как я понимаю, обычно это все в одной строке:
Код:
signature.initSign(privateKey)
    signature.update(signInfoXml.toByteArray())
    val sign = signature.sign()
Судите сами по краткому пересказу стандарта (подпись собирается сразу в документе без формирования кусками и и вставки в каркас):
thanks 1 пользователь поблагодарил two_oceans за этот пост.
Андрей * оставлено 17.09.2021(UTC)
Offline Санчир Момолдаев  
#192 Оставлено : 27 сентября 2021 г. 21:58:59(UTC)
Санчир Момолдаев

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

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

Сказал(а) «Спасибо»: 70 раз
Поблагодарили: 166 раз в 162 постах
Автор: Dmitriy Chernyshov Перейти к цитате

И можно ли аналоги сделать на pycades?

Здравствуйте!
если актуально
Код:
# хэширование текстовых или байтовых данных
def gostHash(data, isText=True):
    hashedData = pycades.HashedData()
    hashedData.Algorithm = pycades.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_256
    hashedData.DataEncoding = pycades.CADESCOM_BASE64_TO_BINARY
    if isText:
        hashedData.Hash(base64.b64encode(data.encode("utf-8")).decode())
    else:
        hashedData.Hash(base64.b64encode(data).decode())
    hexHash = hashedData.Value
    byteHash = bytes.fromhex(hexHash)
    return base64.b64encode(byteHash).decode()

# само значение подписи.
# возвращать надо либо signature либо invert в зависимости от принимающей стороны
def signHash(cert, hashBase64):
    hashValue = base64.b64decode(hashBase64)
    hashValue = hashValue.hex()
    hashedData = pycades.HashedData()
    hashedData.Algorithm = pycades.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_256
    hashedData.DataEncoding = pycades.CADESCOM_BASE64_TO_BINARY
    hashedData.SetHashValue(hashValue)
    rawSign = pycades.RawSignature()
    signature = rawSign.SignHash(hashedData, cert)
    invert = bytearray(reversed(bytearray.fromhex(signature)))
    invert = base64.b64encode(invert).decode()
    signature = bytes.fromhex(signature)
    signature = base64.b64encode(signature).decode()
    # return signature
    return invert



Техническую поддержку оказываем тут
Наша база знаний
Offline mczim  
#193 Оставлено : 7 октября 2021 г. 20:19:56(UTC)
mczim

Статус: Новичок

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

Добрый вечер. Есть зашифрованный, подписанный документ. Как мне в питоне расшифровать и вынуть подписанный документ?

Расшифровываю так.

Код:
store = pycades.Store()
store.Open(pycades.CADESCOM_CURRENT_USER_STORE, pycades.CAPICOM_MY_STORE, pycades.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
certs = store.Certificates
assert(certs.Count != 0), "Certificates with private key not found"

with open('20210917_1.xml.sig.enc', 'r') as f:
    file_content = f.read()

envelopedData = pycades.EnvelopedData()
envelopedData.Decrypt(file_content)
content = envelopedData.Content


в file_content как я понимаю подписанный документ. Как мне его вынуть оттуда?

В ОС linux это две команды

bin/cryptcp -decr -nochain -norev -1 -dn 'CN=...' -start 20210917_1.xml.sig.enc 20210917_1.xml.sig
bin/cryptcp -verify -nochain -norev 20210917_1.xml.sig 20210917_1.xml

Как тоже самое сделать в питоне?

Спасибо.
Offline mczim  
#194 Оставлено : 7 октября 2021 г. 20:47:18(UTC)
mczim

Статус: Новичок

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

Насколько понимаю нужно делать так

Код:
signed_data = pycades.SignedData()
result = signed_data.VerifyCades(content, pycades.CADESCOM_CADES_BES)


Но, теперь получаю ошибку

Код:
    result = signed_data.VerifyCades(content, pycades.CADESCOM_CADES_T)
Exception: Internal error. (0x8009100E)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
10 Страницы«<8910
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.