2009-07-22 3 views
1

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

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

ответ

1

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

Если вы экспортируете сертификат, который будете использовать для записи данных в файл .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, который вы должны указать store securely в настройках конфигурации приложения. Вы можете сделать что-то подобное с файлом .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-документ не защищен паролем и небезопасен. (read the doc on ToXmlString()) Вы можете зашифровать этот XML-документ так же, как и зашифровать любые другие настройки. (search)

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

RSACryptoServiceProvider csp = new RSACryptoServiceProvider(); 
    csp.FromXmlString(keyPairXml); 
+0

Спасибо за ваш ответ и код. Вы хотите сказать, что мне нужно было бы попросить поставщика хостинга установить сертификат на свой сервер? или я просто положил его в один из моих каталогов, и он должен работать? CspProviderFlags.UseMachineKeyStore отключен на большинстве общих хостов. Я думаю, что RSACryptoServiceProvider не может быть создан, иначе я мог бы просто создать открытый закрытый ключ на своей машине и сделать ImportFromXml у поставщика услуг, как это отличается от использования сертификата? – AppDeveloper

+0

Если это файл pfx или .xml, то, конечно, вы можете просто загрузить его, как и любой другой файл. Это альтернатива «магазину машин», который вы используете с UseMachineKeyStore. Вы * думаете * RSACryptoServiceProvider не может быть создан? Это легко проверить. Возьмите мой код и скомпилируйте его и запустите. да, это правда: вы можете создать пару ключей на своем компьютере, загрузить его в xml-форму на хост, а затем ImportFromXml в размещенном приложении. Это прекрасно работает. – Cheeso

0

Да, можно использовать это в среде хостинга, но остерегайтесь мульти резьбой issues relating to its use

Вот некоторые предложения, чтобы свести к минимуму проблемы многопоточности в ASP.NET:

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

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

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

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

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