Вход | Регистрация

  1  2
1С:Предприятие ::

Метки: 

v7: Подпись декларации в 1С 7.7 с помощью CapiCom, JS-скрипт...

Я
   MWWRuza
 
15.01.18 - 13:55
Добрый день!
Третий день бьюсь с подписью АлкоДеклараций прямо из 1С.
Использую MS-CapiCom через JS-скрипт. Вот фрагмент кода, который именно отвечает за подписание файла:

СтрКода    = "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; // CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY
        |   SignedData=new ActiveXObject(""CAPICOM.SignedData"");
        |   SignedData.Content=InData;
        |   OutSignedData=SignedData.Sign(Signer,0,1);
        |
        |   OutStream=new ActiveXObject(""ADODB.Stream"");
        |   OutStream.Type=2; // text data
        |   OutStream.Mode=3; // read/write
        |   OutStream.Open();
        |   OutStream.WriteText(OutSignedData);
        |   OutStream.SaveToFile(OutFileName,2);
        |   OutStream.Close();
        |
        | return(0);
        |}
        |";
        JS.AddCode(СтрКода);
        Рез            = JS.Modules("Global").CodeObject.SignFile(ИмяФайла,ВыбСертификат,ИмяВыхФайла);

Сразу скажу, код не мой, используется разработка и ИнфоСтарта: http://catalog.mista.ru/public/156973/

Все как-бы внешне работает, ошибок не выдает, но содержимое файла изменяется, он становится не читаемым. Это происходит именно после этапа подписания, до архивирования и шифрования.
Если подписывать файл какой-либо сторонней программой, например КриптоАРМ, то его содержимое остается неизменным, просто добавляются в начало и конец небольшие фрагменты двоичного кода, "криптохвосты" самой ЭЦП. Это видно, если например открыть его блокнотом, лучше Notepad-2. В моем же случае, файл становится полностью "двоичным", никакого исходного XML в нем не остается, в основном "NUL"-ами заполнен...
Задал вопрос на ИнфоСтарте, в теме этой разработки, но все, в том числе и автор, молчат...
Что я не так делаю? Кто-нибудь пробовал делать что-то подобное, или конкретно эту обработку, или ее аналог на 8-мерке использовал?
Меня смущает в JS-скрипте вот эти строки:

Чтение: InStream.Type=1;// binary data

Запись, после подписания: OutStream.Type=2;// text data


Почему читает бинарные данные, а записывает текстовые?
Пробовал делать одинаковые, пишет, что "не доступно в данном контексте"...
Может у кого-то есть рабочий пример JS-скрипта, для подписи, работающий из 1С, поделитесь плиз?
 
  Рекламное место пустует
   MWWRuza
 
101 - 26.01.18 - 01:24
Вот, в конец скрипта добавил:

|Set objFSO = CreateObject(""Scripting.FileSystemObject"")
|Set writer = CreateObject(""Adodb.Stream"")
|Set reader = CreateObject(""Adodb.Stream"")
|reader.Open
|reader.LoadFromFile OutFileName
|writer.Mode=3
|writer.Type=1
|writer.Open
|reader.position=2
|reader.copyto writer,-1
|writer.SaveToFile OutFileName,2
|Set writer = Nothing
|Set reader = Nothing

В общем, через поток после подписи не получилось, а через открытие и запись файла с нужной позиции - заработало. Подписанный файл открывается и Notepad++ и КриптоАРМ его открывает. Теперь, доделать обработку - дело техники :)

Всем спасибо!!! У меня-бы без вашей поддержки давно бы терпение лопнуло, тем более, задача на самом деле не особо важная, скорее для собственного развития...
   MWWRuza
 
102 - 26.01.18 - 01:31
Вот вся работающая функция подписи, может кому-нибудь пригодится:

Функция ПодписатьФайл(ИмяФайла,ВыбСертификат,ИмяВыхФайла)
    FileName            = СокрЛП(ИмяФайла);
    OutFileName         = СокрЛП(ИмяВыхФайла);
    Cert                = ВыбСертификат;
    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "vbscript";
    
    code = "
    |Function Signer(FileName, OutFileName, Cert)
    |Set FileIn = CreateObject(""ADODB.Stream"")
    |FileIn.Type = 1
    |FileIn.Mode = 3
    |FileIn.Open() 
    |FileIn.LoadFromFile(FileName)
    |BinaryIn = FileIn.Read(-1)
    |Set Signer = CreateObject(""CAPICOM.Signer"")
    |Signer.Certificate = Cert
    |Signer.Options = 2
    |Set SignedData = CreateObject(""CAPICOM.SignedData"")
    |SignedData.Content = BinaryIn
    |SignData = SignedData.Sign(Signer, False, 1)
    |Set FileOut = CreateObject(""ADODB.Stream"")
    |FileOut.Type = 2
    |FileOut.Mode = 3
    |FileOut.Open()
    |FileOut.WriteText(SignData)
    |FileOut.SaveToFile OutFileName, 2
    |FileOut.Close()
    |FileIn.Close()
    |Set objFSO = CreateObject(""Scripting.FileSystemObject"")
    |Set writer = CreateObject(""Adodb.Stream"")
      |Set reader = CreateObject(""Adodb.Stream"")
      |reader.Open
      |reader.LoadFromFile OutFileName
      |writer.Mode=3
      |writer.Type=1
      |writer.Open
      |reader.position=2
      |reader.copyto writer,-1
      |writer.SaveToFile OutFileName,2
      |Set writer = Nothing
      |Set reader = Nothing
    |SignedData = Unassigned
    |Signer = Unassigned
    |FileIn = Unassigned
    |FileOut = Unassigned

    |End Function
    |";
      
    ScrptCtrl.AddCode(code);
    Попытка
        Рез  = ScrptCtrl.Modules("Global").CodeObject.Signer(FileName, OutFileName, Cert);
    Исключение
        ТекстОшибки    =ОписаниеОшибки();
        Сообщить("Описание ошибки: " + ТекстОшибки,"!");        
    КонецПопытки; 

    Возврат 1;
КонецФункции

Надо теперь еще в шифровании то-же самое сделать, и можно пользоваться.
   MWWRuza
 
103 - 26.01.18 - 01:36
Саму идею решения вот отсюда позаимствовал: http://blog.kalinchyk.com/2013/03/bom-utf.html
   MWWRuza
 
104 - 26.01.18 - 02:14
Не стал переделывать шифрование, оставил "как есть", на JS-скрипте, просто добавил в конец функции шифрования это:

    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "vbscript";
    code = "
    |Function DeleteBom(FileName)
    |Set objFSO = CreateObject(""Scripting.FileSystemObject"")
    |Set writer = CreateObject(""Adodb.Stream"")
      |Set reader = CreateObject(""Adodb.Stream"")
      |reader.Open
      |reader.LoadFromFile FileName
      |writer.Mode=3
      |writer.Type=1
      |writer.Open
      |reader.position=2
      |reader.copyto writer,-1 
      |reader.Close
      |writer.SaveToFile FileName,2
      |Set writer = Nothing
      |Set reader = Nothing
      |End Function
      |";
    ScrptCtrl.AddCode(code);
    Попытка
        Рез  = ScrptCtrl.Modules("Global").CodeObject.DeleteBom(ИмяВыхФайла);
    Исключение
        ТекстОшибки    =ОписаниеОшибки();
        Сообщить("Описание ошибки: " + ТекстОшибки,"!");        
    КонецПопытки;

Все работает. В принципе, это универсальная функция удаления BOM из файла. Можно использовать где угодно, требуется один параметр - имя файла...
В принципе, в этой обработке ее тоже надо вынести в отдельную функцию, но, уже сделал, переделывать лениво...
   NorthWind
 
105 - 26.01.18 - 08:39
(100) Это через почему же? https://drive.google.com/open?id=1sZfT2EtDjs-Bno30dmZDDaWrRxTW6nXw - работает, нет никаких ошибок.
   MWWRuza
 
106 - 26.01.18 - 10:27
А... Ну, Вы прежде чем Write использовать, сначала применили BinaryStringToByteArray. Я так не пробовал. Я попробовал как (91), и бросил. А надо было сначала BinaryStringToByteArray а потом уже Write использовать. Ну, да, так проще, спасибо. Но, и мой способ работает.
   MWWRuza
 
107 - 26.01.18 - 11:06
Кстати, в (91) у меня ошибка, в строке:
|SignData2 = Util.BinaryStringToByteArray(SignedData) должно быть SignData. Но, по любому, через WriteText не правильно работает, массив записывается с BOM, как и без всего этого.

Сделал как в (100), работает.
    code = "
    |Function Signer(FileName, OutFileName, Cert)
    |Set FileIn = CreateObject(""ADODB.Stream"")
    |FileIn.Type = 1
    |FileIn.Mode = 3
    |FileIn.Open() 
    |FileIn.LoadFromFile(FileName)
    |BinaryIn = FileIn.Read(-1)
    |Set Signer = CreateObject(""CAPICOM.Signer"")
    |Signer.Certificate = Cert
    |Signer.Options = 2
    |Set SignedData = CreateObject(""CAPICOM.SignedData"")
    |SignedData.Content = BinaryIn
    |SignData = SignedData.Sign(Signer, False, 1)
    |Set Util = CreateObject(""CAPICOM.Utilities"")
    |BinArr = Util.BinaryStringToByteArray(SignData)
    |Set FileOut = CreateObject(""ADODB.Stream"")
    |FileOut.Type = 1
    |FileOut.Mode = 3
    |FileOut.Open()
    |FileOut.Write(BinArr)
    |FileOut.SaveToFile OutFileName, 2
    |FileOut.Close()
    |FileIn.Close()
    |End Function
    |";
   MWWRuza
 
108 - 26.01.18 - 11:19
В исходной обработке с ИнфоСтарта, на JS-скрипте, в шифровании:

        |    Util = new ActiveXObject(""CAPICOM.Utilities"")
        |    BinArr = Util.BinaryStringToByteArray(OutEnvelopedData)
        |
        |   OutStream=new ActiveXObject(""ADODB.Stream"");
        |   OutStream.Type=1;// text data

        |   OutStream.Mode=3;// read/write

        |   OutStream.Open();
        |   OutStream.Write(BinArr);

Аналогично надо сделать и в подписании, но, я у себя уже под VBS-скрипт переписал, зачем трогать то, что работает(как в том старом анекдоте про программиста и солнце).
   MWWRuza
 
109 - 26.01.18 - 11:25
Комментарий не поправил, должно быть не "// text data" а "// binary data"
   MWWRuza
 
110 - 26.01.18 - 13:41
Отступление от темы, так-сказать, взгляд назад...
Ну, решили вопрос, я для себя почерпнул бесценные знания по использованию VBS и JS скриптов в 1С. Спасибо.
А вот задумался - какие практические применения этого? Кому оно надо?
Разберу на примере своих клиентов. Почти все ЭЦП они оформляли через меня. И они делятся на два типа:
1. ИПшники, кому все пофигу, БухУчет не нужен, торгуют себе пивом и ладно... У них обычно ЭЦП на ДжаКарте/РуТокене ЭЦП-2.0, работают с УТМ ЕГАИС, когда надо подписывать декларации, используют эти-же ЭЦП. Раньше, по третий квартал 2017 использовали бесплатный ЦентрИнформовский SignerGUI, после того, как он перестал работать, купили КриптоАРМ стандарт плюс, который тоже умеет работать с этими носителями.
2. Нормальные организации, торгующие алкоголем. У них почти у всех установлена 1С бухгалтерия 8, и подключена 1С-отчетность. ЭЦП для сдачи деклараций используется из нее. Точнее, декларации сформированные у меня в 7.7, подают используя 1С-отчетность, загружая внешний файл.

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

Поэтому, как-то так... Не понятно, для кого старались.
 
  Рекламное место пустует
   NorthWind
 
111 - 26.01.18 - 15:23
(110) Я не знаю. Я в таком ключе обычно не рассуждаю. Есть задача - ее надо решать. Если это потом зачем-то пригодится - хорошо, не пригодится - ну по крайней мере свою задачу решил. Собственно, все.
   oleg_km
 
112 - 26.01.18 - 15:37
(110) Предлагаю все проделать на C#. Удивишься, что все будет гораздо красивее.
   MWWRuza
 
113 - 26.01.18 - 19:25
(112)Не сомневаюсь. Попадались в сети примеры. Но, я с ним дел не имел ни когда, сложновато для понимания.

Я если чем-то в этом направлении и буду в свободное время заниматься, то если только изучением возможности использовать аппаратные крипто-провайдеры для подписания/шифрования. Но, тут, похоже CAPICOM бессилен, надо другими методами решать.
Пока, ничего подходящего не попадалось.

  1  2

Список тем форума
  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует