Подтвердить что ты не робот

Проблема шифрования/дешифрования RSA в .NET.

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

В настоящий момент я продолжаю получать "Данные, подлежащие расшифровке, превышают максимальный для этого модуля 128 байт". исключение. Я не очень разбирался в криптографии С# 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 web-методе, который я создал, я затем беру эти зашифрованные данные, пытаюсь расшифровать данные с помощью открытого ключа клиентов и отправить их обратно в clear. Но это исключение. Вот мой метод, ответственный за это.

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-шифрованием/расшифровкой.

4b9b3361

Ответ 1

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

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

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

Яркая путаница объясняется тем, что "алгоритм RSA на самом деле является математической операцией, которая может быть отклонена как в асимметричной системе шифрования, так и в системе цифровой подписи. Путаница еще более усиливается стандартом RSA, aka 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 имеет существующие реализации, особенно в С#. Код, который проще всего реализовать и отлаживать, - это код, который уже был реализован и отлажен. Поэтому используйте HTTPS, и вы будете жить дольше и счастливее.

Ответ 2

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

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

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

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

  • Получить открытый ключ RSA вашего адресата. Это часто предоставляется в сертификате; если это так, обязательно проверьте сертификат, чтобы убедиться, что ключ является подлинным. Скажем, что ключ RSA имеет длину 2048 бит.
  • Создайте криптографически сильное псевдослучайное число, которое будет использоваться в качестве ключа для шифрования блока (например, вам понадобится 256 бит в качестве ключа для AES-256). Обратите внимание, что 256 < 2048, максимальный, который RSA-2048 может зашифровать сразу. Мы вызываем это случайное число "ключ сеанса".
  • Шифровать ключ сеанса с помощью открытого ключа RSA 2048 бит. Он даст вам 2048 бит зашифрованного ключа сеанса. Обратите внимание, что эта операция выполняется очень медленно.
  • Зашифруйте все секретные данные с помощью AES-256, используя ключ сеанса. Обратите внимание, что это намного быстрее, чем шаг 3.
  • Свяжите идентификатор открытого ключа из сертификата, зашифрованного ключа сеанса RSA и данных AES зашифрованных данных. Я бы также пометил его идентификатором формата и номером версии, чтобы вы знали, в каком формате он находится и как его расшифровывать.
  • Отправьте пакет в пункт назначения.

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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