Имя: Пароль:
 
1C
1C 7.7
v7: Подпись декларации в 1С 7.7 с помощью CapiCom, JS-скрипт...
0 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С, поделитесь плиз?
1 NikVars
 
15.01.18
16:27
(0) "Почему читает бинарные данные, а записывает текстовые?"
Это?
OutStream.WriteText(OutSignedData);
2 MWWRuza
 
15.01.18
19:16
(1) Да. Код не мой, так было написано в исходной обработке.
Не понятно почему:
       |   InStream.Type=1; // binary data

****************

       |   InStream.Open();

Тут, собственно само подписание, и потом запись файла:

       |   OutStream=new ActiveXObject(""ADODB.Stream"");

       |   OutStream.Type=2; // text data

Почему так? Это разве правильно?
Пробовал поиграть с типами потоков(Stream.Type), делал одинаковыми на входе и на выходе, и 1 и 2, перестает работать совсем, пишет "ADODB.Stream: Операция не допускается в данном контексте."...
3 MWWRuza
 
15.01.18
21:38
Сделал для пробы вот так:
        |   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);
        |
        |   OutSignedData = InData;
        |
        |   OutStream=new ActiveXObject(""ADODB.Stream"");
        |   OutStream.Type=1; // text data
        |   OutStream.Mode=3; // read/write
        |   OutStream.Open();
        |   OutStream.Write(OutSignedData);
//        |   OutStream.WriteText(OutSignedData);
        |   OutStream.SaveToFile(OutFileName,2);
        |   OutStream.Close();
        |
        | return(0);

И при открытии файла и при записи устанавливаю тип - бинарный, подпись убираю - комментирую строку SignedData.Sign(Signer,0,1), передаю данные без изменений OutSignedData = InData. На выходе получаю файл без изменений, абсолютно одинаковый с исходным. Думал, ура, получилось, осталось только подписание раскомментировать! Но, нет... Ошибку выдает: "ADODB.Stream: Аргументы имеют неверный тип, выходят за пределы допустимого диапазона или вступают в конфликт друг с другом."
Странно, я же в самом подписании ничего не менял, и до него тоже, файл прочитывается в поток так-же, только сохраняется по другому...
4 Serginio1
 
15.01.18
22:04
5 NorthWind
 
15.01.18
22:14
(2) может быть и правильно. На вход вы получаете данные в виде строки неограниченной длины (если верно помню). А выход зависит от формата подписи, и если он MIME, то это вполне себе текст. Вам подпись в MIME формате получить надо или вы сами не знаете в каком?
6 MWWRuza
 
16.01.18
00:00
(5)Я действительно не знаю в каком. Знаю только, что кодировка должна быть "DER"...
В общем, похоже, с моими знаниями в этом вопросе, я вряд-ли разберусь с этой задачей... Будем пока внешними программами подписывать/шифровать, благо их много, есть и бесплатные. Жаль конечно, хотелось прямо из 1С получать готовый к отправке файл :(
7 NorthWind
 
16.01.18
08:03
(5) Там, по-моему, и своя штатная утилита командной строки есть в CryptoPro.
В общем, у меня года два назад стояла подобная задача для подписания документов ЮЗДО. Но я делал самостоятельную приблуду (бота) на VBS. Код подписания в ней выглядит так:
' -----------------------------------------------------------------------------------------
' Подписание файла. Подпись кладется по тому же пути, где находится исходный файл, с
' расширением bin
'
Sub Sign (FileName, Cert, Prefix)
    
    SignFileName = GetBinFileName (FileName, Prefix)

    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
    Base64Out = SignedData.Sign (Signer, True, 0)    

    Set FileOut = CreateObject ("ADODB.Stream")
    FileOut.Type = 2
    FileOut.Charset = "US-ASCII"
    FileOut.Mode = 3
    FileOut.Open ()
    FileOut.WriteText (Base64Out)
    FileOut.SaveToFile SignFileName, 2
    FileOut.Close ()
    FileIn.Close ()

    SignedData = Unassgned
    Signer = Unassigned
    FileIn = Unassigned
    FileOut = Unassigned    

End Sub
8 NorthWind
 
16.01.18
08:05
9 NorthWind
 
16.01.18
08:08
Если чего-то будет непонятно, спрашивайте здесь, попробую ответить. Я в целом плясал от уже имеющегося файла и имеющейся правильной подписи: просто подогнал параметры метода Sign и опции, чтобы получить такой же файл подписи.
10 Йохохо
 
16.01.18
08:14
(9) Signer.Certificate = Cert // откуда берется серт? спс
11 NorthWind
 
16.01.18
08:26
(10) Щас объясню:

' -----------------------------------------------------------------------------------------
' Поиск сертификата в хранилище
'
Function GetSigningCert
    
    Set Store = CreateObject ("CAPICOM.Store")

    Store.Open CURRENT_USER_STORE, MY_STORE, STORE_OPEN_READ_ONLY

    Set Certs = Store.Certificates.Find (CAPICOM_CERTIFICATE_FIND_SHA1_HASH, CertSHA1Hash)

    if Certs.Count > 0 Then
        Set GetSigningCert = Certs.Item (1)
    else
        Set GetSigningCert = Nothing
    end if
    
    Store = Unassgned

End Function

Далее в главной функции:

    Set Cert = GetSigningCert
    
    if not Cert is nothing Then
        ... здесь подписание
        end if

CertSHA1Hash - глобальная строка, которая содержит SHA1-хэш подписи для поиска в хранилище, по сути это уникальный ключ по которому можно найти сертификат. Взять эту строку можно из свойств сертификата.
12 NorthWind
 
16.01.18
08:31
' Константы крипто-апи
const CURRENT_USER_STORE = 2            
const MY_STORE = "My"            
const STORE_OPEN_READ_ONLY = 0    
const CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0
13 MWWRuza
 
16.01.18
11:26
(7)В АлкоДекларациях не так:

"Подписание файла. Подпись кладется по тому же пути, где находится исходный файл, с
' расширением bin"

Там файла отдельного для подписи нет. Подпись присоединянтся к основному файлу, как-бы "внедряется" в него. В итоге, файл подписанный отличается от исходного чуть-большим размером, и к нему дописывается через точку расширение "sig", вот так: XXXXXXXXXXXX.xml.sig . Потом, далее, его архивируют, он становится: XXXXXXXXXXXX.xml.sig.zip , и далее его шифруют с сертификатами получателей, и на выходе он получается: XXXXXXXXXXXX.xml.sig.zip.enc
Никаких отдельных файлов не создается(точнее, создаются временные и удаляются), все в исходном.
Если подписывать обработкой с InfoStarta, так все в целом и происходит. Только на выходе получается файл нечитаемый, с ощибкой формата, не открывается ни чем.
Когда начал разбираться, решил "отловить" через отладчик временные файлы до того, как обработка их удалит. Выяснилось, что уже после подписания, файл "портится", становится нечитаемым. Если открыть его блокнотом(Notepad++), то в нем двоичные(или в неправильной кодировке?) символы, ничего общего со структурой исходного файла не имеющие. Если подписать этот-же файл например КриптоАРМом, то при просмотре видно его XML содержимое, и только в начале и в конце небольшие вставки двоичного кода(судя по всему - сама ЭЦП). Дальнейшее архивирование проходит нормально, ZIP-"раззиповывается", а с шифрованием похоже та-же беда, не расшифровывается КриптоАРМом, с сертификатом получателя. Думаю, причина тут одна, что при подписи, что при шифровании... Какая-то мелочь, какой-нибудь параметр не верный...
14 NorthWind
 
16.01.18
11:40
(13) у меня тоже внедряется. Этот bin в кодировке Base64 содержит внутри себя как исходный файл, так и файл подписи. Отвечает за это второй параметр метода Sign.
Чтобы у вас получился файл такой как вы хотите, вам надо отказаться от Base64. Для этого служит третий параметр этого же метода Sign.
Рекомендую немного освоить теорию:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa387726(v=vs.85).aspx
15 MWWRuza
 
16.01.18
11:41
По сути, все подписание происходит вот здесь:

        |   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);

Все как-бы прозрачно, не понятны только параметры "0,1", но смотред в других примерах, там примерно то-же самое...
16 NorthWind
 
16.01.18
11:41
и да, если вы откажетесь от Base64, то выходной поток у вас, скорее всего, должен быть бинарным, потому что иначе "хвостик" электронной подписи не запишется или будет поврежден.
17 NorthWind
 
16.01.18
11:42
(15) я вам ссылку дал, там разжевано для чего параметры. Они вам нужны, поэтому надо хорошо понимать что вы делаете.
18 MWWRuza
 
16.01.18
11:44
Понятно, так и есть. Второй параметр "0" - то, что подпись в файле внутри, а третий "1" - кодировка...
Спасибо за ссылку, вечером займусь изучением теории...
19 MWWRuza
 
16.01.18
12:05
Не дотерпел до вечера... Почитал. Надо попробовать с третьим параметром поиграть. Возможно "тут собака порылась"... Вот только не совсем понятно, как параметр передавать, просто по его индексу в табличке? С нуля или с единицы начинается?
Если в исходной обработке передается "1", это что -
CAPICOM_ENCODE_ANY
или
CAPICOM_ENCODE_BASE64  - ?
В моем случае, что должно быть?
Вечером попробую поэкспериментировать, сейчас просто уже не могу, "труба" зовет...
20 NorthWind
 
16.01.18
12:25
(19) Если почитать статью, там где описывается этот параметр, увидите ссылку https://msdn.microsoft.com/en-us/library/windows/desktop/aa375673(v=vs.85).aspx. По сслыке читаем:
21 NorthWind
 
16.01.18
12:25
CAPICOM_ENCODE_ANY    

Data is saved as a base64-encoded string or a pure binary sequence. This encoding type is used only for input data that has an unknown encoding type. Introduced in CAPICOM 2.0.
    0xffffffff
CAPICOM_ENCODE_BASE64    

Data is saved as a base64-encoded string.
    0
CAPICOM_ENCODE_BINARY    

Data is saved as a pure binary sequence.
    1
22 NorthWind
 
16.01.18
12:26
то есть в вашем случае параметр, скорее всего, должен иметь значение 1.
23 MWWRuza
 
17.01.18
14:07
В моем случае он и есть 1.
Причина в чем-то другом...
24 NorthWind
 
17.01.18
14:24
(23) бинарник вместо текста не хотите попробовать записать?
25 Ёпрст
 
17.01.18
14:29
(0)ну и нахрен эти танцы с бубнами, когда это последний раз сдачи декларации ?
Её же отменили (ну, разве что вы не производство или пивом торгуете).
26 MWWRuza
 
18.01.18
02:26
(24)Пробовал, выдает ошибку, что-то типа того, что недоступно в данном контексте. Завтра точнее посмотрю.
(25)Нет, не производство. Розница. А у розницы отменили только 11-тую форму(Маркируемый алкоголь), а 12(Пиво) осталась. И я думаю, на долго, пока что-то типа акцизных марок на пиво не сделают. А это не один год. А пивняки, самые "раздолбаистые" клиенты, они раньше вообще халявили, через раз сдавали, и все им с рук сходило, а теперь, когда отменили 11 форму, к ним у контролирующих органов будет особое внимание(работы то меньше стало :-) ). Поэтому и хочется сделать для них упрощенный вариант.
27 Ёпрст
 
18.01.18
11:20
(26) есть же готовые поделки для клюшек с подптсью и шифрованием.
28 MWWRuza
 
18.01.18
21:20
(27)Так это она и есть... Других не знаю.
29 NorthWind
 
18.01.18
22:09
(26) я бы перенес все в VBS или JS-файл и поотлаживал бы непосредственно скрипт. Там было бы понятно на какой строке возникает ошибка и соответственно видно, от какой печки плясать. Мне кажется, бинарник должен записываться.
30 MWWRuza
 
19.01.18
23:34
(29)"JS-файл и поотлаживал бы непосредственно скрипт."

Думал об этом... Но, к сожалению, не знаю, как правильно это сделать. :-(:  А автор разработки с ИнфоСтарта, почему-то игнорирует мои вопросы и там, и здесь, хотя на конфу ИнфоСтарта заходит, 15.01.18 был... Проблему я описал значительно раньше :-(
31 NorthWind
 
20.01.18
08:26
(30) просто. Создаете файл с расширением js или vbs, копируете туда ваш код, делаете точку входа и запускаете. Примеры скриптов очень просто ищутся, в частности есть здесь http://scriptcoding.ru/2013/02/22/sintaksis-jscript/.
Есть нюанс, на который я напоролся в свое время - CAPICOM стандартно поставляется в 32-битной версии, поэтому в 64-битной винде для запуска надо использовать не стандарные cscript.exe (wscript.exe), а те, которые находятся в папке c:\windows\syswow64. Иначе ком-объекты работать не будут.
32 MWWRuza
 
20.01.18
17:43
(31)Спасибо, у меня основная рабочая машина, где я всем "творчеством" занимаюсь, вообще под XP, естественно 32 бита. Есть доступная(рядом стоит, на один монитор с клавой выведена, с переключателем) под семеркой, 32 бита, и по удаленке есть семерка 64 бита. Буду пробовать. Не понятно пока вот это: "делаете точку входа и запускаете" - как сделать точку входа?
33 NorthWind
 
20.01.18
22:32
(32) точка входа - это место, откуда начинает выполняться код при запуске скрипта. Посмотрите все же ссылку, там это подробно написано. Если джаваскрипт сложен для понимания, напишите на vbs, там попроще. Вот можно здесь примеры посмотреть еще http://scriptcoding.ru/132-primera-vbscript-jscript/
34 MWWRuza
 
21.01.18
19:07
Да ссылку то я посмотрел... Но не все так просто, как там описано. Примеры из ссылки я пробовал, работают, более менее все понятно.
А вот в моей текущей задаче, не понятно где сертификат брать, что-бы его в скрипт запихнуть...
Сам скрипт понятен, ничего там сложного нет, а вот как с ним работать, темный лес.

FileName = "C:\Dekl\Proba.xml";
// Cert - ???
OutFileName = "C:\Dekl\Proba.xml.sig";

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.Write(OutSignedData);
    OutStream.WriteText(OutSignedData);
    OutStream.SaveToFile(OutFileName,2);
    OutStream.Close();
    return(0);
    }

Функция SignFile, три параметра, имя "входного" файла, имя "выходного", и сертификат. Если имена я могу просто, явно объявить, то как передать сертификат в скрипт, мне не понятно...
И как отлаживать, я пока тоже не понял. Ну, запускаю этот скрипт, и ничего не происходит, ошибок нет но и ничего не делает.
35 MWWRuza
 
21.01.18
20:03
Попробовал вот так сделать:

Функция ПодписатьФайл(ИмяФайла,ВыбСертификат,ИмяВыхФайла)
    Попытка
        JS            = СоздатьОбъект("MSScriptControl.ScriptControl");
        JS.Language    = "jscript";
        JS.Timeout    = -1;
    Исключение
        ТекстОшибки    =ОписаниеОшибки();
        Сообщить("Не удалось создать объект MSScriptControl.ScriptControl","!");
        Сообщить("Описание ошибки: " + ТекстОшибки,"!");
        Возврат 0;
    КонецПопытки;
    
    FileName            = ИмяФайла;
    OutFileName         = ИмяВыхФайла;
    
    InStream             = СоздатьОбъект("ADODB.Stream");
    InStream.Type        = 1; // binary data
    InStream.Mode        = 3; // read/write
    InStream.Open();
    InStream.LoadFromFile(FileName);
    InData                = InStream.Read(-1);
       Signer                = СоздатьОбъект("CAPICOM.Signer");
    Signer.Certificate     = ВыбСертификат;
    Signer.Options        = 2; // CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY
    SignedData            = СоздатьОбъект("CAPICOM.SignedData");
    SignedData.Content    = InData;
    OutSignedData        = SignedData.Sign(Signer,0,1);
    OutStream             = СоздатьОбъект("ADODB.Stream");
    OutStream.Type=2;         // text data
    OutStream.Mode=3;         // read/write
    OutStream.Open();
    OutStream.WriteText(OutSignedData);
    OutStream.SaveToFile(OutFileName,2);
    OutStream.Close();
Возврат 1;
КонецФункции

Пишет ошибку:
InData                = InStream.Read(-1);
{Отчет.АлкогольнаяДекларация.Форма.Модуль(3853)}: Тип переменой не поддерживается

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

SignedData.Content = InStream.Read(-1);

Все равно не работает, та-же ошибка :(
36 MWWRuza
 
21.01.18
20:29
7.7, как я понял, не понимает бинарные данные и не может их поместить в переменную. Может нужно какой-то объект создать, для их хранения и передачи?
37 MWWRuza
 
21.01.18
21:45
Ну, в общем, лед тронулся...
Вот такой код JS у меня заработал, ну, конечно не до конца, ругается на "Несоответствие типов строка 17 символ 2" :

FileName = "C:\\Dekl\\Proba.xml";
OutFileName = "C:\\Dekl\\Proba.xml.sig";
Cert = "";
    InStream=new ActiveXObject("ADODB.Stream");

    WshShell = WScript.CreateObject("WScript.Shell");    

    WScript.Echo (FileName);

    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();

Ну, это и понятно, я ему вместо сертификата пустые кавычки передаю. Надо сейчас поискать, попадались примеры, как в JS скрипте с помощью CAPICOM сертификат получить...
38 NorthWind
 
21.01.18
22:27
(37) я сюда скидывал, в эту ветку, посмотрите мой пример. У каждого сертификата есть SHA1 отпечаток, который можно глянуть в свойствах сертификата. Это относительно короткая строка, содержащая символы 0..9 и a..f. По этой строке можно средствами CAPICOM найти сертификат в хранилище и потом передать для подписания им контента. Смотрите (11) и потом (7).
39 NorthWind
 
21.01.18
22:37
(36) не готов сказать. Все касающееся подписания и отправки у меня крутится на VBS и 1С туда не лезет. Ее дело подготовить исходный файл.
40 MWWRuza
 
22.01.18
00:24
Использовал Ваш пример на vbs из(7) Пока кодировку не менял. Вот так:

    FileName            = СокрЛП(ИмяФайла);
    OutFileName         = СокрЛП(ИмяВыхФайла);
    Cert                = ВыбСертификат;
    
    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "vbscript";
    code = "
    |Sub Sign(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
    |Base64Out = SignedData.Sign(Signer, True, 0)    

    |Set FileOut = CreateObject(""ADODB.Stream"")
    |FileOut.Type = 2
    |FileOut.Charset = ""US-ASCII""
    |FileOut.Mode = 3
    |FileOut.Open ()
    |FileOut.WriteText(Base64Out)
    |FileOut.SaveToFile OutFileName, 2
    |FileOut.Close()
    |FileIn.Close()

    |SignedData = Unassgned
    |Signer = Unassigned
    |FileIn = Unassigned
    |FileOut = Unassigned    

    |End Sub
    |";
      
    ScrptCtrl.AddCode(code);
    Попытка
        ScrptCtrl.Run("Sign");
    Исключение
        ТекстОшибки    =ОписаниеОшибки();
        Сообщить("Описание ошибки: " + ТекстОшибки,"!");        
    КонецПопытки;

Валится в исключение, без объяснения причин...
Имя файла входное/выходное передаю, сертификат тоже...
Не пойму, чего ему не хватает :(
41 MWWRuza
 
22.01.18
01:37
В общем, с запуском скрипта vbs разобрался. Надо так:

    ScrptCtrl.Language = "vbscript";
    code = "
    |Function Signer(FileName, OutFileName, Cert)

// Здесь сам скрипт

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

Проблема была с передачей параметров.
Так работает, но на выходе абракадабра строками по 64 символа. Это из-за кодировки "Base64" - ?
42 Злопчинский
 
22.01.18
01:38
ну покажи пару строк абракадабр...
43 NorthWind
 
22.01.18
09:02
(41) Да, так и есть. Крипто-про записывает Base64 по 64 символа, потом перевод строки. Выглядит примерно так:
MIINCwYJKoZIhvcNAQcCoIIM/DCCDPgCAQExDDAKBgYqhQMCAgkFADALBgkqhkiG
9w0BBwGgggjxMIII7TCCCJygAwIBAgIQAdLOOGcddYAAAA/QA3kAAjAIBgYqhQMC
....
44 MWWRuza
 
22.01.18
11:20
Не знаю, как здесь файлы прикреплять...
В общем, по ссылке: https://cloud.mail.ru/public/BqmL/LgZrBtVu1
архив, в нем три файла - специально сделанный "коротенький" xml, он-же подписанный КриптоАРМом, и он-же подписанный через 1С скриптом на vbs.
Там все видно...
Кстати, подписанный скриптом файл КриптоАРМом открывается, подпись снимается. Но, кодировка явно не та, что нужно.
45 MWWRuza
 
22.01.18
11:31
Да, забыл... Настройки скрипта:
Чтение - FileIn.Type = 1
Подписание - SignData = SignedData.Sign(Signer, False, CAPICOM_ENCODE_BINARY)
Кодовая страница, оставил как в примере из(7), но пробовал разные, эффекта нет - FileOut.Charset = ""US-ASCII""
Запись - FileOut.Type = 2
46 NorthWind
 
22.01.18
15:17
(44) я вашим же скриптом из (37) с минимальными изменениями получил бинарник, который вам нужен. Не знаю, почему у вас не выходит. Вот ссылка: https://drive.google.com/open?id=1JamyH3jIo4WDm4_YHzz-8nKEX382OdDv
Вам нужно будет поменять в скрипте пути к файлам и SHA1-отпечаток на отпечаток вашего сертификата.
47 MWWRuza
 
22.01.18
15:48
Ну... Такое я уже получал, и что?
Это-же не то...
Откройте тот файл, который я в предыдущей месаге выкладывал... Там есть файл, подписанный КриптоАРМ. Если его открыть блокнотом, то видно, что идет небольшой кусочек двоичных данных, потом сама XML-ка, и в конце, опять двоичные данные. При этом, эти двоичные вставки выглядят как текст "кракозябликами". В Вашем файле ничего такого нет, почти все "квадратиками"... И он не открывается КриптоАРМом, ошибку дает. Файлы подписанные самим КриптоАРМом, и моим скриптом на VBS, открываются КриптоАРМом нормально, подпись снимается, файлы восстанавливаются в исходный вид, бит в бит...
48 MWWRuza
 
22.01.18
15:52
(47)"скриптом на VBS" - это там где Base64 кодировка.
49 NorthWind
 
22.01.18
16:24
(47) структура файлов одинаковая. Поиграйтесь с Signer.Options, возможно, нужно включить всю цепочку сертификатов в файл подписи. Поставьте 0 или 1. У меня нет криптоарма, я проверяю с помощью утилиты cryptcp, которую можно скачать тут: http://www.cryptopro.ru/products/other/cryptcp
50 MWWRuza
 
22.01.18
19:10
Исходный файл.
[img]https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/i-220.jpg[/img]
Файл после подписи КриптоАРМом.
[img]https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-221.jpg[/img]
Файл после подписи ДжаваСкриптом.
[img]https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-222.jpg[/img]
Как бы все видно...
51 MWWRuza
 
22.01.18
19:12
Не понимает форум стандартных тегов картинок...
Исходный файл.
https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/i-220.jpg
Файл после подписи КриптоАРМом.
https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-221.jpg
Файл после подписи ДжаваСкриптом.
https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/h-222.jpg
Как бы все видно...
52 NorthWind
 
22.01.18
19:58
(51) хммм... из этого пока что видно видно только то, что Notepad++ в третьем случае для отображения применил другую кодировку, менее подходящую. В фаре, например, у меня это выглядит так:
https://imgur.com/a/51HU2
https://imgur.com/a/OqeLr
то бишь, похоже уже несколько больше.
53 NorthWind
 
22.01.18
20:03
и тут видится некоторый тупик, потому что крипто-про свою подпись проверяет и говорит что все нормально.
54 MWWRuza
 
22.01.18
20:18
Ну, на самом деле, все эти программы, просто смотрят на начало файла, и пытаются подсунуть кодировку, которую там вычитали... И фиг бы с ними(они и не обязаны это делать), но, у меня Ваш(и мой, из аналогичных экспериментов) файл не открывается КриптоАРМом(а вот он, просто ОБЯЗАН открывать любой КОРРЕКТНЫЙ файл с подписью, пофигу, в чем он подписан)... И нет никакой гарантии, что он откроется у получателя(ФСРАР)...
55 MWWRuza
 
22.01.18
20:21
Блокнот, который родной, виндовый, без ++, тоже открывает все квадратиками.
56 MWWRuza
 
22.01.18
20:23
Квадратики, обычно с UNICODE связаны, но, тут похоже что-то другое.
57 NorthWind
 
22.01.18
20:31
(56) совершенно верно. Notepad++ опознает одну из кодировок Unicode, тогда как чтобы увидеть нечто знакомое, вам надо кодировку Windows-1251. Но только суть-то не в этом. Еще раз повторяю - родная утилита, запущенная как cryptcp -verify src.xml.sig, подпись видит и говорит что все с ней хорошо. У вас какой криптопровайдер? Может, VipNet?
58 MWWRuza
 
22.01.18
20:44
У меня, на основном компе, под ХРюшей - КриптоПро CSP 3.6, от банка Возрождение вместе с их Клиент-банком достался. На втором, рядом стоящем компе - VipNet CSP, по удаленке доступны еще несколько компов с разными версиями как КриптоПро, так и ВипНет. Пробовал на разных, все одно и то-же.
59 MWWRuza
 
22.01.18
20:46
Так, что думаю, проблемы не в отображении, а именно в неправильной работе подписанта....
60 MWWRuza
 
22.01.18
20:50
Кстати, результат отработки скрипта одинаковый, как для КриптоПро, так и для ВипНета...
61 NorthWind
 
22.01.18
21:12
Тут еще нужно иметь в виду такую штуку, что CAPICOM довольно-таки старая вещь и она уже давно не развивается. Ей на замену пришел CaDESCOM и там уже несколько больше и кодировок, и многого другого. Возможно, то что вам нужно, удастся сделать на нем. Думаю, будет небесполезно зарегистрироваться на форуме крипто-про и позадавать вопросы еще и там.
62 NorthWind
 
22.01.18
21:14
в 64-битных-то виндах капикома просто нет. И не будет.
63 MWWRuza
 
22.01.18
22:18
Сложно все это... Того не стоит. Я думаю, надо попробовать консольную утилиту из(49) из под 1С заюзать... Думаю, проще и надежнее будет.
64 MWWRuza
 
23.01.18
17:03
Только сейчас заметил, что она платная, 2250 руб. :-(
Нафиг... Уж лучше тогда КриптоАРМ плюс, на 50 рублей дешевле, и при этом, умеет с ДжаКартой работать...
65 MWWRuza
 
24.01.18
00:05
(52) Странно, но у меня Ваш файл в FAR вот так https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/i-223.jpg выглядит, те-же "квадратики"...
66 ex-human
 
24.01.18
02:43
На 8.1 делал так:
Функция ПодписатьФайл(СтруктураОписаний) Экспорт
    ИмяФайла = СтруктураОписаний.ПутьФайлаОтчета + СтруктураОписаний.ИмяФайла + ".zip";
    ИмяВыхФайла = СтруктураОписаний.ПутьФайлаОтчета + СтруктураОписаний.ИмяФайла + ".zip.sgn";
    ВыбСертификат = СтруктураОписаний.Сертификаты.ПодписьДекларантаСОМ;    
    Попытка
        ВходнойПоток = Новый COMОбъект("ADODB.Stream");
        ВходнойПоток.Type = 1;
        ВходнойПоток.Mode = 3;
        ВходнойПоток.Open();
        ВходнойПоток.LoadFromFile(ИмяФайла);
        ВходныеДанные = ВходнойПоток.Read(-1);
        Подписант = Новый COMОбъект("CAPICOM.Signer");
        Подписант.Certificate = ВыбСертификат;
        Подписант.Options = 1; // CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY
        ПодписанныеДанные = Новый COMОбъект("CAPICOM.SignedData");
        ПодписанныеДанные.Content = ВходныеДанные;
        Результат = ПодписанныеДанные.Sign(Подписант, 0, 0);
        ДвоичныеДанные = Base64Значение(Результат);
        ДвоичныеДанные.Записать(ИмяВыхФайла);
    Исключение
        Возврат Ложь;
    КонецПопытки;
    Возврат Истина;
КонецФункции
67 NorthWind
 
24.01.18
07:43
(65) нажмите F8
68 NorthWind
 
24.01.18
08:10
(66) в этой ветке работают также, с той разницей что Options=2 и пытаются сразу писать бинарник вместо base64 (последний параметр Sign).
69 MWWRuza
 
24.01.18
11:22
(67) Да. Так похоже. Но, только КриптоАРМ все равно ругается: https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/i-224.jpg Соответственно, 99.9%, что у получателя тоже не откроется.
(66) Пробовал аналогично под 7.7 (35) Пишет "Неверный тип переменной"... Похоже, семерка не может хранить в переменной двоичные данные...
70 NorthWind
 
24.01.18
11:30
(69) Неплохим вариантом было бы связаться с техподдержкой организации, куда вы посылаете данные, и попросить их проверить подготовленные данные. Второй вариант - просто тупо отослать декларацию обычным порядком. Если ее завернут из-за неподходящей подписи - это ведь вряд ли чревато санкциями?
Да, в семерке описанный в (66) вариант вряд ли прокатит, потому что средствами семерки вы не преобразуете из Base64 в двоичку.
71 NikVars
 
24.01.18
11:32
(69) http://ocvita.ru/content/view/24/
Обработка позволяет размещать двоичные (бинарные) файлы в любом модуле 1С 7.7, как в конфигурации, так и во внешней обработке (.ert), а также предоставляет функции для их распаковки.
72 NorthWind
 
24.01.18
12:01
(69) Удалось понять причину. Проблема в том, что ADOStream.WriteText записывает в начало бинарника два символа с кодом 255 и 254. Если вы их сотрете, то файл начнет проверяться криптоармом. Из-за них и просмотрщики пытаются открывать файл как юникодный.
73 MWWRuza
 
24.01.18
12:21
(72)Интересно... А чем Вы их стираете?
74 MWWRuza
 
24.01.18
12:25
(73)Фаром стер, просмотрщик стал открывать, но, КриптоАРМ все равно на формат ругается...
75 oleg_km
 
24.01.18
12:26
(72) https://docs.microsoft.com/ru-ru/sql/ado/reference/ado-api/charset-property-ado

Мануал читайте, время экономит
76 MWWRuza
 
24.01.18
12:33
(74)Нет, все нормально, лишний символ прихватил...
77 MWWRuza
 
24.01.18
12:34
(75)Займусь...
78 MWWRuza
 
24.01.18
12:41
Файл декларации подписанный из 1С вот этим кодом:

    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)
//    |SignData = SignedData.Sign(Signer, False, 0)
//    |SignData = SignedData.Sign(Signer, TRUE, 1)
//    |SignData = SignedData.Sign(Signer, 0, 1)
//    |SignData = SignedData.Sign(Signer, TRUE, CAPICOM_ENCODE_BINARY)
//    |SignData = SignedData.Sign(Signer, False, CAPICOM_ENCODE_BASE64)
//    |SignData = SignedData.Sign(Signer, False, CAPICOM_ENCODE_BINARY)
    
//    |SignData = SignedData.Sign(Signer, True, 1)

    |Set FileOut = CreateObject(""ADODB.Stream"")
    |FileOut.Type = 2
//    |FileOut.Charset = ""windows-1251""
//    |FileOut.Charset = ""ASCII""
//  |FileOut.Charset = ""UTF-8""
//    |FileOut.Charset = ""ANSI""
//    |FileOut.Charset = ""UNICODE""
//    |FileOut.Charset = ""OEM866""
    |FileOut.Mode = 3
    |FileOut.Open()
    |FileOut.WriteText(SignData)
//     |FileOut.Write(SignData)    
    |FileOut.SaveToFile OutFileName, 2
    |FileOut.Close()
    |FileIn.Close()

    |SignedData = Unassigned
    |Signer = Unassigned
    |FileIn = Unassigned
    |FileOut = Unassigned    

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

тоже открывается, если стереть два первых символа...
Все, что там закомментировано, это мои "эксперименты", ни к чему не приведшие... Надо мануал внимательнее изучать...
79 MWWRuza
 
24.01.18
13:36
Исходный код на JS тоже работает. Останавливаю выполнение обработки отладчиком после подписания, убираю из промежуточного файла первые два символа, жму продолжить. Получаю подписанный, архивированный и зашифрованный файл. Естественно, в таком виде он КриптоАРМом не открывается,ошибка формата. Так-же, фаром убираю первые два символа из зашифрованного файла, и УРА! все работает, КриптоАРМу уже этот шифрованный файл нравится, и даже расшифровывает, если в получатели добавить свой сертификат...

Вот только что надо сделать, чтобы это правильно работало, мне пока не понятно...
80 NorthWind
 
24.01.18
14:26
(75) читаем мы мануал, не беспокойтесь. Проблема заключается в том, что Sign возвращает бинарку в виде строки. А бинарный стрим при использовании Write хочет на вход не строку, а вариабельный массив байтов, а когда ему даешь строку - он ее, гад, не кушает. Приходится использовать текстовый стрим.
81 NorthWind
 
24.01.18
14:31
+ (80) и к (78): прочтите вот это http://bbs.vbstreets.ru/viewtopic.php?f=8&t=44139
82 NorthWind
 
24.01.18
14:59
В принципе возможен такой вариант - сначала в промежуточный стрим текстовый, потом оттуда методом CopyTo в бинарный, потом в бинарнике поставить указатель на 3, вычитать до конца, очистить и записать то что вычитали. Ну а потом SaveToFile. Хотя это, конечно, изврат.
83 NorthWind
 
24.01.18
15:04
ну или в (81) почитайте, может там менее черезж@пные варианты есть
84 NorthWind
 
25.01.18
16:21
ТС, получили исчерпывающую инфу по своей проблеме и сбежали. Вы бы хоть спасибо сказали, что ли. Вашу работу делали, между прочим...
85 MWWRuza
 
25.01.18
18:44
Спасибо конечно, но, информация пока не исчерпывающая, ссылки изучаю, но, ничего нового сделать не получилось. Через@пный вариант мне не нравится, а найти что-то более вменяемое пока не получилось.
И никуда я не сбегал, просто сейчас пока некогда было этим заниматься, текучка не дает что-то новое творить...

PS Если кто и сбежал, то автор оригинальной разработки с ИнфоСтарта... Выложил, за СМ, и пропал, на вопросы не отвечает, а разработка, как мы с Вами выяснили, принципиально не рабочая... Мог бы хоть отозваться.
86 NorthWind
 
25.01.18
19:08
(85) Ссылку в (81) читали? Особенно последний пост... Цитирую:
Выяснилось, что CAPICOM возвращает что-то вроде BSTR, где каждый символ представлен 2мя байтами (UNICODE), из которых первый редко меняется - похоже именно его и извлекал mid. Решение предоставляется самим CAPICOM'ом - в нем нашелся объект Utilities, а в нем чудо функция искомая в заголовке этой темы - BinaryStringToByteArray. Она успешно формирует именно ByteArray из возвращаемых CAPICOMом помоев, а его уже ест ADODB.Stream.
87 NorthWind
 
25.01.18
19:10
и, кстати, не исключено что эти два байта не особенно мешают... Во всяком случае, cryptcp на них плюет. Вполне может быть, что и ФСРАРовскому роботу пофиг.
88 MWWRuza
 
25.01.18
19:11
Нет, до этого пока не добрался... Точнее, читал, но не пробовал реализовать.
Сегодня постараюсь попробовать, потом, отпишусь когда проверю.
89 NorthWind
 
25.01.18
19:13
Подумайте логически. Если автор выложил эту разработку на ИС, не опасаясь никакой критики - значит, надо полагать что скорее всего декларации он какие-то сдавал и они у него проходили. Так что... не исключено, что мы тут махаемся только ради знаний :)
90 MWWRuza
 
25.01.18
19:17
(87) Может быть. Но, хотелось сделать, что-бы открывалось любыми средствами. Проверить, к сожалению, пока не на чем - первички все сдали, теперь только в следующем квартале. Если только кто-нибудь решит корректировку подать, тогда попробую. Ничего страшного в этом нет, ну вернется ошибка, сто-то типа "ошибка расшифровки", ну и ладно.
(89)Ну, да возможно...
91 MWWRuza
 
25.01.18
19:47
(88)В принципе, не сложный объект, и функция в нем. https://msdn.microsoft.com/en-us/library/windows/desktop/aa388179(v=vs.85).aspx
Попробовал:

|SignData = SignedData.Sign(Signer, False, 1)
|Set Util = CreateObject(""CAPICOM.Utilities"")
|SignData2 = Util.BinaryStringToByteArray(SignedData)
|Set FileOut = CreateObject(""ADODB.Stream"")
|FileOut.Type = 2
|FileOut.Mode = 3
|FileOut.Open()
|FileOut.WriteText(SignData2)
|FileOut.SaveToFile OutFileName, 2

В результате, на выходе получаю исходную XML, без подписи, но в начале эти пресловутые два символа. Если их убрать ФАР-ом, то получается исходная XML, в исходной кодировке, только лишнее расширение sig добавлено.
92 MWWRuza
 
25.01.18
20:05
Я, честно говоря, так до конца и не понял - эти два символа ADODB.Stream при выполнении метода WriteText добавляет, типа как "маркер кодировки", или они уже из CAPICOM прилетают?
93 MWWRuza
 
25.01.18
20:16
(92)Судя по тому, что после BinaryStringToByteArray эти символы остаются, хотя вся бинарная часть данных(сама подпись) пропадает, все-таки наверно WriteText их добавляет - ?
94 MWWRuza
 
25.01.18
20:48
(91)Так, по приколу:

    Тхт = СоздатьОбъект("Текст");
    Тхт.Открыть(OutFileName);
    Для Сч = 1 По Тхт.КоличествоСтрок() Цикл
        Стр = Тхт.ПолучитьСтроку(Сч);
        Если Сч = 1 Тогда
            Стр = Сред(Стр,3);
            Тхт.ЗаменитьСтроку(1,Стр);
            Прервать;
        КонецЕсли;    
    КонецЦикла;
    Тхт.Записать(OutFileName);

На выходе получается входная XML-ка, бит в бит...
Но, естественно, если убрать BinaryStringToByteArray, то получается ерунда, но без первых двух символов :) , само собой разумеется - 1С-ка не умеет строки двоичных символов открывать и сохранять.
95 MWWRuza
 
25.01.18
20:58
Вот так выглядит в отладчике 1С первая строка подписанного файла:
https://content.foto.my.mail.ru/mail/m_w_w/_mypagephoto/i-225.jpg
Это если без BinaryStringToByteArray, если с ним - то обычная строка.
96 NorthWind
 
25.01.18
22:19
(93) WriteText добавляет, конечно. Это так называемый BOM, https://ru.wikipedia.org/wiki/Маркер_последовательности_байтов, который вставляется в начало текстовых файлов. Поток у нас текстовый, соответственно...
97 NorthWind
 
25.01.18
22:23
(91) здесь уже по идее бинарный стрим использовать надо, а не текстовый, и Write вместь WriteText. Вот тогда и наступит счастье.
98 MWWRuza
 
25.01.18
23:09
Вот интересное нашел: http://rsdn.org/forum/web/671507.hot
В конце.
Описание метода CopyTo: https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/copyto-method-ado
"CopyTo следует использовать для копирования данных в целевой поток того же типа, что и исходный поток (их параметры свойств типа являются как adTypeText, так и оба adTypeBinary). Для объектов текстового потока вы можете изменить параметр свойства Charset для потока назначения для перевода из одного набора символов в другой. Кроме того, объекты текстового потока могут быть успешно скопированы в двоичные объекты Stream, но двоичные объекты Stream не могут быть скопированы в текстовые объекты Stream." - ГуглПеревод.
Попробовал:

|Set FileOut = CreateObject(""ADODB.Stream"")
|Set FileOut2 = CreateObject(""ADODB.Stream"")
|FileOut.Type = 2
|FileOut2.Type = 2
|FileOut.Mode = 3
|FileOut.Open()
|FileOut2.Mode = 3
|FileOut2.Open()
|FileOut.Position=3
|FileOut.WriteText(SignData)
|FileOut2.Charset = ""windows-1251""
|FileOut.CopyTo FileOut2, -1
|FileOut2.SaveToFile OutFileName, 2
|FileOut2.Close()
|FileOut.Close()
|FileIn.Close()

Выходной файл пустой получается, с нулевым размером...
Не могу понять, почему?
99 MWWRuza
 
25.01.18
23:18
(93)Это так называемый BOM
Это я уже понял... Как ему задать кодировку "без BOM" - ?
Когда в том-же Notepad++ открываешь кодировки, там есть "Utf-8" и есть "Utf-8 без BOM". Может тут тоже можно как-то задать такую кодировку?
100 MWWRuza
 
25.01.18
23:20
Write я пробовал, ошибку пишет...
101 MWWRuza
 
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++ и КриптоАРМ его открывает. Теперь, доделать обработку - дело техники :)

Всем спасибо!!! У меня-бы без вашей поддержки давно бы терпение лопнуло, тем более, задача на самом деле не особо важная, скорее для собственного развития...
102 MWWRuza
 
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;
КонецФункции

Надо теперь еще в шифровании то-же самое сделать, и можно пользоваться.
103 MWWRuza
 
26.01.18
01:36
Саму идею решения вот отсюда позаимствовал: http://blog.kalinchyk.com/2013/03/bom-utf.html
104 MWWRuza
 
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 из файла. Можно использовать где угодно, требуется один параметр - имя файла...
В принципе, в этой обработке ее тоже надо вынести в отдельную функцию, но, уже сделал, переделывать лениво...
105 NorthWind
 
26.01.18
08:39
(100) Это через почему же? https://drive.google.com/open?id=1sZfT2EtDjs-Bno30dmZDDaWrRxTW6nXw - работает, нет никаких ошибок.
106 MWWRuza
 
26.01.18
10:27
А... Ну, Вы прежде чем Write использовать, сначала применили BinaryStringToByteArray. Я так не пробовал. Я попробовал как (91), и бросил. А надо было сначала BinaryStringToByteArray а потом уже Write использовать. Ну, да, так проще, спасибо. Но, и мой способ работает.
107 MWWRuza
 
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
    |";
108 MWWRuza
 
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-скрипт переписал, зачем трогать то, что работает(как в том старом анекдоте про программиста и солнце).
109 MWWRuza
 
26.01.18
11:25
Комментарий не поправил, должно быть не "// text data" а "// binary data"
110 MWWRuza
 
26.01.18
13:41
Отступление от темы, так-сказать, взгляд назад...
Ну, решили вопрос, я для себя почерпнул бесценные знания по использованию VBS и JS скриптов в 1С. Спасибо.
А вот задумался - какие практические применения этого? Кому оно надо?
Разберу на примере своих клиентов. Почти все ЭЦП они оформляли через меня. И они делятся на два типа:
1. ИПшники, кому все пофигу, БухУчет не нужен, торгуют себе пивом и ладно... У них обычно ЭЦП на ДжаКарте/РуТокене ЭЦП-2.0, работают с УТМ ЕГАИС, когда надо подписывать декларации, используют эти-же ЭЦП. Раньше, по третий квартал 2017 использовали бесплатный ЦентрИнформовский SignerGUI, после того, как он перестал работать, купили КриптоАРМ стандарт плюс, который тоже умеет работать с этими носителями.
2. Нормальные организации, торгующие алкоголем. У них почти у всех установлена 1С бухгалтерия 8, и подключена 1С-отчетность. ЭЦП для сдачи деклараций используется из нее. Точнее, декларации сформированные у меня в 7.7, подают используя 1С-отчетность, загружая внешний файл.

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

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

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