|
Интеграция с Честным Знаком | ☑ | ||
---|---|---|---|---|
0
1СникСоСтажем
14.05.22
✎
18:23
|
Всем привет! Делаю интеграцию 1с с честным знаком. Задача получать входящие документы и их подписывать.
1. Ключ сессии (/api/v1/session) получаю вполне корректно, Честный знак принимает подпись 2. Входящие документы получаю корректно, но при попытке подписи документов (api/v1/incoming-documents/xml/upd/title) ошибка "Подпись не прошла проверку в crypto" (хотя при получении ключа сессии все нормально) Ниже пример использования: ПодписатьТекст(ЗашифроватьBase64(ФайлXML, "windows-1251"),Отпечаток,Истина); // sThumbprint - отпечаток сертификата, используемого для подписи; строка, // представляющая отпечаток в шестнадцатеричном виде // пример 195934d72dcdf69149901d6632aca4562d8806d8 // ТекстДляПодписи должен быть в Base64 // bDetached - Истина/Ложь - откреплённая(для подписания документов)/прикреплённая(для получения токена авторизации) подпись Функция ПодписатьТекст(ТекстДляПодписи, sThumbprint, bDetached) CADESCOM_BASE64_TO_BINARY = 1; // Входные данные пришли в Base64 CADESCOM_CADES_TYPE = 1; // Тип усовершенствованной подписи CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0; // Атрибут штампа времени подписи oSigner = Новый COMОбъект("CAdESCOM.CPSigner"); // Объект, задающий параметры создания и содержащий информацию об усовершенствованной подписи. oSigner.Certificate = ПолучитьСертификатПоОтпечатку(sThumbprint); oSigningTimeAttr = Новый COMОбъект("CAdESCOM.CPAttribute"); oSigningTimeAttr.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME; oSigningTimeAttr.Value = ТекущаяДата(); oSigner.AuthenticatedAttributes2.Add(oSigningTimeAttr); ТекстДляПодписи = СокрЛП(ТекстДляПодписи); oSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData"); // Объект CadesSignedData предоставляет свойства и методы для работы с усовершенствованной подписью. oSignedData.ContentEncoding = CADESCOM_BASE64_TO_BINARY; //oSignedData.propset_ContentEncoding = CADESCOM_BASE64_TO_BINARY; oSignedData.Content = СокрЛП(ТекстДляПодписи); EncodingType = 0; sSignedMessage = oSignedData.SignCades(oSigner, CADESCOM_CADES_TYPE, bDetached, EncodingType); // Метод добавляет к сообщению усовершенствованную подпись. sSignedMessage = СтрЗаменить(sSignedMessage,Символы.ПС,""); sSignedMessage = СтрЗаменить(sSignedMessage,Символы.ВК,""); Возврат sSignedMessage; // Подпись в формате Base64 КонецФункции //Отпечаток - строка HEX Функция ПолучитьСертификатПоОтпечатку(ОтпечатокСтр) Рез = Неопределено; // Найденный сертификат (Com-объект) CAPICOM_CURRENT_USER_STORE = 2; //2 - Искать сертификат в ветке "Личное" хранилища. CAPICOM_MY_STORE = "My"; // Указываем, что ветку "Личное" берем из хранилища текущего пользователя CAPICOM_STORE_OPEN_READ_ONLY = 0; // Открыть хранилище только на чтение oStore = Новый COMОбъект("CAdESCOM.Store"); // Объект описывает хранилище сертификатов oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY); // Открыть хранилище сертификатов // 1 вариант: поиск сертификата по отпечатку //CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0; //Certificates = oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, ОтпечатокСтр); //Рез = Certificates.Item(1); //2 вариант: обходом по коллекции и сравнение с отпечатком Для Каждого ТекСертификат Из oStore.Certificates Цикл ТекОтпечаток = ТекСертификат.Thumbprint; // возвращается отпечаток в шестнадцатеричном виде Если ВРЕГ(ТекОтпечаток) = ВРЕГ(ОтпечатокСтр) Тогда Рез = ТекСертификат; Прервать; КонецЕсли; КонецЦикла; oStore.Close(); // Закрыть хранилище сертификатов и освободить объект 61 Возврат Рез; КонецФункции ТекстДляПодписи - содержание XML файла У клиента менялся сертификат, может быть в этом причина? Хотя при "ручном" подписании ошибок нет. Кто сталкивался? Отзовитесь плиз..... |
|||
1
NorthWind
14.05.22
✎
18:29
|
А штамп времени там реально нужен?
|
|||
2
NorthWind
14.05.22
✎
18:33
|
у меня есть образец рабочего кода такой фигни, но там простая подпись CADES_BES, без штампа времени. Здесь используется штамп времени, но я что-то не уверен, что он применяется у Честного знака, во всяком случае, упоминаний об этом я не нашел. Он там применяется или нет?
|
|||
3
1СникСоСтажем
14.05.22
✎
19:04
|
(2) добрый день! Хороший вопрос! Кол не мой. Предлагаете штамм времени опустить? У Вас что - то аналогичное используется в реализации?
|
|||
4
NorthWind
14.05.22
✎
19:27
|
(3) а ключ сессии вы этим же методом подписываете?
|
|||
5
1СникСоСтажем
14.05.22
✎
20:00
|
(4) ну да.bDetached Ложь только. Там в описании функции указано.
|
|||
6
timurhv
14.05.22
✎
20:10
|
Куда сейчас документацию API выкладывают? Раньше в телеге выкладывали, сейчас - фиг разберешься.
Исходный xml отправляете ведь с подписанным? Через base64Строка прогнать и отправить? |
|||
7
1СникСоСтажем
14.05.22
✎
21:27
|
(6) у нах сайт лёг кстати. Успел вытащить описание до санкций.
Да, файл покупателя уже с подписанным файлом от продавца. Вначале в base64, а потом уже подписываем. Плюс в тело post запроса подпись самого файла от покупателя. Попробую без CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME. Отпишусь. Думаю, что всем полезно знать решение |
|||
8
1СникСоСтажем
14.05.22
✎
23:02
|
(2)
Решил отказаться от штамма времени в алгоритме при подписании документов: Функция ПодписатьТекст(ТекстДляПодписи, sThumbprint, bDetached) CADESCOM_BASE64_TO_BINARY = 1; // Входные данные пришли в Base64 CADESCOM_CADES_TYPE = 1; // Тип усовершенствованной подписи //CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0; // Атрибут штампа времени подписи oSigner = Новый COMОбъект("CAdESCOM.CPSigner"); // Объект, задающий параметры создания и содержащий информацию об усовершенствованной подписи. oSigner.Certificate = ПолучитьСертификатПоОтпечатку(sThumbprint); // при подписании документов не используем штамп времени Если Не bDetached Тогда oSigningTimeAttr = Новый COMОбъект("CAdESCOM.CPAttribute"); oSigningTimeAttr.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME; oSigningTimeAttr.Value = ТекущаяДатаСеанса(); oSigner.AuthenticatedAttributes2.Add(oSigningTimeAttr); КонецЕсли; ТекстДляПодписи = СокрЛП(ТекстДляПодписи); oSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData"); // Объект CadesSignedData предоставляет свойства и методы для работы с усовершенствованной подписью. oSignedData.ContentEncoding = CADESCOM_BASE64_TO_BINARY; //oSignedData.propset_ContentEncoding = CADESCOM_BASE64_TO_BINARY; oSignedData.Content = СокрЛП(ТекстДляПодписи); EncodingType = 0; sSignedMessage = oSignedData.SignCades(oSigner, CADESCOM_CADES_TYPE, bDetached, EncodingType); // Метод добавляет к сообщению усовершенствованную подпись. sSignedMessage = СтрЗаменить(sSignedMessage,Символы.ПС,""); sSignedMessage = СтрЗаменить(sSignedMessage,Символы.ВК,""); Возврат sSignedMessage; // Подпись в формате Base64 КонецФункции Но ничего не изменилось. А Вы говорили, что у Вас есть рабочий код для подписи? Можете поделиться? Спасибо |
|||
9
H A D G E H O G s
14.05.22
✎
23:08
|
Каждый раз читаю это и каждый раз благодарю судьбу, что мы отказались поддерживать ЧЗ.
|
|||
10
H A D G E H O G s
14.05.22
✎
23:11
|
Создателям этой жлыги можно пожелать встретить голландскую шхуну..
|
|||
11
timurhv
14.05.22
✎
23:16
|
(9) В БСП 1 функция вызывается. Но у автора, видимо, свой велосипед
|
|||
12
H A D G E H O G s
14.05.22
✎
23:20
|
(11) Да понятно, что в БСП одна функция, но что-то иногда идет не так. И это не отменяет ебаклакизм ЧЗ, которые забили на запилить приложуху на стороне клиента или хотя бы dll.
|
|||
13
1СникСоСтажем
14.05.22
✎
23:58
|
(11)
Не всегда БСПшные функции работают корректно. Велосипед, да. Но нужно в нем разобраться. |
|||
14
1СникСоСтажем
14.05.22
✎
23:58
|
(12)
Тут согласен полностью. Но имеем то, что имеем. |
|||
15
NorthWind
15.05.22
✎
09:22
|
(8)
def find_cert(self, hash_str): """ ищет сертификат в хранилище сертификатов по его sha1-отпечатку """ current_user_store = 2 my_store = "my" store_open_read_only = 0 capicom_certificate_find_sha1_hash = 0 store = win32com.client.Dispatch("CADESCOM.store") store.Open(current_user_store, my_store, store_open_read_only) certs = store.Certificates.Find(capicom_certificate_find_sha1_hash, hash_str) if certs.Count > 0: self.cert = certs.Item(1) # --------------------------------------------------------------------------------------------------------------- def sign(self, filename: str, prefix: str): """ подписывает файл с переданным именем """ cades_bes = 1 capicom_encode_base64 = 0 capicom_certificate_include_end_entity_only = 2 sign_filename = self.get_bin_filename(filename, prefix) signer = win32com.client.Dispatch("CADESCOM.CpSigner") signer.Certificate = self.cert signer.Options = capicom_certificate_include_end_entity_only signed_data = win32com.client.Dispatch("CADESCOM.CadesSignedData") f_in = open(filename, 'rb') signed_data.Content = f_in.read() out_data = signed_data.SignCades(signer, cades_bes, True, capicom_encode_base64) f_out = open(sign_filename, 'wt') f_out.write(out_data) f_in.close() f_out.close() |
|||
16
1СникСоСтажем
15.05.22
✎
10:40
|
(15)
Доброе утро! Что это за язык программирования? Думал пример на 1с :) 1. Поиск сертификата по sha-1 обязательно искать? У меня просто идёт поиск по коллекции сертификатов. 2. А self, win32com и prefix что означают? |
|||
17
NorthWind
15.05.22
✎
11:08
|
(16) это python.
Поиск сертификата есть и у вас, реализован практически точно так же как и в моем случае. win32com.client это механизм для работы с COM-объектами на python, то же самое что Новый COMОбъект () в 1С. prefix это строчка, которая добавляется слева к имени файла подписи, для ваших целей это вряд ли нужно. Вообще у вас вполне нормальный код, только он сильно замусорен непонятно зачем нужными опциями: сертификат ищется двумя способами, к подписи добавляются какие-то атрибуты и штамп времени... Возможно, все это нужно ЧЗ. Или нет? У меня на этот счет сомнения. |
|||
18
1СникСоСтажем
15.05.22
✎
11:38
|
(17)
Смотрю да. Надо короче пробовать. Но мы же текстовое содержимое файлов xml файлов подписываем? Пробовал уйти от времени - результат тот же. Подумаем короче... |
|||
19
1СникСоСтажем
15.05.22
✎
11:39
|
(17)
Сам алгоритм то рабочий, сессию же я получаю без проблем. Проблемы с подписью документов. |
|||
20
timurhv
15.05.22
✎
13:11
|
(19) Для токена:
ПараметрыCMS = ЭлектроннаяПодписьКлиент.ПараметрыCMS(); ПараметрыCMS.Открепленная = Ложь; Для Национальный каталог, True Api, ГИС МТ: ПараметрыCMS.Открепленная = Истина; |
|||
21
1СникСоСтажем
15.05.22
✎
13:45
|
(20)
Добрый день! А подробнее можно? Куда этот параметр CMS вставить? |
|||
22
1СникСоСтажем
15.05.22
✎
18:04
|
Причем сверил сам отпечаток. Полностью совпадает с тем, как тут получают. Так что проблем серфикатом быть не должно
ДанныеСертификата = Сертификат.ДанныеСертификата.Получить(); ск = Новый СертификатКриптографии(ДанныеСертификата); Отпечаток = ПолучитьHexСтрокуИзДвоичныхДанных(ск.Отпечаток); Ниже код, как я заполняю справочников сертификатов (отдельный сделал, БСПшный не стал использовать): ОбъектСертификат.Наименование = ВладелецСертификата; ОбъектСертификат.ВладелецСертификата = ВладелецСертификата; ОбъектСертификат.ДатаНачала = ТекСертификат.ValidFromDate; ОбъектСертификат.ДатаОкончания = ТекСертификат.ValidToDate; ОбъектСертификат.Контейнер = ТекСертификат.PrivateKey.UniqueContainerName; ОбъектСертификат.Отпечаток = ТекСертификат.Thumbprint; ОбъектСертификат.Записать(); Отказался от CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME. результат тот же... |
|||
23
1СникСоСтажем
16.05.22
✎
00:40
|
Народ, тут до меня дошло, что нужно использовать "Новый МенеджерКриптографии" (мне же открепленная подпись нужна). Тут вопрос по параметрам? Где их взять? У кого - нибудь есть рабочий пример?
|
|||
24
1СникСоСтажем
16.05.22
✎
00:54
|
Вот код:
Функция ПодписатьТекстОтсоединеннаяПодпись(ТекстДляПодписи,Отпечаток) ФайлСПодписями = ПолучитьИмяВременногоФайла("txt"); МенеджерКриптографии = Новый МенеджерКриптографии("Microsoft Enhanced Cryptographic Provider v1.0","",1); Хранилище = МенеджерКриптографии.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); Сертификат = Хранилище.НайтиПоОтпечатку(ПолучитьДвоичныеДанныеИзHexСтроки(Отпечаток)); ДД_Подпись = МенеджерКриптографии.Подписать(ТекстДляПодписи,ФайлСПодписями,Сертификат); Возврат ПолучитьСтрокуИзДвоичныхДанных(ДД_Подпись,"windows-1251"); КонецФункции // ПодписатьТекстОтсоединеннаяПодпись() Но получаю ошибку: ОбщийМодуль.vvoИнтеграция.Модуль(986)}: Ошибка при вызове метода контекста (Подписать) ДД_Подпись = МенеджерКриптографии.Подписать(ТекстДляПодписи,ФайлСПодписями,Сертификат); по причине: Ошибка операции с файлом. по причине: Каталог не обнаружен 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0id2luZG93cy0xMjUxIiA\Pg0KPNTg6esgwuXw8c\w7uM9ItHB6NEzIiDC5fDx1O7w7D0iNS4wMSIgyOTU4OnrPSJPTl9OU.... Там очень длинный текст. Как заставить его работать? |
|||
25
Тихий омут
16.05.22
✎
03:37
|
Использую для ГИИС, но может, найдёшь что полезное.
Стр - ссылка на эл. справочника СертификатыКлючейЭлектроннойПодписиИШифрования Код на базе БСП 3.1.5.385 КриптоСертификат=Новый СертификатКриптографии(Стр.ДанныеСертификата.Получить()); //двоичные данные сертификата МенеджерКриптографии=Новый МенеджерКриптографии(Стр.СертификатИмяПрограммы,"",Стр.СертификатТипПрограммы); //из того же справочника ПараметрыXMLDSig=ЭлектроннаяПодписьСлужебныйКлиентСервер.ПараметрыXMLDSig(); МенеджерКриптографии.ПарольДоступаКЗакрытомуКлючу="****"; ПодписанныйПакет=ЭлектроннаяПодписьСлужебный.Подписать(ТелоПакета,ПараметрыXMLDSig,КриптоСертификат,МенеджерКриптографии); |
|||
26
NorthWind
16.05.22
✎
08:24
|
(24) судя по строке ошибки, вы задаете само содержимое подписи в виде строки base64 в качестве имени файла, и пытаетесь такой файл сохранить.
|
|||
27
1СникСоСтажем
16.05.22
✎
22:42
|
(26)
Добрый день! Именно так и есть, хотя бы подпись получил. Ниже код, как я это делаю. Причем ФайлXML_ДД - двоичные данные XML файла. Если отправлять содержимое XML файла - то будет ошибка, описанная выше. То есть вначале подпись, а потом уже ее в Base64/ На что еще обратить внимание? Подписываю файл продавца и титул покупателя одинаково ПодписатьТекстОтсоединеннаяПодпись(ФайлXML_ДД,Отпечаток) Функция ПодписатьТекстОтсоединеннаяПодпись(Файл_ДД,Отпечаток) МенеджерКриптографии = Новый МенеджерКриптографии("Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider","",80); Хранилище = МенеджерКриптографии.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); Сертификат = Хранилище.НайтиПоОтпечатку(ПолучитьДвоичныеДанныеИзHexСтроки(Отпечаток)); ДД_Подпись = МенеджерКриптографии.Подписать(Файл_ДД,Сертификат); Результат = Base64Строка(ДД_Подпись); Если Лев(Результат, 4) = "77u/" Тогда Результат = Сред(Результат, 5); КонецЕсли; Результат = СтрЗаменить(Результат, Символы.ПС, ""); Результат = СтрЗаменить(Результат, Символы.ВК, ""); Возврат Результат; КонецФункции // ПодписатьТекстОтсоединеннаяПодпись() |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |