首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无法导入RSA私钥:“提供程序的错误版本”

无法导入RSA私钥:“提供程序的错误版本”
EN

Stack Overflow用户
提问于 2019-05-30 15:26:05
回答 2查看 2.8K关注 0票数 5

我有一个随机私钥("C:\tmp\private.key"):

代码语言:javascript
复制
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDHikastc8+I81zCg/qWW8dMr8mqvXQ3qbPAmu0RjxoZVI47tvs
kYlFAXOf0sPrhO2nUuooJngnHV0639iTTEYG1vckNaW2R6U5QTdQ5Rq5u+uV3pMk
7w7Vs4n3urQ6jnqt2rTXbC1DNa/PFeAZatbf7ffBBy0IGO0zc128IshYcwIDAQAB
AoGBALTNl2JxTvq4SDW/3VH0fZkQXWH1MM10oeMbB2qO5beWb11FGaOO77nGKfWc
bYgfp5Ogrql4yhBvLAXnxH8bcqqwORtFhlyV68U1y4R+8WxDNh0aevxH8hRS/1X5
031DJm1JlU0E+vStiktN0tC3ebH5hE+1OxbIHSZ+WOWLYX7JAkEA5uigRgKp8ScG
auUijvdOLZIhHWq7y5Wz+nOHUuDw8P7wOTKU34QJAoWEe771p9Pf/GTA/kr0BQnP
QvWUDxGzJwJBAN05C6krwPeryFKrKtjOGJIniIoY72wRnoNcdEEs3HDRhf48YWFo
riRbZylzzzNFy/gmzT6XJQTfktGqq+FZD9UCQGIJaGrxHJgfmpDuAhMzGsUsYtTr
iRox0D1Iqa7dhE693t5aBG010OF6MLqdZA1CXrn5SRtuVVaCSLZEL/2J5UcCQQDA
d3MXucNnN4NPuS/L9HMYJWD7lPoosaORcgyK77bSSNgk+u9WSjbH1uYIAIPSffUZ
bti+jc1dUg5wb+aeZlgJAkEAurrpmpqj5vg087ZngKfFGR5rozDiTsK5DceTV97K
a3Y+Nzl+XWTxDBWk4YPh2ZlKv402hZEfWBYxUDn5ZkH/bw==
-----END RSA PRIVATE KEY-----  

我尝试使用RSACryptoServiceProvider.ImportCspBlob来导入它,但失败了,并显示以下错误:

完整堆栈跟踪:

代码语言:javascript
复制
Failed: System.Security.Cryptography.CryptographicException: Bad Version of provider.

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils._ImportCspBlob(Byte[] keyBlob, SafeProvHandle hProv, CspProviderFlags flags, SafeKeyHandle& hKey)
   at System.Security.Cryptography.Utils.ImportCspBlobHelper(CspAlgorithmType keyType, Byte[] keyBlob, Boolean publicOnly, CspParameters& parameters, Boolean randomKeyContainer, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.ImportCspBlob(Byte[] keyBlob)
   at ConsoleApplication3.Program.DecodeRSA(Byte[] data, Int32 c_data) in C:\Users\myuser\Documents\Visual Studio 2015\Projects\myproj\ConsoleApplication3\Program.cs:line 28
   at ConsoleApplication3.Program.Main(String[] args) in C:\Users\myuser\Documents\Visual Studio 2015\Projects\myproj\ConsoleApplication3\Program.cs:line 14
Press any key to continue . . .

你知道我做错了什么吗?

这是我的代码:

代码语言:javascript
复制
using System;
using System.Security.Cryptography;

namespace ConsoleApplication3
{
    class Program
    {
        static public byte[] privateKey;
        static void Main(string[] args)
        {
            try
            {
                privateKey = System.IO.File.ReadAllBytes(@"C:\tmp\private.key");
                DecodeRSA(privateKey);
            }
            catch(Exception e)
            {
                Console.WriteLine("Failed: {0}", e);
            }
        }

        static public void DecodeRSA(byte[] data)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportCspBlob(Program.privateKey);
            }
        }

    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-03 15:47:31

多亏了@Topaco的回答,我知道我需要找到CSP blob,就像他提到的,它是没有文档记录的。

所以我只是使用byte[] a = rsa.ExportCspBlob(true);来获取它。

我将字节转换为base64,这是适用于我的base64中的正确密钥格式:

代码语言:javascript
复制
BwIAAACkAABSU0EyAAQAAAEAAQD99dvdVctFcYP6fGCvz/8QcoJqjpfKMPxCIsVRAZSCaKTB6Dl0DbEQBcaLNe8Cm31lzMYyf/2vh6gM+GUHmKcBYo2Z7JvauTGXFXEyv02ai8RINlvAGAicZwWoyGJb5h4sM881Q5+BuDTcoyefk+b7x7KBQjMD/wNuPCWijZ0lsP+Gt1tPryE757QDDl95jQk04ZS+70vGOAO836f+RCyeA6c0ZEA1eYzsM/PVsv+nLwh7pTj7KLFSha5CM304SdcDnyOnt1ARyv1BQsRhyN3IAOH/Se00OfWhcc0sZCjg+xvDebKuoODHDhUfHJPchOmyvhSxjyNACJuxg1uGh3XRmaPoceXXFCuNhFGheK5cQrfUGHpWeJKrpWM/+f3XcrYob0jQCloBIicXfvhhPnkPojiOquxmjy0rA8/JRjHov3+znJY+pQgFC5cUmvGWxhWygm+qDwYco6yCSRkkaIp/K39uJXQ2pQf9XapqjtAJipRo5xX0o/itiDyF1qPT7TumZROMUhU3znXGnxPelZ2bA7SgPiu6BBKADfqG1XJE1K50ydaEfyXYceYHIs7UAMLw9aTptqHbPPGp1hDL2xpWBR6hvqkPqouiVJ7VgPHkjxwT/hgXBvJbHOm/ghq/xA/1oTtXLJHXCASVdylt+nwauOp5qR0Dfdbz7IQGjChYzBHuqDuKorpmfHhZl+bDTHpJ1PjWrojoBfAt2v5zlBnw/ipjkD9MXKrNlPqbgeYXUAeAzfFKQhF2kr3zlmExIS8=  

重要的是要提到,我只需要这个函数将成功通过,因为我在一个黑盒应用程序上工作,我不能改变代码,我需要提供正确的输入。

票数 1
EN

Stack Overflow用户

发布于 2019-05-31 06:38:20

您的私钥具有PKCS1-PEM-Format。Private key BLOBs有另一种格式。正如评论中已经提到的,格式非常不同,不容易转换(例如,参见here)。当然,您可以使用PKCS1-PEM-key,但这并不容易。以下是一些选项:

可能性1:

如果您使用PKCS1Core3.0,则有一个用于读取.NET密钥的direct support (另请参阅here):

代码语言:javascript
复制
byte[] privateKeyPkcs1PEM = File.ReadAllBytes(@"C:\tmp\private.key"); // PKCS1 - PEM
byte[] privateKeyPkcs1DER = ConvertPKCS1PemToDer(Encoding.UTF8.GetString(privateKeyPkcs1PEM));
RSA rsa = RSA.Create();
rsa.ImportRSAPrivateKey(privateKeyPkcs1DER, out _);

// use e.g. rsa.Decrypt(...)

但是,ImportRSAPrivateKey-method只能处理DER格式,这本质上是PEM格式的二进制格式(有关更多详细信息,请参阅herehere)。因此,必须将PEM格式转换为DER格式,如下所示

代码语言:javascript
复制
private static byte[] ConvertPKCS1PemToDer(string pemContents)
{
    return Convert.FromBase64String(pemContents
        .TrimStart("-----BEGIN RSA PRIVATE KEY-----".ToCharArray())
        .TrimEnd("-----END RSA PRIVATE KEY-----".ToCharArray())
        .Replace("\r\n",""));
}

或者,也可以将OpenSSL用于conversion

代码语言:javascript
复制
openssl rsa -inform PEM -outform DER -in C:\tmp\private.key -out C:\tmp\private.der

可能性2:

您可以使用OpenSSL将PKCS1-PEM-key转换为PKCS8-DER-key。相应的command为:

代码语言:javascript
复制
openssl pkcs8 -topk8 -inform pem -in C:\tmp\private.key -outform der -nocrypt -out C:\tmp\privatepkcs8.der

here解释了pkcs1格式和pkcs8格式之间的差异。然后,您可以使用内置的.NET方法导入密钥(另请参阅here,PKCS#8 PrivateKeyInfo一节):

代码语言:javascript
复制
byte[] privateKeyPkcs8DER = File.ReadAllBytes(@"C:\tmp\privatepkcs8.der"); // PKCS8 - DER
CngKey cngKey = CngKey.Import(privateKeyPkcs8DER, CngKeyBlobFormat.Pkcs8PrivateBlob);
RSA rsa = new RSACng(cngKey);

// use e.g. rsa.Decrypt(...)

可能性3:

如果可以使用第三方库,BouncyCastle也是一种可能:

代码语言:javascript
复制
StreamReader reader = File.OpenText(@"C:\tmp\private.key"); // PKCS1 - PEM
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
Pkcs1Encoding pkcs1Encoding = new Pkcs1Encoding(new RsaEngine());

// E.g. decryption
pkcs1Encoding.Init(false, keyPair.Private);
byte[] decrypted = pkcs1Encoding.ProcessBlock(encrypted, 0, encrypted.Length);

可能性4:

另一种可能性是使用来自JavaScienceDecodeRSAPrivateKey-method,其可以处理PKCS1密钥。但是,DecodeRSAPrivateKey-method只能处理DER格式。因此,您必须首先使用ConvertPKCS1PemToDer或OpenSSL将PEM格式手动转换为DER格式。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56373628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档