runliuv

runliuv@cnblogs

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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;
    }
}

 

--

posted on 2025-05-30 11:23  runliuv  阅读(161)  评论(0)    收藏  举报