仅从公钥创建 RSACryptoServiceProvider

Posted

技术标签:

【中文标题】仅从公钥创建 RSACryptoServiceProvider【英文标题】:Create RSACryptoServiceProvider from public key ONLY 【发布时间】:2018-07-16 12:52:30 【问题描述】:

我正在使用密钥对签署我的 XML(使用 SignedXml),并将公钥作为嵌入式资源嵌入到我的应用程序中。

我如何创建密钥对

sn -k Warehouse.snk
sn -p Warehouse.snk WarehousePublic.snk

当我尝试阅读 WarehousePublic.snk 时,我得到一个异常 Bad Version of provider.

这是我的代码:

using (Stream stream = assembly.GetManifestResourceStream("WareApp.Resources.WarehousePublic.snk"))

    byte[] bytes = new byte[stream.Length];
    stream.Read(bytes, 0, bytes.Length);

    using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
    
        rsa.ImportCspBlob(bytes);  //the exception occurred here

        ...
        ...
        ...
    

有没有办法仅从公钥创建 RSACryptoServiceProvider

我也尝试过使用 X509Certificate2

X509Certificate2 cert = new X509Certificate2(bytes);  //I got exception here
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert2.PublicKey.Key;

但我得到异常找不到请求的对象。

有什么想法吗?

谢谢

【问题讨论】:

【参考方案1】:

我会接受 Shaamaan 的回答,因为他是“一半”正确的。您实际上可以使用 SN 来签署证书。 ImportCspBlob() 会起作用的!但是,当您尝试导入使用sn -p Warehouse.snk WarehousePublic.snk 生成的公钥时,它将不起作用。

为了使其工作,您需要使用RSACryptoServiceProvider.ToXmlString(false) 在 XML 中生成公钥并将其嵌入为“嵌入式资源”。

我所做的是创建一个控制台应用程序。只需在下面剪切并粘贴我的代码即可在 XML 文件中生成公钥。

class Program

    static void Main(string[] args)
    
        if (args.Length < 2)
        
            Console.WriteLine("Invalid Argument");
            Console.WriteLine("Usage:");
            Console.WriteLine("\tExtractPublicKey [Input SNK File] [Output XML File]");
            return;
        

        using (FileStream fs = File.Open(args[0], FileMode.Open, FileAccess.Read))
        
            byte[] bytes = new byte[fs.Length];
            fs.Read(bytes, 0, bytes.Length);

            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            
                rsa.ImportCspBlob(bytes);
                using (StreamWriter sw = new StreamWriter(File.Open(args[1], FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)))
                    sw.Write(rsa.ToXmlString(false));
            
        
    

编译后,要使用可执行文件,只需调用: ExtractPublicKey.exe [SNK File with Private Key] [Output Public Key in XML File]

要使用嵌入式证书,只需执行以下操作:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(stream.ReadToEnd());

我希望这对遇到类似问题的人有所帮助。

干杯

更新

应遵循 Shaamaan 的回答。请阅读带有 MSDN 链接的 Shaamaan 评论。他的回答是因为他不仅提供了正确的安全方法,而且还告诉我为什么 SN 不是正确的安全工具。谢谢你Shaamaan!

【讨论】:

感谢您的提醒。也就是说,MSDN 本身将SN 工具列为不利于安全性。不要误会我的意思,感谢您找到解决方法(我也为此+1;您可能还想接受您自己的答案而不是我的答案),但我敢说使用makecert.exe 可能是要走的路... ;) 天啊!你说的对!!!在这种情况下,你的答案是绝对正确的!谢谢Shaamaan!【参考方案2】:

我认为不支持使用SN 生成签名证书(至少使用RSACryptoServiceProvider)。我认为这可以解释错误。在 Windows 中,您要查找的是 .PFX 文件(即带密钥的证书)和 .CER 文件(不带私钥的证书)。

SN (MSDN link) 不提供安全性,仅用于身份识别。您可以使用 IIS 或 makecert.exe 生成一个自签名证书,该证书应该适用于您正在尝试执行的操作(即 .PFX 文件和/或已导入 Windows 证书存储的证书)。然后,您可以从中提取 .CER 文件并将其用于您的项目。

【讨论】:

嗨 Shaamaan,这就是我尝试过的方法(请参阅我的原始问题),但它不适用于错误 找不到请求的对象。 :(跨度> 哦,对不起@Sam,错过了第二点(用我的手机写了答案)。 @Sam 检查我的新答案 - 我完全错过了这个问题(再次,将此归咎于我的手机:P)

以上是关于仅从公钥创建 RSACryptoServiceProvider的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 仅从 SELECT 创建具有自动增量的临时表

如何仅从直方图值创建 KDE?

我可以仅从 SSLCertificateKeyFile.key 和 SSLCertificateFile.crt 文件创建 ssl 证书链吗?

如何创建临时表或仅从循环中的列中选择不同的值

是否可以仅从 std::any 使用 std::reference_wrapper 创建 std::any?

Jackson ObjectWriter 仅从流中写入第一个条目