首页 > 编程语言 >C# .NET CORE .NET6 RSA 公钥加密 私钥解密

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

时间:2023-06-08 23:44:56浏览次数:34  
标签:CORE 公钥 私钥 string C# ----- 123ABC 加密 泰酷

环境说明:

.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";

        /// <summary>
        /// 公钥加密(超过 私钥长度 / 8 - 11,分段加密)
        /// </summary>
        /// <param name="content">明文</param>
        /// <param name="charset">编码</param>
        /// <param name="publicKeyPem">公钥</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        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);
            }
        }

        /// <summary>
        /// 私钥解密(超过 私钥长度 / 8 - 11,分段加密)
        /// </summary>
        /// <param name="content">密文</param>
        /// <param name="charset">编码</param>
        /// <param name="privateKeyPem">私钥</param>
        /// <param name="keyFormat">私钥格式 PKCS1,PKCS8</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        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();

 

-

 

标签:CORE,公钥,私钥,string,C#,-----,123ABC,加密,泰酷
From: https://www.cnblogs.com/runliuv/p/17467994.html

相关文章

  • C++面试八股文:C++中指针、引用、解引用和取地址有什么不同?
    C++面试八股文:C++中指针、引用、解引用和取地址有什么不同?某日小二参加XXX科技公司的C++工程师开发岗位2面:面试官:指针、引用、解引用和取地址是C++中的重要概念,请问它们在语法和语义上有所不同?小二:指针是一个变量,它存储了一个内存地址。小二:引用是一个别名,它允许使用一个......
  • demosaicnet-master的包代码阅读笔记
    init.py我在学init用法时候的笔记该文件里面都是导入模块,其中从dataset.py是导入所有模块,因为模糊导入的__all__没有定义。from.modulesimportBayerDemosaickfrom.modulesimportXTransDemosaickfrom.mosaicimportxtransfrom.mosaicimportbayerfrom.mosaicim......
  • 51存储器块清零和二进制数转换成二十进制(BCD)码
    一、实验目的1、了解单片机实验开发板电路原理图2、掌握KEIL软件开发单片机C51程序的流程3、掌握单片机开发程序的烧录方法和流程二、实验内容1、完成单片机开发相关必备软件的安装2、学习单片机开发板套件的实验原理图3、编写、下载及实现第一个单片机程序(点亮一个LED灯)三......
  • C语言 #pragma指令
    简介#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的#pragma用于指示编译器完成一些特定的动作#pragma所定义的很多指示字是编译器特有的#pr......
  • C++面试八股文:C++中,设计一个类要注意哪些东西?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第9面:面试官:C++中,设计一个类要注意哪些东西?二师兄:设计一个类主要考虑以下几个方面:1.面向对象的封装、继承及多态。2.bigthree或者bigfive。3.运算符和函数重载、静态成员、友元、异常处理等相关问题。面试官:请介绍一下面向对象......
  • 【LeetCode滑动窗口专题#2】无重复字符的最长子串
    #1传送门滑动窗口最大值长度最小的子数组无重复字符的最长子串给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。示例1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:s="bbbbb"输出:1解释:......
  • 用Spring Cloud Alibaba构建用户中心!只要5分钟
    你好,我是田哥。前几天,有几位朋友私信我,叫我写一个使用SpringCloudAlibaba搭建项目。今天,我给安排上,使用SpringCloudAlibaba搭建一个用户中心。下面,我就来给大家说一下,我饿还是如何搭建的,具体步骤如下:使用IDEA创建项目结构添加maven相关依赖安装Nacos业务代码整个技术栈:Spring......
  • 7.1 套接字(socket)
    套接字(socket)是计算机之间进行通信的一种技术,它允许不同主机上的进程之间进行数据交换。在Python中,我们可以使用socket模块来创建和使用套接字。首先,我们需要导入socket模块:importsocket在网络编程中,有两种主要类型的套接字:流套接字(StreamSockets)和数据报套接字(DatagramSoc......
  • win10 vs2022 搭建 cocos2d-x 3.17 开发环境
    引擎下载地址https://cocos2d-x.org/download/也可以在github下载https://github.com/cocos2d/cocos2d-x/tags手册地址https://docs.cocos2d-x.org/cocos2d-x/v3/zh/api文档地址https://docs.cocos2d-x.org/api-ref/cplusplus/v3x/index.htmlhelloworld安装注意事项......
  • C# 实现保留两位小数的方法
    1、Math.Round(0.333333,2);//按照四舍五入的国际标准2、   doubledbdata=0.335333;   stringstr1=String.Format("{0:F}",dbdata);//默认为保留两位3、   floati=0.333333;   intj=(int)(i*100);   i=j/100;4、   decimal.Round(decimal.Parse("0......