RSA Шифруют / Дешифруют проблему в.NET

У меня есть проблема с шифрованием C# и дешифрованием использования RSA. Я разработал веб-сервис, который будет отправлен чувствительную финансовую информацию и транзакции. То, что я хотел бы смочь сделать, находится на стороне клиента, Зашифруйте определенные поля с помощью клиентского закрытого ключа RSA, после того как это достигло моего сервиса, который это дешифрует с клиентским открытым ключом.

В данный момент я продолжаю заставлять "Данные быть дешифрованными, превышает максимум для этого модуля 128 байтов". исключение. Я не имел дело очень с криптографией C# RSA, таким образом, любая справка значительно ценилась бы.

Это - метод, который я использую для генерации ключей

private void buttonGenerate_Click(object sender, EventArgs e)
{
    string secretKey = RandomString(12, true);

    CspParameters param = new CspParameters();
    param.Flags = CspProviderFlags.UseMachineKeyStore;

    SecureString secureString = new SecureString();
    byte[] stringBytes = Encoding.ASCII.GetBytes(secretKey);
    for (int i = 0; i < stringBytes.Length; i++)
    {
        secureString.AppendChar((char)stringBytes[i]);
    }
    secureString.MakeReadOnly();
    param.KeyPassword = secureString;

    RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);
    rsaProvider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
    rsaProvider.KeySize = 1024;


    string publicKey = rsaProvider.ToXmlString(false);
    string privateKey = rsaProvider.ToXmlString(true);

    Repository.RSA_XML_PRIVATE_KEY = privateKey;
    Repository.RSA_XML_PUBLIC_KEY = publicKey;

    textBoxRsaPrivate.Text = Repository.RSA_XML_PRIVATE_KEY;
    textBoxRsaPublic.Text = Repository.RSA_XML_PUBLIC_KEY;

    MessageBox.Show("Please note, when generating keys you must sign on to the gateway\n" +
        " to exhange keys otherwise transactions will fail", "Key Exchange", MessageBoxButtons.OK, MessageBoxIcon.Information);

}

После того как я генерировал ключи, я отправляю открытый ключ в веб-сервис, который хранит его как XML-файл.

Теперь я решил протестировать это, таким образом, вот мой метод для шифрования строки

public static string RsaEncrypt(string dataToEncrypt)
{
    string rsaPrivate = RSA_XML_PRIVATE_KEY;
    CspParameters csp = new CspParameters();
    csp.Flags = CspProviderFlags.UseMachineKeyStore;

    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(csp);

    provider.FromXmlString(rsaPrivate);

    ASCIIEncoding enc = new ASCIIEncoding();
    int numOfChars = enc.GetByteCount(dataToEncrypt);
    byte[] tempArray = enc.GetBytes(dataToEncrypt);
    byte[] result = provider.Encrypt(tempArray, true);
    string resultString = Convert.ToBase64String(result);
    Console.WriteLine("Encrypted : " + resultString);
    return resultString;
}

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

public string DecryptRSA(string data, string merchantId)
{
    string clearData = null;
    try
    {
        CspParameters param = new CspParameters();
        param.Flags = CspProviderFlags.UseMachineKeyStore;
        RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);

        string merchantRsaPublic = GetXmlRsaKey(merchantId);
        rsaProvider.FromXmlString(merchantRsaPublic);
        byte[] asciiString = Encoding.ASCII.GetBytes(data);

        byte[] decryptedData = rsaProvider.Decrypt(asciiString, false);

        clearData = Convert.ToString(decryptedData);
    }
    catch (CryptographicException ex)
    {
        Log.Error("A cryptographic error occured trying to decrypt a value for " + merchantId, ex);

    }
    return clearData;
}

Если бы кто-либо мог бы помочь мне, который был бы удивительным, поскольку я сказал, что не сделал многого с шифрованием RSA C# / дешифрование.

17
задан John Saunders 19 March 2010 в 09:08
поделиться

5 ответов

Позвольте мне немного терминологии. Есть асимметричное шифрование и есть цифровая подпись.

  • Асимметричное шифрование - это сохранение конфиденциальности. Некоторые конфиденциальные данные преобразуются в нечто нечитаемое, кроме как для субъекта, знающего ключ расшифровки. Ключ расшифровки обязательно является закрытым ключом: если ключ расшифровки является открытым ключом, то все могут расшифровать данные (открытый ключ является открытым), и конфиденциальности больше нет. При асимметричном шифровании человек шифрует с помощью открытого ключа, а расшифровывает с помощью соответствующего закрытого ключа.

  • Цифровые подписи предназначены для доказательства целостности. Кто-то вычисляет своего рода контрольную сумму с ключом над данными таким образом, что связь между контрольной суммой и данными может быть проверена позже. Это "подпись" только потому, что для вычисления этой контрольной суммы требуется знание чего-то, что не является публичным - проще говоря, для подписи используется закрытый ключ. Проверка, однако, должна быть доступна любому, и, следовательно, использовать открытый ключ.

Изрядная доля путаницы связана с тем, что "алгоритм" RSA на самом деле является математической операцией, которую можно разложить как на систему асимметричного шифрования, так и на систему цифровой подписи. Путаницу еще больше усиливает стандарт RSA, он же PKCS#1, который неявно опирается на то, как цифровые подписи RSA были впервые описаны, то есть как "обратное шифрование" ("подписывающий шифрует данные своим закрытым ключом"). Это приводит к тому, что подписи RSA называются "sha1WithRSAEncryption". Это весьма прискорбно.

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

Кроме того, существует нечто, называемое аутентификацией, которая может выглядеть как цифровые подписи, но она слабее. Смысл подписей в том, что любой может проверить подпись. В частности, подпись может быть показана судье и таким образом служить юридическим оружием против подписанта (подпись юридически обязательна - по крайней мере, если вы все сделаете правильно, а при нынешнем состоянии регулирования электронных подписей это непросто). В большинстве ситуаций вам нужно что-то более слабое и простое, при котором сервер убежден, что разговаривает с нужным клиентом, но не может впоследствии убедить кого-либо еще, что этот клиент действительно был. Любой веб-сайт с пользовательскими паролями использует такую аутентификацию.

С учетом сказанного...

  • Асимметричное шифрование RSA охватывает только короткие сообщения. Для 1024-битного ключа RSA (т.е. ключа, в котором самая важная часть, "модуль RSA", является большим числом со значением между 2^1023 и 2^1024, а зашифрованные сообщения будут иметь длину 128 байт) максимальный размер зашифрованного сообщения составляет 117 байт (это фактический источник вашего сообщения об ошибке). Когда мы хотим отправить более длинные сообщения, мы используем гибридную систему, в которой мы шифруем только небольшой набор случайных бит (скажем, 128 бит) и используем этот набор как ключ для системы симметричного шифрования (например, AES), которая может обрабатывать гораздо более длинные сообщения (и гораздо быстрее).

  • Подписи RSA, аналогично, могут быть вычислены только на коротких сообщениях, поэтому стандарт PKCS#1 предписывает, что подпись фактически вычисляется по хэш-значению. Хэш-значение является результатом работы определенной хэш-функции, которая вычисляется над подписываемым сообщением. Хэш-функция имеет выход фиксированного размера (например, 256 бит для SHA-256), но принимает входные сообщения (почти) произвольной длины. Хеш-функции являются открытыми (в них нет ключа) и для обеспечения безопасности должны обладать некоторыми особыми свойствами. SHA-256 на данный момент является неплохим выбором. SHA-1 (предшественник SHA-256), как было доказано, имеет некоторые недостатки, и его следует избегать. MD5 (своего рода дядя SHA-1) имеет больше недостатков и не должен использоваться.

  • Правильное использование асимметричного шифрования, особенно в гибридной схеме, и цифровых подписей сложнее, чем может показаться из приведенного выше текста. Ужасно легко в какой-то момент ошибиться, незаметно, т.е. код будет выглядеть работающим, но при этом произойдет утечка данных, полезных для злоумышленника. правильный способ использования асимметричного шифрования или цифровых подписей заключается в использовании существующих, хорошо продуманных протоколов. Протокол - это сборка криптографических элементов в целостную систему, где утечки защищены. Ярким примером является протокол TLS, также известный как SSL. Это протокол, который обеспечивает конфиденциальную передачу данных, целостность и аутентификацию (возможно, взаимную аутентификацию). Протокол HTTPS представляет собой смесь HTTP и SSL. Положительной стороной является то, что HTTPS имеет существующие реализации, в частности, на C#. Код, который легче всего реализовать и отладить, - это код, который уже был реализован и отлажен. Так что используйте HTTPS, и вы будете жить дольше и счастливее.

34
ответ дан 30 November 2019 в 10:24
поделиться

Сначала решите, от чего вы пытаетесь защитить. Если вы «зашифруете» что-то с помощью закрытого ключа, любой может «расшифровать» это с помощью открытого ключа, поскольку открытый ключ - ну - открытый .

Если вы действительно хотите подписать его, вам следует (как объясняет Пол Александер) подписать хеш с закрытым ключом, который затем может быть проверен на сервере.

Чтобы зашифровать данные с помощью RSA, вы должны сначала сгенерировать случайный симметричный ключ (например, AES), зашифровать ключ с помощью открытого ключа и зашифровать данные с помощью симметричного ключа.Затем вы можете передать зашифрованный ключ вместе с зашифрованными данными держателю закрытого ключа , который затем может сначала расшифровать зашифрованный ключ закрытым ключом, а затем расшифровать данные симметричным ключом.

Вы также можете рассмотреть возможность использования SSL, но не забудьте тщательно продумать аутентификацию. Вам, вероятно, понадобится аутентификация клиента, и вам нужно будет решить, каким сертификатам доверять (вы не должны просто слепо принимать любой сертификат, выданный Verisign).

2
ответ дан 30 November 2019 в 10:24
поделиться

В DecryptRSA "данные" закодированы в base 64? Если да, то сначала нужно отменить это.

Честно говоря, я думаю, что вам не стоит самостоятельно применять эту процедуру для защиты "конфиденциальной финансовой информации", если у вас нет большого опыта в криптографии. Существует слишком много способов сделать ошибки. Лучше использовать какое-то готовое решение - может быть, SSL и сертификаты, или просто PGP или GnuPG?

.
3
ответ дан 30 November 2019 в 10:24
поделиться

RSA в основном используется для проверки безопасных хэшей данных - а не для шифрования самих данных. Так, при наличии большого объема данных вы можете использовать SHA512 для создания хэша этих данных, а затем использовать RSA для подписи этого хэша.

Для больших блоков данных лучше использовать алгоритм симметричного шифрования - что-то вроде AES или 3DES.

Управление безопасными транзакциями - дело непростое, и его следует оставить тем, кто думает об этом день и ночь. Если вы предоставляете услугу через Интернет, просто используйте SSL, который уже шифрует и защищает ваши данные.

3
ответ дан 30 November 2019 в 10:24
поделиться

Я понимаю, почему вы задаете вопрос. Проблема в том, что RSA не используется как типичный блочный шифр (например, AES или 3DES), который шифрует 8 байтов за раз в течение всего дня. RSA - это математическая операция, которая возвращает остаток от деления (модуль). Еще в начальной школе, когда вы выучили деление в столбик, помните, что остаток никогда не может быть больше делителя: если вы делите 20 на 7, ваш остаток равен 6. Независимо от того, какое целое число вы делите на 7, остаток не может быть больше чем шесть.

Математика RSA аналогична. Например, если вы используете 1024-битный открытый ключ RSA, остаток никогда не может быть больше 2 ^ 1024, что составляет всего 128 байт. Таким образом, вы можете зашифровать только 128 байтов за раз с помощью этого ключа. (Это одна из причин, по которой мы измеряем размер ключей RSA количеством битов.)

Технически вы можете использовать этот ключ RSA в цикле для шифрования 128-байтовых блоков данных за раз. На самом деле мы почти никогда этого не делаем, потому что математика RSA - БОЛЬШАЯ и МЕДЛЕННАЯ. Вместо этого мы используем так называемое «двухфазное» шифрование. Мы используем RSA для шифрования только короткого «сеансового ключа», а затем используем этот сеансовый ключ в быстром блочном шифре с симметричным ключом (например, AES) для шифрования фактических данных.

Весь протокол таков:

  1. Получите открытый ключ RSA вашего пункта назначения. Это часто встроено в сертификат; если это так, обязательно проверьте сертификат, чтобы убедиться, что ключ подлинный. Допустим, длина ключа RSA составляет 2048 бит.
  2. Сгенерируйте криптостойкое псевдослучайное число, которое будет использоваться в качестве ключа для блочного шифра (например, вам потребуется 256 бит в качестве ключа для AES-256.Обратите внимание, что 256 <2048, максимум, который RSA-2048 может зашифровать за один раз. Мы называем это случайное число «сеансовым ключом».
  3. Зашифруйте сеансовый ключ, используя 2048-битный открытый ключ RSA. Это даст вам 2048 бит зашифрованного сеансового ключа. Обратите внимание, что эта операция выполняется очень медленно.
  4. Зашифруйте все секретные данные с помощью AES-256, используя сеансовый ключ. Обратите внимание, что это намного быстрее, чем шаг 3.
  5. Объедините идентификатор открытого ключа из сертификата, зашифрованный ключ сеанса RSA и зашифрованные данные AES вместе. Я бы также пометил его идентификатором формата и номером версии, чтобы вы знали, в каком он формате и как его расшифровать.
  6. Отправьте пачку по назначению.

  7. В месте назначения вы используете идентификатор формата и версию для разборки пакета.

  8. Получить закрытый ключ, идентификатор которого указан в поле идентификатора открытого ключа.
  9. Используйте этот закрытый ключ в RSA для расшифровки сеансового ключа.
  10. Используйте сеансовый ключ в AES для дешифрования данных.

Если вы собираетесь это сделать, вы должны знать, что это именно то, для чего предназначен формат CMS (PKCS # 7). Я бы посоветовал вам узнать о стандарте и принять его, а не пытаться изобретать свой собственный формат. CSP Microsoft поддерживает это, так что это должно быть легко.

Если вы не следуете стандарту, вам придется принимать собственные решения о таких вещах, как «в каком формате должны быть биты ключа AES в процессе шифрования RSA?» Более вероятно, что вы почти наверняка сделаете ошибки безопасности, ослабив вашу систему. Кроме того, вы обнаружите, что с такими инструментами, как CSP, будет очень сложно работать, если вы не будете следовать стандарту.

14
ответ дан 30 November 2019 в 10:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: