C# .NET Framework 读取 PKCS8 RSA 私钥的三种方法(RSACryptoServiceProvider)
都需要nuget引用:BouncyCastle.Crypto 库。
方法1:
pkcs8 文本先转为 .NET XML 私钥字符串
(这个方法,是网上搜索出来最多的方案;但有少量的PKCS8 RSA私钥无法解析,privateKeyXml 虽然转出来了,但FromXmlString 报错,估计是RSAPrivateKeyJava2DotNet转的效果不如 DotNetUtilities.ToRSAParameters)
/// <summary> /// PKCS8 文本转RSACryptoServiceProvider 对象 /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKeyPKCS8(string privateKeyPemPkcs8) { try { //PKCS8是“BEGIN PRIVATE KEY” privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); //RSAPrivateKeyJava2DotNet 不能是完整格式的 PKCS8 私钥字符串。 //pkcs8 文本先转为 .NET XML 私钥字符串 string privateKeyXml = RSAPrivateKeyJava2DotNet(privateKeyPemPkcs8); RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider(); publicRsa.FromXmlString(privateKeyXml); return publicRsa; } catch (Exception ex) { throw ex; } } /// <summary> /// PKCS8 私钥文本 转 .NET XML 私钥文本 /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static string RSAPrivateKeyJava2DotNet(string privateKeyPemPkcs8) { RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyPemPkcs8)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); }
方法2:
使用:PemReader + DotNetUtilities.ToRSAParameters
/// <summary> /// 把PKCS8私钥转成RSA私钥对象的。(方式二,使用:PemReader + DotNetUtilities.ToRSAParameters) /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKeyPKCS8Way2(string privateKeyPemPkcs8) { try { //PKCS8是“BEGIN PRIVATE KEY” //使用PemReader,需要完整的 PKCS8 格式字符串(包含BEGIN PRIVATE KEY)。否则读取出来是null。 privateKeyPemPkcs8 = StrToFullPrivateKeyPKCS8(privateKeyPemPkcs8); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); // 使用 BouncyCastle 读取 PEM 文件 using (var reader = new StringReader(privateKeyPemPkcs8)) { var pemReader = new PemReader(reader); object pemObject = pemReader.ReadObject(); var keyPair = (RsaPrivateCrtKeyParameters)pemObject; var rsaParameters = DotNetUtilities.ToRSAParameters(keyPair); rsa.ImportParameters(rsaParameters); } return rsa; } catch (Exception ex) { throw ex; } } /// <summary> /// PKCS8 私钥字符串转换为完整的 PKCS8 格式字符串(包含BEGIN PRIVATE KEY) /// </summary> /// <param name="keyStr"></param> /// <returns></returns> public static string StrToFullPrivateKeyPKCS8(string keyStr) { //去除意外字符 keyStr = keyStr.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); //完整 string rn = "\n"; StringBuilder sbKey = new StringBuilder(keyStr); int nKeyLen = sbKey.Length; //sbKey为base64编码的公钥字符串 for (int i = 64; i < nKeyLen; i += 64) { sbKey.Insert(i, rn); i++; } sbKey.Insert(0, "-----BEGIN PRIVATE KEY-----" + rn); sbKey.Append(rn + "-----END PRIVATE KEY-----" + rn); string all_key_str = sbKey.ToString(); return all_key_str; }
PemReader命名空间是:Org.BouncyCastle.OpenSsl。
方式3:
使用:PrivateKeyFactory.CreateKey + DotNetUtilities.ToRSAParameters
/// <summary> /// (方式3,使用:PrivateKeyFactory.CreateKey + DotNetUtilities.ToRSAParameters) /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKeyPKCS8Way3(string privateKeyPemPkcs8) { try { //PrivateKeyFactory.CreateKey()参数只能是纯字符串 privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyPemPkcs8)); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); var rsaParameters = DotNetUtilities.ToRSAParameters(privateKeyParam); rsa.ImportParameters(rsaParameters); return rsa; } catch (Exception ex) { throw ex; } }
--