![](/img/trans.png)
[英]How to create a RSA key in the machine for using in RSACryptoServiceProvider?
[英]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中的线程问题:
创建RSACryptoServiceProvider对象时,设置CspParameters.KeyContainer名称。 永远不要使用默认值! 这容易导致存储损坏。 我们已经讨论过了。
如有可能,显式调用RSACrytpoServiceProvider对象上的Dispose。 这样,我们就不再依赖垃圾收集器“最终”发布CSP。
创建RSACryptoServiceProvider时,请在CspParameters.Flags中设置UseMachineKeyStore。 该标志告诉RSACryptoServiceProvider使用“机器位置”来存储RSA公共/私有密钥对,而不是“当前用户”位置。 这等效于使用CRYPT_MACHINE_KEYSET调用CryptAcquireContext API。 确保所有使用RSA实例的线程都在同一帐户下运行。
不要将RSACryptoServiceProvider.PersistKeyInCSP设置为False。 当释放RSA实例或进行垃圾回收时,这将导致密钥容器被删除。 如果多个线程试图访问相同的命名密钥容器,则该命名密钥容器的状态可能处于临时清除状态,因此无法获取。
另一种选择是,作为Web应用程序初始化的一部分,我们实例化一次RSACryptoServiceProvider,然后在诸如锁(例如Mutex)之类的关键部分下使用同一实例进行加密或解密。 这也将避免从同一过程中多次重新获取密钥容器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.