繁体   English   中英

在托管环境中使用RSACryptoServiceProvider或RSA

[英]using RSACryptoServiceProvider or RSA in hosted environment

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

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

是的,很有可能。

如果将将用于数据签名的证书导出到.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文件执行类似的操作。

您还可以从常规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文档不受密码保护,并且不安全。 (请阅读ToXmlString()上的文档 )您可以加密此XML文档,就像加密任何其他设置一样。 搜寻

在这种情况下,您可以执行以下操作来获取csp:

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

是的,可以在托管环境中使用它,但是请注意与其使用相关的多线程问题

这些是一些建议,可以最大程度地减少ASP.NET中的线程问题:

  1. 创建RSACryptoServiceProvider对象时,设置CspParameters.KeyContainer名称。 永远不要使用默认值! 这容易导致存储损坏。 我们已经讨论过了。

  2. 如有可能,显式调用RSACrytpoServiceProvider对象上的Dispose。 这样,我们就不再依赖垃圾收集器“最终”发布CSP。

  3. 创建RSACryptoServiceProvider时,请在CspParameters.Flags中设置UseMachineKeyStore。 该标志告诉RSACryptoServiceProvider使用“机器位置”来存储RSA公共/私有密钥对,而不是“当前用户”位置。 这等效于使用CRYPT_MACHINE_KEYSET调用CryptAcquireContext API。 确保所有使用RSA实例的线程都在同一帐户下运行。

  4. 不要将RSACryptoServiceProvider.PersistKeyInCSP设置为False。 当释放RSA实例或进行垃圾回收时,这将导致密钥容器被删除。 如果多个线程试图访问相同的命名密钥容器,则该命名密钥容器的状态可能处于临时清除状态,因此无法获取。

  5. 另一种选择是,作为Web应用程序初始化的一部分,我们实例化一次RSACryptoServiceProvider,然后在诸如锁(例如Mutex)之类的关键部分下使用同一实例进行加密或解密。 这也将避免从同一过程中多次重新获取密钥容器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM