• C# .NET CORE .NET6 RSA 公钥加密 私钥解密


    环境说明:

    .NET CORE 版本:.NET 6 。

     

    .NET CORE 对于RSA的支持:

    1. .NET 6 中内置了对 PKCS1,PKCS8 2种私钥格式的支持。

    2. 如果你要部署在Linux,docker ,k8s 中;一定要用 “RSA”这个类,不能是 .NET FRAMEWORK 的 RSACryptoServiceProvider。

    3. .NET 中默认加密算法为“RSA/ECB/PKCS1Padding” ,要和JAVA互通,JAVA 那边也得是 RSA/ECB/PKCS1Padding 。

     

    加密解析:

    //假设私钥长度为1024, 1024/8-11=117。
    //如果明文的长度小于117,直接全加密,然后转base64。(data.Length <= maxBlockSize)
    //如果明文长度大于117,则每117分一段加密,写入到另一个Stream中,最后转base64。while (blockSize > 0)

     

    如果要和其它语言互通,这个分段长度需要和其它语言约定好,不一是 私钥长度/8-11。

     

    解密解析:

    //假设私钥长度为1024, 1024/8 =128。
    //如果明文的长度小于 128,直接全解密。(data.Length <= maxBlockSize)
    //如果明文长度大于 128,则每 128 分一段解密,写入到另一个Stream中,最后 GetString。while (blockSize > 0)

     

    用“支付宝开放平台开发助手”生成一组公私钥:

    PKCS8私钥:

    MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMz0Czg6QUtTISa2pUkloeQB/TEpHdqrfyroWpKLW9B/LWFSOGH9nyTk1pPZaeadyEZQ6gay/C0pUAetLraq9bMA/Luxq68b87uG7WX7dKytEO2/87qGpGMRs97H+GlkzWil2QO2KK4cHnAcVicPsmi5aZ72U0BWJFyPhtd+qdmrAgMBAAECgYEAvW67iAbgHt0BASVD9C3iSjpEaVHVlC165o/IVzaTcEx8Bz3Ve0zN8W3JnvIO3ebsG4HiLLr2Nk++9rltOc0eNeGMv7F1e/OFot1wN0ON6s1g4bYh1z5Uz8FcYiMWcqHHICrx+oSFeK9x+I2Zge7enQXcsVnqEhm77ZE5YczSryECQQD9nB58e5efYchF+cYbmURioX18cUMuhQbB9Aq2N55cd689Lg35KZqT8JQTp/8tQSdCJG8d2nU8VKspUKTEAuaDAkEAzuKIIoc9PVJvy90LhIPA9c1S8BPCI7EMCaTZqJ5o3VaR2dqvUZDGX7kL3kYkQ+n7mq3KIECvkEFzA+FOP96XuQJBAJQTKHW0T/YeSKoayUHp/lS8R6F2HCy4PRbXn71+wfbpZqcJEd2OHhQM3tiPOV258esbjMlYeSUNppZL4LgVnXMCQQC7Lvs9Ql+GPDAqo7ToEM1lmICR906QPIBHuX+1sJ3wpYMROWumwPa7ZRH36j6ls+6R5OwcgmpWeuE1gYTrBNsBAkEAn2pEtAljX1foQff6CLozYg/J6J9RmVFcJ6qz0LX3052qNFBQYw8CMHB7VkVNzsDIDC8LX5uP2pzTrdPLew+pPA==

    与之匹配的 PKCS1 私钥,用助手转换的:

    MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw=

    与之匹配的公钥:

    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB

     

    加密工具类:

    RsaEncryptUtil

    复制代码
    using System.Security.Cryptography;
    using System.Text;
    
    namespace CommonUtils
    {
        public static class RsaEncryptUtil
        {
            #region 标准的-公钥加密-私钥解密
    
            /** 默认编码字符集 */
            private static string DEFAULT_CHARSET = "UTF-8";
    
            /// 
            /// 公钥加密(超过 私钥长度 / 8 - 11,分段加密)
            /// 
            /// 明文
            /// 编码
            /// 公钥
            /// 
            /// 
            public static string RSAEncrypt(string content, string charset, string publicKeyPem)
            {
                try
                {
                    //假设私钥长度为1024, 1024/8-11=117。
                    //如果明文的长度小于117,直接全加密,然后转base64。(data.Length <= maxBlockSize)
                    //如果明文长度大于117,则每117分一段加密,写入到另一个Stream中,最后转base64。while (blockSize > 0)                 
    
                    //转为纯字符串,不带格式
                    publicKeyPem = publicKeyPem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
    
                    RSA rsa = RSA.Create();
                    rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(publicKeyPem), out _);
    
                    if (string.IsNullOrEmpty(charset))
                    {
                        charset = DEFAULT_CHARSET;
                    }
                    byte[] data = Encoding.GetEncoding(charset).GetBytes(content);
                    int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
                    if (data.Length <= maxBlockSize)
                    {
                        byte[] cipherbytes = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
                        return Convert.ToBase64String(cipherbytes);
                    }
                    MemoryStream plaiStream = new MemoryStream(data);
                    MemoryStream crypStream = new MemoryStream();
                    byte[] buffer = new byte[maxBlockSize];
                    int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
                    while (blockSize > 0)
                    {
                        byte[] toEncrypt = new byte[blockSize];
                        Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
                        byte[] cryptograph = rsa.Encrypt(toEncrypt, RSAEncryptionPadding.Pkcs1);
                        crypStream.Write(cryptograph, 0, cryptograph.Length);
                        blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
                    }
    
                    return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
                }
                catch (Exception ex)
                {
                    throw new Exception("EncryptContent = " + content + ",charset = " + charset, ex);
                }
            }
    
            /// 
            /// 私钥解密(超过 私钥长度 / 8 - 11,分段加密)
            /// 
            /// 密文
            /// 编码
            /// 私钥
            /// 私钥格式 PKCS1,PKCS8
            /// 
            /// 
            public static string RSADecrypt(string content, string charset, string privateKeyPem, string keyFormat)
            {
                try
                {
                    //假设私钥长度为1024, 1024/8 =128。
                    //如果明文的长度小于 128,直接全解密。(data.Length <= maxBlockSize)
                    //如果明文长度大于 128,则每 128 分一段解密,写入到另一个Stream中,最后 GetString。while (blockSize > 0)                                 
    
                    //转为纯字符串,不带格式
                    privateKeyPem = privateKeyPem.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
                    privateKeyPem = privateKeyPem.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim();
    
    
                    RSA rsaCsp = RSA.Create();
                    if (keyFormat == "PKCS8")
                        rsaCsp.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKeyPem), out _);
                    else if (keyFormat == "PKCS1")
                        rsaCsp.ImportRSAPrivateKey(Convert.FromBase64String(privateKeyPem), out _);
                    else
                        throw new Exception("只支持PKCS8,PKCS1");
    
                    if (string.IsNullOrEmpty(charset))
                    {
                        charset = DEFAULT_CHARSET;
                    }
                    byte[] data = Convert.FromBase64String(content);
                    int maxBlockSize = rsaCsp.KeySize / 8; //解密块最大长度限制
                    if (data.Length <= maxBlockSize)
                    {
                        byte[] cipherbytes = rsaCsp.Decrypt(data, RSAEncryptionPadding.Pkcs1);
                        return Encoding.GetEncoding(charset).GetString(cipherbytes);
                    }
                    MemoryStream crypStream = new MemoryStream(data);
                    MemoryStream plaiStream = new MemoryStream();
                    byte[] buffer = new byte[maxBlockSize];
                    int blockSize = crypStream.Read(buffer, 0, maxBlockSize);
                    while (blockSize > 0)
                    {
                        byte[] toDecrypt = new byte[blockSize];
                        Array.Copy(buffer, 0, toDecrypt, 0, blockSize);
                        byte[] cryptograph = rsaCsp.Decrypt(toDecrypt, RSAEncryptionPadding.Pkcs1);
                        plaiStream.Write(cryptograph, 0, cryptograph.Length);
                        blockSize = crypStream.Read(buffer, 0, maxBlockSize);
                    }
    
                    return Encoding.GetEncoding(charset).GetString(plaiStream.ToArray());
                }
                catch (Exception ex)
                {
                    throw new Exception("DecryptContent = " + content + ",charset = " + charset, ex);
                }
            }
    
            #endregion
    
        }
    }
    复制代码

    调用代码:

     

    复制代码
    // See https://aka.ms/new-console-template for more information
    
    
    using CommonUtils;
    
    try
    {
        //PKCS8格式私钥
        string strPriPkcs8 = "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMz0Czg6QUtTISa2pUkloeQB/TEpHdqrfyroWpKLW9B/LWFSOGH9nyTk1pPZaeadyEZQ6gay/C0pUAetLraq9bMA/Luxq68b87uG7WX7dKytEO2/87qGpGMRs97H+GlkzWil2QO2KK4cHnAcVicPsmi5aZ72U0BWJFyPhtd+qdmrAgMBAAECgYEAvW67iAbgHt0BASVD9C3iSjpEaVHVlC165o/IVzaTcEx8Bz3Ve0zN8W3JnvIO3ebsG4HiLLr2Nk++9rltOc0eNeGMv7F1e/OFot1wN0ON6s1g4bYh1z5Uz8FcYiMWcqHHICrx+oSFeK9x+I2Zge7enQXcsVnqEhm77ZE5YczSryECQQD9nB58e5efYchF+cYbmURioX18cUMuhQbB9Aq2N55cd689Lg35KZqT8JQTp/8tQSdCJG8d2nU8VKspUKTEAuaDAkEAzuKIIoc9PVJvy90LhIPA9c1S8BPCI7EMCaTZqJ5o3VaR2dqvUZDGX7kL3kYkQ+n7mq3KIECvkEFzA+FOP96XuQJBAJQTKHW0T/YeSKoayUHp/lS8R6F2HCy4PRbXn71+wfbpZqcJEd2OHhQM3tiPOV258esbjMlYeSUNppZL4LgVnXMCQQC7Lvs9Ql+GPDAqo7ToEM1lmICR906QPIBHuX+1sJ3wpYMROWumwPa7ZRH36j6ls+6R5OwcgmpWeuE1gYTrBNsBAkEAn2pEtAljX1foQff6CLozYg/J6J9RmVFcJ6qz0LX3052qNFBQYw8CMHB7VkVNzsDIDC8LX5uP2pzTrdPLew+pPA==";
        //PKCS1格式私钥
        string strPriPkcs1 = "MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw=";
        //公钥
        string strPub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB";
    
        string strDJM = "泰酷拉!123ABC";//待加密字符串
        strDJM = "泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC泰酷拉!123ABC";//待加密字符串,超过117字符的测试
    
        Console.WriteLine("待加密字符串:" + strDJM);
        string charSet = "UTF-8";
        string strJMH = RsaEncryptUtil.RSAEncrypt(strDJM, charSet, strPub);//密文
        Console.WriteLine("密文:" + strJMH);
    
        string strDecryptedByPkcs8 = RsaEncryptUtil.RSADecrypt(strJMH, charSet, strPriPkcs8, "PKCS8");//使用PKCS8格式私钥解密
        Console.WriteLine("PKCS8 解密后:" + strDecryptedByPkcs8);
    
        string strDecryptedByPkcs1 = RsaEncryptUtil.RSADecrypt(strJMH, charSet, strPriPkcs1, "PKCS1");//使用PKCS1格式私钥解密
    
        Console.WriteLine("PKCS1 解密后:" + strDecryptedByPkcs1);
    
    }
    catch (Exception ex)
    {
    
        Console.WriteLine("ex:" + ex.Message);
    }
    
    Console.WriteLine("Hello, World!");
    Console.ReadKey();
    复制代码

     

     

    -

     

  • 相关阅读:
    2. Java 对象和类
    sublimeAstyle针对C++20三路运算符的格式化调整
    HDFS机架感知配置(block放置策略/NodeGroup分配策略配置)
    善网ESG周报(第三期)
    【基于Arduino的垃圾分类装置开发教程四超声波检测】
    Fiddler配置及使用
    Spring Boot Starter必知必会(Spring Boot Starter简介及定义方法分享)
    隐私计算基础组件系列-混淆电路
    内网渗透-Windows内网渗透
    tauri vue vite elemrntui
  • 原文地址:https://www.cnblogs.com/runliuv/p/17467994.html