【问题标题】:extract private key bytes in C#在 C# 中提取私钥字节
【发布时间】:2011-09-09 16:02:20
【问题描述】:

我目前能够使用 OpenSSL 使用以下命令从 PFX 文件中提取私钥:

openssl pkcs12 -in filename.pfx -nocerts -out privateKey.pem

openssl.exe rsa -in privateKey.pem -out private.pem

private.pem 文件以---BEGIN RSA PRIVATE KEY--- 开头,以---END RSA PRIVATE KEY--- 结尾

我想在 C# 中使用 .NET 库或 Bouncy Castle 库来做同样的事情。

我该怎么做?

【问题讨论】:

标签: .net openssl


【解决方案1】:

这对我有用。也应该为您工作:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;

namespace SO6258771
{
    class Program
    {
        static void Main()
        {
            // Load your certificate from file
            X509Certificate2 certificate = new X509Certificate2("filename.pfx", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

            // Now you have your private key in binary form as you wanted
            // You can use rsa.ExportParameters() or rsa.ExportCspBlob() to get you bytes
            // depending on format you need them in
            RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;

            // Just for lulz, let's write out the PEM representation of the private key
            // using Bouncy Castle, so that we are 100% sure that the result is exaclty the same as:
            // openssl pkcs12 -in filename.pfx -nocerts -out privateKey.pem
            // openssl.exe rsa -in privateKey.pem -out private.pem

            // You should of course dispose of / close the streams properly. I'm skipping this part for brevity
            MemoryStream memoryStream = new MemoryStream();
            TextWriter streamWriter = new StreamWriter(memoryStream);
            PemWriter pemWriter = new PemWriter(streamWriter);

            AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(rsa);
            pemWriter.WriteObject(keyPair.Private);
            streamWriter.Flush();

            // Here is the output with ---BEGIN RSA PRIVATE KEY---
            // that should be exactly the same as in private.pem
            Console.Write(Encoding.ASCII.GetString(memoryStream.GetBuffer()));
        }
    }
}

【讨论】:

  • 我的构建环境中的 WriteObject 方法在我的 vs2008 编辑器中以红色下划线显示。错误显示:错误 1 ​​'Org.BouncyCastle.Utilities.IO.Pem.PemWriter.WriteObject(Org.BouncyCastle.Utilities.IO.Pem.PemObjectGenerator)' 的最佳重载方法匹配有一些无效参数。这里有什么问题?
  • 包含RsaPrivateCrtKeyParameters 而不是Org.BouncyCastle.Utilities.IO.Pem 这就是为什么@Subbu 在编译期间有无效参数的原因。
  • @CodeMonkeyKing 谢谢。我错了using 并且已经为此苦苦挣扎了一段时间。 ..IO.Pem 似乎是一个看似合理的命名空间。
【解决方案2】:

我发现 PEMwriter 仅适用于 VS2005 中的 .NET 2.0。 .NET 3.5 SDK 环境强调 pemWriter.WriteObject(keyPair.Private); 是由于转换问题导致的错误。如果您尝试将其转换为 PEMObjectGenerator 并最终构建和调试代码,则当调试器到达这行代码时会引发 InvalidCastException。我也会在充气城堡论坛上公布这一点。

【讨论】:

  • 我对此表示纠正。它适用于 .NET 3.5 和 .NET 2.0。由于我添加了 using 命名空间,出现了转换问题。
  • 您可以将其编辑到您的问题中,而不是将其保留为答案/评论吗?谢谢。
  • @Bill:当我读到它时,这一个答案——它恰好是个坏消息。
  • 我同意@John 的观点……这听起来像是一个完全有效的自我回答,尽管有很多标志。
【解决方案3】:

Bouncy Castle C# API 似乎已更改,当前答案不再有效。我现在找不到关于如何使用它的任何答案,所以我将留下这个更新的示例。诀窍是使用MiscPemGenerator

void ConvertPfxToPem(
    string pfxPath,
    string pfxPassword,
    string keyPath)
{
    using (Stream stream = File.Open(pfxPath, FileMode.Open))
    {
        Pkcs12Store pkcs = new Pkcs12Store(stream, pfxPassword.ToCharArray());

        foreach (string alias in pkcs.Aliases)
        {
            if (pkcs.IsKeyEntry(alias) && pkcs.GetKey(alias).Key.IsPrivate)
            {
                AsymmetricKeyParameter privateKey = pkcs.GetKey(alias).Key;

                using (Stream s = new FileStream(keyPath, FileMode.Create))
                using (TextWriter textWriter = new StreamWriter(s))
                {
                    var generator = new MiscPemGenerator(privateKey);

                    PemWriter pemWriter = new PemWriter(textWriter);
                    pemWriter.WriteObject(generator);
                    textWriter.Flush();
                }
            }
        }
    }
}

【讨论】:

    【解决方案4】:

    System.Security.Cryptography.X509.x509certificate2 类具有 PrivateKey 属性

    您可以从 X509Store 对象中获取 x509certificate2 对象

    如果您拥有私钥的权限,那么它将位于 X509Certificate2 对象中(因此该对象并不真正代表证书)

    【讨论】:

      猜你喜欢
      • 2011-07-31
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多