Добрый день.
Пытаюсь реализовать на сервере проверку подписи хэша документа по ГОСТ Р 34.11-2012 256.
Проштудировал все доки, SDK и форум, находил смежные ответы (например
тут), однако советы в тех ветках не помогли. КриптоПро .net лицензия куплена)
В результате проверки всегда получаю False. При этом при проверки подписи по хэш функции на Госуслугах все ок - подпись верна. Так же проверял на
https://dss.cryptopro.ru/Verify/Verify/, отсоединенная подпись в формате GOST R 34.11-94 - результат "Подпись действительна". То есть в подписи и полученном хэше 100% нет проблем.
Хэш значение файла высчитанное по Госту:
Код:625f2a9064c66e0322894f545a1ccd9528fb95bc90adcfa8d889145983860416
Base64 значение, которое передается на сервер и в функцию проверки подписи:
Код:Yl8qkGTGbgMiiU9UWhzNlSj7lbyQrc+o2IkUWYOGBBY=
Сама подпись в base64:
Код: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
В бинарном виде
signature.zip
(2kb) загружен 3 раз(а).Пробовал несколько вариантов, и с Gost2012_256SignatureDeformatter и через Gost3410_2012_256CryptoServiceProvider.
Собственно:
Клиент загружает документ. На клиенте через js высчитывается Гост хэш файла, данный хэш подписывается плагином в js, после чего на сервер передается хэш и его подпись. На сервере есть открытый ключ сертификата, через который можно проверить подпись.
Функция проверки подписи хэша:
Естественно вначале конвертирую подпись и хэш из base64 в byte array через Convert.FromBase64String
Код:
public static bool VerifySignatureHash(X509Certificate2 signerCert , byte[] hash, byte[] sig)
{
//Попытка 1 через Gost2012_256SignatureDeformatter - False
/*
Gost2012_256SignatureDeformatter deformater = new Gost2012_256SignatureDeformatter(signerCert.PublicKey.Key);
deformater.SetHashAlgorithm("Gost3411_2012_256");
//Так же пытался реверсить подпись туда-сюда,
Array.Reverse(sig);
bool ret = deformater.VerifySignature(hash, sig);
return ret;
*/
//Попытка 2 через Gost3410_2012_256CryptoServiceProvider - False
Gost3410_2012_256CryptoServiceProvider publicProv = (Gost3410_2012_256CryptoServiceProvider)(signerCert.PublicKey.Key);
bool ret = publicProv.VerifySignature(hash, sig);
return ret;
//Аналог попытки 2
/*using (var signerPubKey = signerCert.PublicKey.Key)
{
if (!(signerPubKey is Gost3410_2012_256CryptoServiceProvider gost3410_2012_256))
{
throw new Exception("Поддерживаются только сертификаты с ключом ГОСТ Р 34.10-2012 256(512)");
}
return gost3410_2012_256.VerifySignature(hash, sig);
}*/
}
При этом используются аналогичные конструкции для проверки подписи по цельным данным, которые идеально работают, например:
Код:
public static bool VerifySignature(X509Certificate2 signerCert , byte[] sig, byte[] data)
{
using (var signerPubKey = signerCert.PublicKey.Key)
{
if (!(signerPubKey is Gost3410_2012_256CryptoServiceProvider gost3410_2012_256))
{
throw new Exception("Поддерживаются только сертификаты с ключом ГОСТ Р 34.10-2012 256(512)");
}
// Объект, реализующий алгоритм вычисления хэш по ГОСТ Р 34.11-2012 256
using (var hashAlg = new Gost3411_2012_256CryptoServiceProvider())
{
return gost3410_2012_256.VerifyData(data, hashAlg, sig);
}
}
}
Аналогично я в курсе как сделать проверку подписи как в SDK, даже есть метод, которые реализует проверку через new SignedCms. Но тут именно задача проверить подпись через подписанное хэш значение документа, а не сам файл.
Так же пробовал всё тоже самое с VerifyHash вместо VerifySignature, результат идентичный - False.
Подскажите пожалуйста, где в итоге я ошибаюсь и как правильнее сделать данную проверку подписи хэша файла при отсутствии изначальных бинарных значений файла. Спасибо!
Отредактировано пользователем 24 марта 2021 г. 13:06:11(UTC)
| Причина: Не указана