Вроде бы алгоритмы старые, не Стрибог. Сам алгоритм подписи на элиптических кривых. Теоретически можно и математикой сделать. Я сам этот гост раньше не делал, но думаю менеджер криптографии 1с не подходит.
https://m.habr.com/ru/post/191240/
(6) Тоже бывает. В Тинькофбанке помню - сначала вычислял хеш, потом вычислял ХешХеша, и уже SingHash(ХешХеша) - только тогда прошло успешно. Обратите внимание - в коде два раза идет oHashedData.Hash. И кстати они же два примера - как захешировать строку и как захешировать двоичные данные:
UTF8Encoding = Новый COMОбъект("System.Text.UTF8Encoding");
//байты = UTF8Encoding.GetBytes_4(Строка); //массив чисел-байтов, каждый байт - буква переменной Строка
oHashedData.Hash(UTF8Encoding.GetBytes_4(Строка));
ХэшХексСтрока = oHashedData.Value;
ХэшДвоичный = Получить_ДвоичныеДанныеИзHexСтроки(ХэшХексСтрока); //этот хеш будем отправлять в POST запрос
ХэшДвоичный_64 = Base64Строка(ХэшДвоичный);
oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;
oHashedData.Hash(ХэшДвоичный_64); //хешируем хеш чтобы подписать методом SignHash
sRawSignature = oRawSignature.SignHash(oHashedData, oCertificate);
ПодписьДвоичная = Получить_ДвоичныеДанныеИзHexСтроки(sRawSignature);
СтруктураОтвета = Новый Структура;
СтруктураОтвета.Вставить("DigestValue", Base64Строка(ХэшДвоичный));
СтруктураОтвета.Вставить("SignatureValue", Base64Строка(ПодписьДвоичная));
СтруктураОтвета.Вставить("X509SerialNumber", oCertificate.SerialNumber);
(7) Обратите внимание, что SignHash() отличается от МенеджерКриптографии.Подписать (в Кадескоме вроде тоже был Sign() у какого-то класса). Отличие в том, что SignHash никаких преобразований с подуписуемым хешем не делает - сразу вычисляет подпись для oHashedData без вычисления дайджеста (т.е. не вычисляется ХешХеша). Метод Подписать - сначала вычисляет дайджест и уже по нему вычисляет подпись. Т.е. если Методу Подписать скормить изначально полученный хеш - то МенеджерКриптографии из этого хеша вычислит еще один хеш, и для ХешХеша будет вычислять подпись.
"Вычислить подпись" и "подписать" - я имею в виду разные понятия. Подписать - это две операции 1) вычислить хеш; 2) вычислить подпись для полученного хеша.
(10) А, неправильный алгоритм - это сотый? Ну он устарел и запрещен вроде уже.
CADESCOM_HASH_ALGORITHM_CP_GOST_3411 Алгоритм ГОСТ Р 34.11-94.
=100
Вы уверены, что Вам хеш хеша надо подписывать? Просто первый хеш подписать не пробовали, без повторного хеширования? И это непонятно ХэшДвоичный = ПолучитьДвоичныеДанныеИзХеша(ХэшХексСтрока), там может какие-то нюансы с little endian.
МенеджерКриптографии не умеет переданный ему хеш подписывать по типу CADESCOM-ового SignHash(). Если делать как у Вас - то Менеджер сначала посчитает ХешХеша, а потом его и подпишет. Подписывайте исходные данные.
В процессе МенеджерКриптографии.Подписать происходит сначала вычисление хеша, а потом пополученному хешу вычисляется подись - она и возвращается как результат.
Хотя у Вас по ошибке даже дайджест не проходит (он же хэш). Т.е. уже хеш у Вас видимо неправильный. Смотрю свой код трехлетней давности, судя по нему по умолчанию переданную на хеширование строку Кадеском воспринимает просто как строку(CADESCOM_STRING_TO_UCS2LE), а не как бейс64. Чтобы он воспринял ее как бейс-64 нужно команду дать
HashedData.DataEncoding = 1;
Скопирую сюда что нашел, первый вариант с прямой передачей исходной строки у меня тогда не работал. Только бейс64 или в старой платформе - двоичные данные скармливал Кадескому - тогда результат норм. получался.
//Способ кодирования данных для подписи для пслеующего свойства ContentEncoding
CADESCOM_BASE64_TO_BINARY = 1; // Кодировка BASE64.
CADESCOM_STRING_TO_UCS2LE = 0; // Кодировка UTF-8 или UNICODE.
//oHashedData.DataEncoding = CADESCOM_STRING_TO_UCS2LE; //этот и так по умолчпнию
//прямая передача строки в ком (без флага раскодировки) дает другой хеш
//oHashedData.Hash(Строка); //врет (без oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY)
//Строка64 = Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(Строка)); //ПолучитьДвоичныеДанныеИзСтроки нет в 1с 8.9
//тмп = oHashedData.Value; //сбросим аккумуляцию хеша на всякий слуай
//oHashedData.Hash(Строка64);
UTF8Encoding = Новый COMОбъект("System.Text.UTF8Encoding");
//байты = UTF8Encoding.GetBytes_4(Строка); //массив чисел-байтов, каждый байт - буква переменной Строка
oHashedData.Hash(UTF8Encoding.GetBytes_4(Строка));
ХэшХексСтрока = oHashedData.Value;
Я на СМЭВе съел собаку, поэтому, если тема еще актуальна, могу предложить альтернативное решение. Начнем с того, что во-первых, вам нужно подписывать НЕ ХЕШ, А САМ ФАЙЛ. Во-вторых, подпись является НЕОБЯЗАТЕЛЬНОЙ. А хеш - обязательным. Теперь по вашей теме: рекомендую использовать внешнюю компоненту XMLDSign, либо ее современный аналог ExtraCryptoAPI. В типовых конфигурациях наподобие Розницы ее можно найти (могу скинуть в личку). Лично я использую первую, хотя вторая более универсальная (работает практически в любом браузере на веб-клиенте, на винде, на линухе и на маке. Первая же работает в веб-клиенте только на винде, и НЕ на веб-клиенте - на винде и на линухе. Обе работают как под 32, так и под 64-бит). У компоненты есть метод Hash. Идентификатор ("AddIn. ...") первой компоненты - XMLDSign, второй - ExtraCryptoAPI. Она возвращает в Base-64 формате готовый (тот, который нужен вам) хеш. Функция:
ДанныеДляХеширования: Тип - Строка или ДвоичныеДанные. То, что собираемся хешировать. Как видите, можно хешировать не только двоичные данные, но и строку, что очень пригождается при вычислении хеша от части xml, когда требуется получить подпись в формате xmldsign (опять же, пригодится и для подписи запросов в СМЭВ. Лично я использую. Единственная проблема - алгоритм трансформации СМЭВ в этой компоненте не заложен. Лично я писал его ручками прямо в 1С и он работает. Однако, в последней компоненте ExtraCryptoAPI уже есть готовый метод TransformSMEV, который также можно использовать. Когда я его писал - я про вторую компоненту еще не знал, поэтому написал руками)
OIDАлгоритмаХеширования: Тип - Строка. Идентификатор алгоритма хеширования, который будет использован для вычисления хеша. В твоем случае ГОСТ Р 34.11-2012 256 бит, его OID = "1.2.643.7.1.1.2.2". Если требуется 512 бит - то OID = "1.2.643.7.1.1.2.3"
ТипКриптопровайдера: Тип - Число. Его ты возмьешь уже из свойств твоих данных. Где у тебя там хранятся сертификаты или программы электронной подписи и шифрования. Например, если это КриптоПро (сертификат 256 бит), то его тип = 80, если же КриптоПро Стронг (сертификат 512 бит), то его тип = 81
Возвращаемое значение: Тип - Строка. Нужный хеш в формате Base-64. Если ничего не вернулось - значит произошла ошибка. Последнюю ошибку можно узнать через функцию компоненты GetLastError(). Однако, на последних версиях платформы (не помню с какой) на винде она возрвращает ошибку не в той кодировке. Поэтому, если видите крякозябры - перекодируйте ошибку из UTF-8 в ANSI
P.S. Где-то на каких-то форумах я читал, что ваш вариант хеширования тоже подойдет, только его нужно, кажется, повернуть в обратном направлении (то ли каждый байт развернуть побитово, то ли полубайты поменять местами, то ли целиком развернуть побайтово. Не помню. Кажется, полубайт. Т.е. например очередной байт в хеше 8A. После преобразования будет A8. Разумеется, я сейчас говорю про шестнадцатиричное представление хеша, а не про Base-64. Как перевести из одного в другое, думаю, разберетесь). Попробуйте различные варианты переворота хеша, если не хотите заморачиваться с внешней компонентой. Возможно, получится
P.P.S. На официальном сайте VipNET есть консольная утилита, которая возвращает нужный вам хеш от файла. Скачайте. Она бесплатная. Ее тоже можно использовать. Если не в коде 1С, то хотя бы для проверки. Она возвращает хеш, правда в шестнадцатиричном виде, но вы, опять же, без труда переведете в Base64. Утилита есть под винду и под линух
Поэтому, если видите крякозябры - перекодируйте ошибку из UTF-8 в ANSI
Добрый день! Подскажите, есть ли пример использования TransformSMEV с последующем чтении XML-строки после трансформации?
У нас как раз таки СМЭВ, использовали компоненту из БГУ Xades с методом ПодписатьXMLDSignСМЭВ3 для подписи, но с переходом серверов на Линукс начали сталкиваться с ошибкой, что кириллица возвращается как кракозябры... Попробовали на днях метод XMLDSig, подписывает нормально, потом трансформируем через TransformSMEV, и дальше надо модернизировать код для прочтения этой строки, так как она отличается от строки, которая у нас была при использовании ПодписатьXMLDSignСМЭВ3 ...
Для проверки правильности формирования дайджеста (хэша) XMLDSig найдите любое достоверное (прошедшее проверку подписи) XML-сообщение и отправьте его на вход своего алгоритма.
Рассчитанное значение сравните со значением элемента Signature/SignedInfo/DigestValue. Если дело только в изменении порядка байтов - Вы легко это исправите. Хуже, если Ваш алгоритм трансформации не соответствует актуальной версии (а версию алгоритма в СМЭВ в прошлом году поменяли).