如何在C#中解密PKCS#1格式的加密RSA私钥?
在C#中解密PKCS#1格式的加密RSA私钥
由于.NET原生API对加密的PKCS#1格式私钥支持有限,最简便的方式是使用BouncyCastle第三方库来实现,以下是具体步骤:
步骤1:安装BouncyCastle NuGet包
在项目中安装BouncyCastle的.NET包,可通过NuGet包管理器搜索BouncyCastle,或使用命令行:
Install-Package BouncyCastle
步骤2:编写解密代码
通过BouncyCastle的PemReader读取加密的私钥字符串,传入密码短语完成解密:
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; using System.IO; public static class RsaKeyHelper { // 解密PKCS#1加密私钥,返回BouncyCastle的密钥参数 public static AsymmetricKeyParameter DecryptEncryptedPkcs1Key(string encryptedKeyStr, string passphrase) { using var stringReader = new StringReader(encryptedKeyStr); // 传入密码查找器 var pemReader = new PemReader(stringReader, new PassphraseFinder(passphrase)); return (AsymmetricKeyParameter)pemReader.ReadObject(); } // 辅助类:提供密码短语给PemReader private class PassphraseFinder : IPasswordFinder { private readonly string _passphrase; public PassphraseFinder(string passphrase) => _passphrase = passphrase; public char[] GetPassword() => _passphrase.ToCharArray(); } // 可选:转换为.NET原生RSA对象,方便后续操作 public static RSA ConvertToDotNetRsa(AsymmetricKeyParameter bcKey) { var rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)bcKey); var rsa = RSA.Create(); rsa.ImportParameters(rsaParams); return rsa; } }
调用示例
// 你的加密私钥字符串(注意实际私钥包含Base64密文,示例仅为头信息) string encryptedPrivateKey = @"-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,10B1961116EC503A [这里是实际的Base64加密私钥内容] -----END RSA PRIVATE KEY-----"; string passphrase = "你的密码短语"; // 解密并转换为.NET原生RSA对象 var bcKey = RsaKeyHelper.DecryptEncryptedPkcs1Key(encryptedPrivateKey, passphrase); using var rsa = RsaKeyHelper.ConvertToDotNetRsa(bcKey); // 后续可使用rsa对象进行解密、签名等操作
替代方案:不使用第三方库(复杂)
如果不想依赖第三方库,需要手动实现OpenSSL的密钥派生逻辑(EVP_BytesToKey)和ASN.1解析,步骤如下:
- 解析PEM内容,提取DEK-Info中的加密算法(如
DES-EDE3-CBC)和IV(如10B1961116EC503A转字节数组) - 用
EVP_BytesToKey从密码短语派生加密密钥 - 使用对应对称算法解密私钥密文
- 解析解密后的ASN.1数据得到RSA参数
以下是EVP_BytesToKey的简化实现(MD5版本,OpenSSL默认):
private static byte[] EvpBytesToKey(string password, byte[] salt, int keySizeBytes, int ivSizeBytes) { var passwordBytes = System.Text.Encoding.UTF8.GetBytes(password); var keyMaterial = new List<byte>(); byte[] currentHash = null; while (keyMaterial.Count < keySizeBytes + ivSizeBytes) { var hashInput = new List<byte>(); if (currentHash != null) hashInput.AddRange(currentHash); hashInput.AddRange(passwordBytes); if (salt != null) hashInput.AddRange(salt); currentHash = System.Security.Cryptography.MD5.HashData(hashInput.ToArray()); keyMaterial.AddRange(currentHash); } return keyMaterial.Take(keySizeBytes + ivSizeBytes).ToArray(); }
后续的解密和ASN.1解析需要手动处理,容易出错,因此仅推荐在无法使用第三方库的场景下尝试。
内容的提问来源于stack exchange,提问作者user1514910
相关产品推荐
相关产品推荐

