Как работает ЭЦП RSA+SHA1? Как реализовать на C#? Добрый день! Интегрируемся с платежным шлюзом, который использует для верификации общения ЭЦП RSA+SHA1 с сертификатами X509. Нами был сформирован закртый ключ + сертификат, который мы отправили шлюзу. Шлюз в ответ сформировал сертификат на своей стороне и прислал два файла, CRT и KEY (содержит паблик кей). Насколько я понимаю алгоритм подписи, при отправке мы сначала от подписываемого контента считаем RSA, используя их сертификат(открытый ключ?), затем считаем sha1-хеш от полученного шифра. Вопрос: 1) Правильно ли я описал процесс? или есть еще шаги, которые я упускаю? 2) Сертификат содержит открытый ключ? если так, то нужен ли присланный шлюзом KEY-файл? Практическая часть. Реализацию делаем на C#. var content = "data"; var ctr = new X509Certificate2(filename); // путь до crt-файла присланного шлюзом var provider = ctr.PublicKey.Key as RSACryptoServiceProvider; // если после этой строки посмотрим на provider, то там действительно есть сертификат длинной 2048 var dta = provider.Encrypt(Encoding.ASCII.GetBytes(content), true); // в dta вроде бы 256 байт var sig = provider.SignData(dta, "SHA1"); // и тут мы ловим исключение "набор ключей не существует" 1) Что я делаю не так? Ключ то вроде есть? 2) если контент длиннее 2048 байт, то я предполагаю возникнут проблемы на этапе получения RSA-шифра. Предусмотрен ли механизм преодоления этой беды? или единственное решение изначальное формирование ключей длинной в 16кб (ну т.е. бОльшей длинны)? Спасибо.
1) Ваша интерпретация процесса ЭЦП правильна. Для подписи данных вы используете закрытый ключ из вашего сертификата, а для верификации шлюз использует свой открытый ключ. 2) Да, сертификат содержит открытый ключ. KEY файл, который вам прислал шлюз, также содержит открытый ключ, но его формат может отличаться от сертификата. Вам нужно использовать открытый ключ из сертификата для проверки подписи.
По вашей практической части: 1) Проблема возникает из-за того, что вы пытаетесь использовать открытый ключ для подписи данных, а его нужно использовать для верификации подписи. Для подписи данных вам нужно использовать закрытый ключ. Вы можете подписать данные с помощью метода SignData, передав открытые данные и алгоритм хеширования. Пример:
var ctr = new X509Certificate2(filename); RSACryptoServiceProvider provider = (RSACryptoServiceProvider)ctr.PrivateKey; byte[] data = Encoding.ASCII.GetBytes(content); byte[] signature = provider.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
2) Если контент длиннее 2048 байт, то нужно использовать другие алгоритмы подписи, такие как RSA с длиной ключа 3072 или 4096 бит. К сожалению, в стандартной библиотеке .NET Framework поддерживаются только алгоритмы RSA с ключом длиной до 2048 бит. Для использования более длинных ключей вам придется использовать другие библиотеки или реализации, такие как BouncyCastle или OpenSSL.
1) Ваша интерпретация процесса ЭЦП правильна. Для подписи данных вы используете закрытый ключ из вашего сертификата, а для верификации шлюз использует свой открытый ключ.
2) Да, сертификат содержит открытый ключ. KEY файл, который вам прислал шлюз, также содержит открытый ключ, но его формат может отличаться от сертификата. Вам нужно использовать открытый ключ из сертификата для проверки подписи.
По вашей практической части:
var ctr = new X509Certificate2(filename);1) Проблема возникает из-за того, что вы пытаетесь использовать открытый ключ для подписи данных, а его нужно использовать для верификации подписи. Для подписи данных вам нужно использовать закрытый ключ. Вы можете подписать данные с помощью метода SignData, передав открытые данные и алгоритм хеширования.
Пример:
RSACryptoServiceProvider provider = (RSACryptoServiceProvider)ctr.PrivateKey;
byte[] data = Encoding.ASCII.GetBytes(content);
byte[] signature = provider.SignData(data, CryptoConfig.MapNameToOID("SHA1"));
2) Если контент длиннее 2048 байт, то нужно использовать другие алгоритмы подписи, такие как RSA с длиной ключа 3072 или 4096 бит. К сожалению, в стандартной библиотеке .NET Framework поддерживаются только алгоритмы RSA с ключом длиной до 2048 бит. Для использования более длинных ключей вам придется использовать другие библиотеки или реализации, такие как BouncyCastle или OpenSSL.