在托管环境中使用 RSACryptoServiceProvider 或 RSA

发布于 2024-07-29 01:06:25 字数 141 浏览 1 评论 0原文

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

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

I would like to use Public/Private encryption where my web app would sign an xml document or a piece of data using a private key and it will be verified in the application using the public key,

Is it possible to use RSACryptoServiceProvider in .net 2.0 hosted environment if not what are other possible workarounds?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深巷少女 2024-08-05 01:06:25

是的,很有可能。

如果将用于数据签名的证书导出到 .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);

Yes, quite possible.

If you export the cert you will use for data-signing into a .pfx file, you can get a digsig this way.

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));
}

To use this, you will have to upload a .pfx file to the hosted server. You also need a password for that pfx file, which you should store securely in application config settings. You can do something similar with a .cer file.

You can also load the RSA key from regular XML. If you have an RSACryptoServiceProvider that you instantiated by loading a key from your local machine store, like this:

  // 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);

...then you can export that key with

RsaCsp.ToXmlString(true);  

The result is a string, containing an XML document that you can save to a file, and then upload to the hosted server. An alternative to the .pfx file as a store for your key pair. Be careful. This xml document is not protected with a password, and is insecure. (read the doc on ToXmlString()) You can encrypt this XML doc, just as you would encrypt any other settings. (search)

In that case you can do this to get your csp:

  RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
  csp.FromXmlString(keyPairXml);
是伱的 2024-08-05 01:06:25

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

这些是最小化 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. 另一种选择是我们将 RSACryptoServiceProvider 作为 Web 应用程序的一部分实例化一次
    初始化,然后使用同一实例进行加密或
    在像锁(即互斥锁)这样的关键部分下解密。 这个会
    还避免从同一个容器多次重新获取密钥容器
    流程。

Yes, it is possible to use this in a hosted environment, but beware of the multi threaded issues relating to its use

These are some suggestions to minimize threading issues in ASP.NET:

  1. Set CspParameters.KeyContainer name when creating an RSACryptoServiceProvider object. Never use the default one, NEVER!
    This is prone to store corruption. We talked about this already.

  2. Explicitely call Dispose on the RSACrytpoServiceProvider object when possible. This way, we don't rely on the Garbage Collector to
    "eventually" release the CSP.

  3. Set UseMachineKeyStore in CspParameters.Flags when creating an RSACryptoServiceProvider. This flag tells RSACryptoServiceProvider to
    use "machine location" for storing RSA public/private key pair instead
    of the "current user" location. This is equivalent to calling
    CryptAcquireContext API with CRYPT_MACHINE_KEYSET. Make sure all the
    threads using the RSA instance are running under the same account.

  4. Don't set RSACryptoServiceProvider.PersistKeyInCSP to False. This will cause the key container to be deleted when RSA instance is
    released or garbage collected. If multiple threads are trying to
    access the same named key container, the state of that named key
    container could be in a temporary cleaned up state and it cannot be
    acquired.

  5. Another option would be for us to instantiate RSACryptoServiceProvider once as part of Web Application
    initialization and then use that same instance for encryption or
    decryption under a critical section like lock (i.e. Mutex). This would
    also avoid reacquiring key container multiple times from the same
    process.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文