с использованием RSACryptoServiceProvider или RSA в размещенной среде

Я хотел бы использовать общедоступное/частное шифрование, когда мое веб-приложение будет подписывать XML-документ или часть данных с помощью закрытого ключа, и это будет проверено в приложении с помощью открытого ключа,

Можно ли использовать RSACryptoServiceProvider в размещенной среде .net 2.0, если нет других возможных обходных путей?


person AppDeveloper    schedule 22.07.2009    source источник


Ответы (3)


См. здесь: http://www.codeproject.com/KB/security/EZRSA.aspx

person Jens    schedule 18.03.2010

Да, вполне возможно.

Если вы экспортируете сертификат, который будете использовать для подписи данных, в файл .pfx, вы можете получить digsig таким образом.

using System;
using System.Xml;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
// ...

static void SignWithPfxPrivateKey()
{
    X509Certificate2 certificate = new X509Certificate2(certFile, pfxPassword);
    RSACryptoServiceProvider rsaCsp = (RSACryptoServiceProvider) certificate.PrivateKey;   

    XmlDocument xmlDoc = new XmlDocument();

    xmlDoc.PreserveWhitespace = true;
    if (loadFromString)
      xmlDoc.LoadXml(rawXml);   // load from a string
    else 
      xmlDoc.Load("test.xml");  // load from a document 

    // Sign the XML document. 
    SignXml(xmlDoc, rsaCsp);

    // Save the document.
    xmlDoc.Save("RsaSigningWithCert.xml");

    xmlDoc.Save(new XTWFND(Console.Out));
}

public static void SignXml(XmlDocument Doc, RSA Key)
{
    // Check arguments.
    if (Doc == null)
        throw new ArgumentException("Doc");
    if (Key == null)
        throw new ArgumentException("Key");

    // Create a SignedXml object.
    SignedXml signedXml = new SignedXml(Doc);

    // Add the key to the SignedXml document.
    signedXml.SigningKey = Key;

    // Create a reference to be signed.
    Reference reference = new Reference();
    reference.Uri = "";

    // Add an enveloped transformation to the reference.
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);

    // Add the reference to the SignedXml object.
    signedXml.AddReference(reference);

    // Compute the signature.
    signedXml.ComputeSignature();

    // Get the XML representation of the signature and save
    // it to an XmlElement object.
    XmlElement xmlDigitalSignature = signedXml.GetXml();

    // Append the element to the XML document.
    Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
}

Чтобы использовать это, вам нужно будет загрузить файл .pfx на размещенный сервер. Вам также потребуется пароль для этого pfx-файла, который вы должны сохранить. безопасно в настройках конфигурации приложения. Вы можете сделать что-то подобное с файлом .cer.

Вы также можете загрузить ключ RSA из обычного XML. Если у вас есть RSACryptoServiceProvider, экземпляр которого вы создали, загрузив ключ из вашего локального хранилища компьютеров, например так:

  // Get the key pair from the key store.
  CspParameters parms = new CspParameters(1);
  parms.Flags = CspProviderFlags.UseMachineKeyStore;
  parms.KeyContainerName = "SnapConfig";
  parms.KeyNumber = 2;
  RsaCsp = new RSACryptoServiceProvider(parms);

... затем вы можете экспортировать этот ключ с помощью

RsaCsp.ToXmlString(true);  

Результатом является строка, содержащая XML-документ, который можно сохранить в файл, а затем загрузить на размещенный сервер. Альтернатива файлу .pfx в качестве хранилища для вашей пары ключей. Будьте осторожны. Этот XML-документ не защищен паролем и небезопасен. (прочитайте документ по ToXmlString()) Вы можете зашифровать этот XML-документ так же, как и любые другие настройки. (поиск)

В этом случае вы можете сделать это, чтобы получить свой csp:

  RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
  csp.FromXmlString(keyPairXml);
person Cheeso    schedule 29.07.2009
comment
Спасибо за ваш ответ и код. Вы имеете в виду, что мне придется просить провайдера виртуального хостинга установить сертификат на их сервер? или я просто поместил его в один из моих каталогов, и он должен работать? CspProviderFlags.UseMachineKeyStore отключен на большинстве общих узлов. Я думаю, что RSACryptoServiceProvider не может быть создан, иначе я мог бы просто сгенерировать открытый закрытый ключ на своем компьютере и выполнить ImportFromXml для поставщика услуг, чем это отличается от использования сертификата? - person AppDeveloper; 30.07.2009
comment
Если это файл pfx или файл .xml, то, конечно, вы можете просто загрузить его, как и любой другой файл. Это альтернатива машинному хранилищу, которое вы используете с UseMachineKeyStore. Вы думаете, что нельзя создать экземпляр RSACryptoServiceProvider? Это легко проверить. Возьмите мой код, скомпилируйте его и запустите. да, это правда: вы можете сгенерировать пару ключей на своем компьютере, загрузить ее в виде xml на хост, а затем ImportFromXml в размещенном приложении. Это прекрасно работает. - person Cheeso; 30.07.2009

Да, это можно использовать в размещенной среде, но остерегайтесь многопоточного проблемы, связанные с его использованием

Вот несколько советов по минимизации проблем с потоками в ASP.NET:

  1. Задайте имя CspParameters.KeyContainer при создании объекта RSACryptoServiceProvider. Никогда не используйте стандартную версию, НИКОГДА! Это склонно к повреждению хранилища. Мы говорили об этом уже.

  2. Явно вызывайте Dispose для объекта RSACrytpoServiceProvider, когда это возможно. Таким образом, мы не полагаемся на сборщик мусора, чтобы «в конечном итоге» выпустить CSP.

  3. Установите UseMachineKeyStore в CspParameters.Flags при создании RSACryptoServiceProvider. Этот флаг указывает RSACryptoServiceProvider использовать «местоположение компьютера» для хранения пары открытого и закрытого ключей RSA вместо местоположения «текущего пользователя». Это эквивалентно вызову CryptAcquireContext API с CRYPT_MACHINE_KEYSET. Убедитесь, что все потоки, использующие экземпляр RSA, выполняются под одной и той же учетной записью.

  4. Не устанавливайте для RSACryptoServiceProvider.PersistKeyInCSP значение False. Это приведет к удалению контейнера ключей при освобождении экземпляра RSA или сборке мусора. Если несколько потоков пытаются получить доступ к одному контейнеру именованных ключей, состояние этого контейнера именованных ключей может находиться во временном очищенном состоянии, и его нельзя получить.

  5. Другой вариант — создать экземпляр RSACryptoServiceProvider один раз как часть инициализации веб-приложения, а затем использовать тот же экземпляр для шифрования или дешифрования в критической секции, такой как блокировка (т. е. Mutex). Это также позволит избежать многократного повторного получения контейнера ключей из одного и того же процесса.

person halfbit    schedule 03.07.2012