.NET Core 3.1 - RSA.ImportRSAPrivateKey 引发 CryptographicException

.NET Core 3.1 - RSA.ImportRSAPrivateKey raises a CryptographicException

我正在接受 RSA 非对称加密培训。我用 ssh-keygen 创建了一个密钥对,并设法用我的 public 密钥加密了一些数据。 但是当我尝试用我的私钥解密这些数据时,出现了这个异常:

System.Security.Cryptography.CryptographicException : 'ASN1 corrupted data.'

这是包含私钥的 PEM 文件:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,E79376C1ECFD82F05A871D9245BFC958

iEL9aNdWIC3TckveRH2ADdHrnCAQeyg0GUFx0obx1sHOCDdiCIb2u46vFUQ8QP6H
vHHgA9Kf4lY8Jq6Qkv/Iyhh9WcWTR2nNjbN7Ndlb343MyjeNdlXdVrHsfR8Q98ul
06FiKZdnS640PzxAUvibbmkLVus8g3V14qZqeDTqN1rbOCAk2Kxfy5V4kd6M7wCm
fqABkYpp+2EYf4Z4YcJbLDXEEIg7HD/AI1gPpE5nRQoSib/9bm87j98VnG5dOYAJ
38ZMTvJjIImQveOUeSNyR/re71V+YUy0N/zvqMrlp4pDFsDb6infZga0jPFzGXGy
5S3XYXSs9iPReFHQnhWr/L3dRx9TpfZJcl4BJ6D8j9wxrWRcharGNNgCK/kV9FJw
BpwFu01jNESDHV3dyWTcOAzQit4pDkr0A9EK4N1vfWaLLO8vqyGtqlvtU5sD2rYQ
JvrMEsUsAYXJcBDUX2cksNEen+7s338cBGg4NdE+xAUeKv5EysYIKgojPJi6WQ39
FAgkr1TfWaffO/TgfL/DwC1wyHXleNyDQ87unyxRIRu/wWnqJaQQG8Z0BilIbDp8
KrKfkHW9CWaPCbldOzHJ5UDZmA5+AvfoaATRw/vW1Wg0GYkuNqqHzV7tNFKcnUG1
DmIaSI+Y55cngqeOStFfgRTehbXK84w3PzR3lnpuxG4rtOjDV8RfZSozaSValqju
ZWRYEbKn7Za2XZWJT4kkDa5O4nJUMbihBOUL+FWc6dmDIaZY/nUKJAm2pxmd0R1s
9PcXhqLEnBTvGh1CrOdhiqkHQ5A5OtIp/FrPhUltjsy129NC5/dPZaN9v4TgNYQu
zNd8vSlVXuimB+2OoXu3fNE75ywxmrs4H8M4y3u87GQWFdYwQFFnv2fyCzV8iqvy
ybQR599v5qL2IKvHdw68q9PDmasd4jSTAoFP/g6QQKMCaQuMUbrtlHzvPvNnCgk1
AChbFeuLK57c2rwVwTx0YEATcKz27/V5af0E2x6sLDoqQv5SBkREuuWyA6DsSO/S
vX1WR/hZWk2PVi24N/AG8T/sIfyBeTPw7Yx3RuT5MWLdR6haSEKkGGrGuxr1HnoF
lt3JruZczavGpAn5Q8DSVKb78Q8kqI/gdLYNIuq5Yy7Mz1ldocN0N2CarUGWgU7e
+z0TM2CWkTBE7Q0CU4Na5QusvaLYDgH4LW4WY9BNN86C4uKQFjJHz6gZoI3zx8/L
RxN2bGyd0H83k4xuQXml2RnnPPB6L5JwJxxme5ecWpMdp5c6xyXX1ZPKkkGuRbFs
OxeQqNNfPEExqtC2U/Jn5B1HYJqCYCeKlUNdqUoZv5vT8x9UDoE5vKtP3DtTckeB
+6n7S2viNWzV2qid8moh9DfWGMlF4i1y91pdcNJx+M01OfLOB1EPlD0MoTvkfU6s
x0VQh5t4wCbcJ7kcIrp2siPbBg4RPV8MNKtaBhTvFf+nH1TAEsUMjdi7FrnfBn3b
4o4BqC+ibQHC/+SkGAxRakdJjM5XcXO1BZp4zLYSBQyXGu7kp8ohOvHx65vtwvls
XCdbtnJs/iAORxAgLnuVPzLUfTd6bLlszOsyIvC8+j587GX5YFW+h4s+bicZMwCm
-----END RSA PRIVATE KEY-----

这里是使用这个私钥的代码示例:

static string RSA_Decrypt(byte[] value)
{
    byte[] deciphered;

    using (var reader = File.OpenText(@"C:\Users\???\.ssh\id_rsa"))
    {
        // Extracting the payload
        string privateKeyFile = reader.ReadToEnd();
        var exp = privateKeyFile.Split("\n\n");
        var privateKey = exp[1].Split("\n-----")[0];

        // using the payload to decrypt my data
        using(var rsa = RSA.Create())
        {
            rsa.ImportRSAPrivateKey(Convert.FromBase64String(privateKey), out _); //CryptographicException

            deciphered = rsa.Decrypt(value, RSAEncryptionPadding.Pkcs1);
        }
    }

    return Encoding.Default.GetString(deciphered);
}

我做错了什么?

发布的私钥是经过加密的 PEM 编码 PKCS#1 密钥。

RSA.ImportRSAPrivateKey() 只能导入这种格式的未加密密钥,而且是 DER 编码的。 DER 编码是 PEM 编码的结果,通过删除页眉和页脚以及对其余部分进行 Base64 解码。

据我所知,无法使用 .NET Core 3.1 板载方式导入加密的 PKCS#1 密钥。但是可以使用 BouncyCastle and its Org.BouncyCastle.OpenSsl.PemReader class, see e.g. .

进行导入

与 PKCS#1 格式不同,PKCS#8 格式的 DER 编码私钥可以使用开箱即用的 .NET Core 3.1 导入 (RSA.ImportPkcs8PrivateKey()), even if it is encrypted (RSA.ImportEncryptedPkcs8PrivateKey())。
可以生成这种格式的密钥,例如openssl genpkey。使用 OpenSSL 也可以在格式之间进行转换。

感谢 Topaco,这正是我所需要的!我使用 BouncyCastle 来解密我的私钥,现在它运行完美!我不知道为什么 RSA class 没有任何方法可以做到...

现在这是我的代码:

static string RSA_Decrypt(byte[] value)
{
    string deciphered;

    using (var reader = File.OpenText(@"C:\Users\???\.ssh\id_rsa"))
    {
        string privateKeyFile = reader.ReadToEnd();
        var keyReader = new StringReader(privateKeyFile);

        var decryptEngine = new Pkcs1Encoding(new RsaEngine());

        object pemReader = new PemReader(keyReader, new PasswordFinder("azerty")).ReadObject();
        var keyPair = (AsymmetricCipherKeyPair)pemReader;
        decryptEngine.Init(false, keyPair.Private);

        deciphered = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(value, 0, value.Length));
    }

    return deciphered;
}

PS : 是的,我的私钥密码是“azerty”^^ 我创建密钥对时没有受到启发^^