在托管环境中使用RSACryptoServiceProvider或RSA

时间:2009-07-22 19:29:20

标签: c# encryption rsa digital-signature

我想使用公共/私人加密,我的网络应用会使用私钥对xml文档或数据进行签名,并且将使用公钥在应用程序中进行验证,

是否可以在.net 2.0托管环境中使用RSACryptoServiceProvider,如果不是其他可能的解决方法?

3 个答案:

答案 0 :(得分:1)

是的,很有可能。

如果您导出用于数据签名的证书到.pfx文件,您可以通过这种方式获取数据。

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文件执行类似的操作。

您还可以从常规XML加载RSA密钥。如果您有一个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

在这种情况下,你可以这样做来获取你的csp:

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

答案 1 :(得分:0)

答案 2 :(得分:0)

是的,可以在托管环境中使用它,但要注意多线程issues relating to its use

这些是一些最小化ASP.NET中的线程问题的建议:

  
      
  1. 创建RSACryptoServiceProvider对象时设置CspParameters.KeyContainer名称。永远不要使用默认的!   这容易造成商店腐败。我们已经讨论了这个问题。

  2.   
  3. 尽可能在RSACrytpoServiceProvider对象上显式调用Dispose。这样,我们就不依赖垃圾收集器了   “最终”释放了CSP。

  4.   
  5. 在创建RSACryptoServiceProvider时在CspParameters.Flags中设置UseMachineKeyStore。此标志告诉RSACryptoServiceProvider   使用“机器位置”来存储RSA公钥/私钥对   “当前用户”位置。这相当于打电话   带有CRYPT_MACHINE_KEYSET的CryptAcquireContext API。确保所有的   使用RSA实例的线程在同一帐户下运行。

  6.   
  7. 不要将RSACryptoServiceProvider.PersistKeyInCSP设置为False。这将导致在RSA实例时删除密钥容器   释放或垃圾收集。如果多个线程正在尝试   访问相同的命名密钥容器,该命名密钥的状态   容器可能处于临时清理状态,但不可能   获得的。

  8.   
  9. 另一个选择是我们在Web应用程序中实例化一次RSACryptoServiceProvider   初始化然后使用相同的实例进行加密或   在像锁(即Mutex)这样的关键部分下进行解密。这个会   同时避免多次从密钥容器中重新获取密钥容器   过程

  10.