我想使用公共/私人加密,我的网络应用程序将使用私钥签署 xml 文档或一段数据,并将使用公钥在应用程序中对其进行验证,
如果没有其他可能的解决方法,是否可以在 .net 2.0 托管环境中使用 RSACryptoServiceProvider?
我想使用公共/私人加密,我的网络应用程序将使用私钥签署 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);
见这里: http: //www.codeproject.com/KB/security/EZRSA.aspx
是的,可以在托管环境中使用它,但要注意与其使用相关的多线程问题
这些是减少 ASP.NET 中的线程问题的一些建议:
创建 RSACryptoServiceProvider 对象时设置 CspParameters.KeyContainer 名称。永远不要使用默认的,永远不要!这很容易导致存储损坏。我们已经谈过了。
尽可能在 RSACrytpoServiceProvider 对象上显式调用 Dispose。这样,我们就不会依赖垃圾收集器来“最终”发布 CSP。
创建 RSACryptoServiceProvider 时,在 CspParameters.Flags 中设置 UseMachineKeyStore。此标志告诉 RSACryptoServiceProvider 使用“机器位置”来存储 RSA 公钥/私钥对而不是“当前用户”位置。这相当于使用 CRYPT_MACHINE_KEYSET 调用 CryptAcquireContext API。确保使用 RSA 实例的所有线程都在同一帐户下运行。
不要将 RSACryptoServiceProvider.PersistKeyInCSP 设置为 False。这将导致在释放 RSA 实例或进行垃圾收集时删除密钥容器。如果多个线程试图访问同一个命名密钥容器,则该命名密钥容器的状态可能处于临时清理状态并且无法获取。
另一种选择是我们将 RSACryptoServiceProvider 实例化一次,作为 Web 应用程序初始化的一部分,然后在锁(即互斥锁)等关键部分下使用相同的实例进行加密或解密。这也将避免从同一进程中多次重新获取密钥容器。