Подпись для 1с 7.7 (CAPICOM vs CAdESCOM) под х64 ОС.
Для решения ряда проблем с библиотеками в рамках платформы 1с 7.7 представлен вариант обработки для подписи (формирования сигнатуры ) сообщений. Signature
— электронная подпись в формате CMS SignedData в DER-кодировке. Тесты проводились на клиентском ПК с ОС Win10 x64 и настройками ключа ЭЦП под работу в ЛК операторов ЭДО и сервисов ГИСМТ, КриптоПро SCP 5.0.13000 КС1. Принципиально было добиться работы CAPICOM в данном окружении, заявленный как устаревший элемент управления, но по факту он под капотом у CAdESCOM. CAdESCOM же в свою очередь в тех же условиях настроенной ОС не выводит списка сертификатов, ошибка на этапе открытия CAdESCOM.Store, решено взять рабочие примеры с использование JavaScript из 1с 8.х. В скриптах модифицирован возврат xbase64 строки в код обработки, для более простого переброса в тело запросов, требующих сигнатуру представить в данной кодировке. функция для кодирования в xbase64, может быть заменен на встроенную в CAPICOM.Utilities.Base64Encode(Str), вмеcто использования объекта CDO.Message. В обработку так же включен пример отправки сообщения XML через HTTP API c добавленной сигнатурой. Отмечу, что саму сигнатуру после сохранения в файл *.sig можно проверить инструментом криптопро cptools.
пример формирования подписи/сигнатуры (фрагмент):
Функция Base64Encoder(ИмяФайла)
CDO=СоздатьОбъект("CDO.Message");
Attachment=CDO.AddAttachment(ИмяФайла);
Attachment.ContentTransferEncoding="base64";
Стр=Attachment.GetEncodedContentStream();
Возврат Стр.ReadText();
КонецФункции
Функция ПодписатьФайл(ИмяФайла,ВыбСертификат,ИмяВыхФайла)
сообщить(ИмяФайла);
Попытка
JS=СоздатьОбъект("MSScriptControl.ScriptControl");
JS.Language="javascript";
Исключение
ТекстОшибки=ОписаниеОшибки();
Сообщить("Не удалось создать объект MSScriptControl.ScriptControl","!");
Сообщить("Описание ошибки: "+ТекстОшибки,"!");
Возврат 0;
КонецПопытки;
Попытка
СтрКода="function SignFile(FileName,Cert,OutFileName)
|{
| InStream=new ActiveXObject(""ADODB.Stream"");
| InStream.Type=1; // binary data
| InStream.Mode=3; // read/write
| InStream.Open();
| InStream.LoadFromFile(FileName);
| InData=InStream.Read(-1);
| Signer=new ActiveXObject(""CAPICOM.Signer"");
| Signer.Certificate=Cert;
| Signer.Options=2;
| SignedData=new ActiveXObject(""CAPICOM.SignedData"");
| SignedData.Content=InData;
| OutSignedData=SignedData.Sign(Signer,1,0);
|
| OutStream=new ActiveXObject(""ADODB.Stream"");
| OutStream.Charset = ""ASCII"";
| OutStream.Open();
| OutStream.Type=2; // text data
| OutStream.WriteText(OutSignedData);
| OutStream.SaveToFile(OutFileName,2);
| OutStream.Close();
|
| return(OutSignedData);
|}
|";
JS.AddCode(СтрКода);
Рез=JS.Modules("Global").CodeObject.SignFile(ИмяФайла,ВыбСертификат,ИмяВыхФайла);
сообщить(лев(Рез,255));
Исключение
ТекстОшибки=ОписаниеОшибки();
Сообщить("Произошла ошибка при подписи файла!","!");
Сообщить("Описание ошибки: "+ТекстОшибки,"!");
Возврат 0;
КонецПопытки;
Возврат Рез;
КонецФункции
функция ПодписьФайла(ПутьКФайлу,ПоказыватьНастройки=1)
ПравильноеЧислоПолучателей=1;
ИмяНастроек="Подпись_";
// CAPICOM constants
CAPICOM_CURRENT_USER_STORE=2;
CAPICOM_MY_STORE="My";
CAPICOM_STORE_OPEN_READ_ONLY=0;
CAPICOM_CERTIFICATE_FIND_TIME_VALID=9;
ТекДата=ТекущаяДата();
СохранённыйОтпечатокСертификата="";
// восстанавливаем настройки
Попытка
НастройкиПодписи=ВосстановитьЗначение(ИмяНастроек);
Если ТипЗначенияСтр(НастройкиПодписи)="СписокЗначений" Тогда
СохранённыйОтпечатокСертификата=НастройкиПодписи.Получить("ОтпечатокСертификата");
КонецЕсли;
Исключение
КонецПопытки;
СписокНашихСертификатов=СоздатьОбъект("СписокЗначений");
ВыбСертификатЭЦП="";
Попытка
Store = CreateObject("CAPICOM.Store");
//comCPSigner = CreateObject("CAPICOM.Signer");
//comSignedData = CreateObject("CAPICOM.SignedData");
//Store = CreateObject("CAdESCOM.Store");
//comCPSigner = CreateObject("CAdESCOM.CPSigner");
//comSignedData = CreateObject("CAdESCOM.CadesSignedData");
CURRENT_USER_STORE = 2;
MY_STORE = "My";
STORE_OPEN_READ_ONLY = 0;
//Store.Open(CURRENT_USER_STORE, MY_STORE, STORE_OPEN_READ_ONLY);
Store.Open(CAPICOM_CURRENT_USER_STORE,CAPICOM_MY_STORE,CAPICOM_STORE_OPEN_READ_ONLY);
Certs=Store.Certificates;
ValidCerts=Certs.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID,ТекущаяДата(),-1);
Для CertNum=1 По ValidCerts.Count Цикл
CurCert=ValidCerts.Item(CertNum);
Thumbprint =CurCert.Thumbprint;
SerialNumber =CurCert.SerialNumber;
SubjectName =CurCert.SubjectName;
ValidFromDate=CurCert.ValidFromDate;
ValidToDate =CurCert.ValidToDate;
ПредставлениеСертификата=ПолучитьПредставлениеСертификата(SubjectName);
ПредставлениеСертификата=ПредставлениеСертификата+", с "+Формат(ValidFromDate,"Д ДДММГГГГ")+" по "+Формат(ValidToDate,"Д ДДММГГГГ");
СписокНашихСертификатов.ДобавитьЗначение(CurCert,ПредставлениеСертификата);
Если (Thumbprint=СохранённыйОтпечатокСертификата) Тогда
ВыбСертификатЭЦП = CurCert;
//comCPSigner.Certificate = ВыбСертификатЭЦП;
//comCPSigner.Options = 2;
//comSignedData.Content = СодержимоеФайла;
//ПодписанныеДанные = comSignedData.Sign(comCPSigner, 1, 0);
//ПодписанныеДанные = comSignedData.SignCades(comCPSigner, 1, "true", );
ПодписанныеДанные = ПодписатьФайл(ПутьКФайлу, ВыбСертификатЭЦП, ПутьКФайлу+".sig");
//сообщить(лев(ПодписанныеДанные,250));
возврат ПодписанныеДанные;
КонецЕсли;
КонецЦикла;
Исключение
ТекстОшибки=ОписаниеОшибки();
Сообщить("Произошла ошибка при работе с хранилищем сертификатов! (Возможно, не установлен модуль CAPICOM)","!");
Сообщить("Описание ошибки: "+ТекстОшибки,"!");
Возврат 0;
КонецПопытки;
конецфункции
Подпись для 1с 8.3 (CAPICOM vs CAdESCOM) под х64 ОС.
Реализация подписи для 8ки обратная версии 7.7, драйвер CAPICOM по дефолту х32 и как правило установленная 1с платформа х64 его не видит. Переключаемся на CAdESCOM инсталлированием драйвера cadescom-x64.msi, т.к одних настроек под работу в ЛК ЭДО не достаточно. В отличии от 7ки скрипты можно не использовать и вызвать методы подписи из com-объекта. Из минусов такой реализации сигнатура при сохранении не подлежит проверке в криптопро cptools, и сохранение в файл *.sig выполнено аналогично через "ADODB.Stream" com-объект.
пример подписи 8.х (фрагмент):
функция ПодписьФайла(СодержимоеФайла)
Попытка
// CAPICOM constants
//CAPICOM_CURRENT_USER_STORE=2;
//CAPICOM_MY_STORE="My";
//CAPICOM_STORE_OPEN_READ_ONLY=0;
CAPICOM_CERTIFICATE_FIND_TIME_VALID=9;
//Store = Новый COMОбъект("CAPICOM.Store");
//comCPSigner = Новый COMОбъект("CAPICOM.Signer");
//comSignedData = Новый COMОбъект("CAPICOM.SignedData");
//Store.Open(CAPICOM_CURRENT_USER_STORE,CAPICOM_MY_STORE,CAPICOM_STORE_OPEN_READ_ONLY);
Store = Новый COMОбъект("CAdESCOM.Store");
comCPSigner = Новый COMОбъект("CAdESCOM.CPSigner");
comSignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
CURRENT_USER_STORE = 2;
MY_STORE = "My";
STORE_OPEN_READ_ONLY = 0;
Store.Open(CURRENT_USER_STORE, MY_STORE, STORE_OPEN_READ_ONLY);
Certs=Store.Certificates;
ValidCerts=Certs.Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID,ТекущаяДата(),-1);
Для CertNum=1 По ValidCerts.Count Цикл
CurCert =ValidCerts.Item(CertNum);
Thumbprint =CurCert.Thumbprint;
SerialNumber =CurCert.SerialNumber;
SubjectName =CurCert.SubjectName;
ValidFromDate=CurCert.ValidFromDate;
ValidToDate =CurCert.ValidToDate;
сообщить(SerialNumber);
Если SerialNumber="xxx" Тогда
ВыбСертификатЭЦП = CurCert;
comCPSigner.Certificate = ВыбСертификатЭЦП;
comCPSigner.Options = 2;
comSignedData.ContentEncoding = 1;
comSignedData.Content = СодержимоеФайла;
//ПодписанныеДанные = comSignedData.Sign(comCPSigner, 1, 0);
ПодписанныеДанные = comSignedData.SignCades(comCPSigner, 1, "true", );
//сообщить(лев(ПодписанныеДанные,250));
//Сообщить("Файл подписан!");
возврат ПодписанныеДанные;
КонецЕсли;
КонецЦикла;
Исключение
ТекстОшибки=ОписаниеОшибки();
Сообщить("Произошла ошибка при работе с хранилищем сертификатов! (Возможно, не установлен модуль CAPICOM)");
Сообщить("Описание ошибки: "+ТекстОшибки);
Возврат 0;
КонецПопытки;
КонецФункции
Проверено на следующих конфигурациях и релизах:
- Управление торговлей, редакция 10.3, релизы 10.2.8.2
- Управление торговлей, редакция 11, релизы 11.5.22.63