

C# .NET CORE .NET6 RSA 公钥加密 私钥解密 - runliuv
source link: https://www.cnblogs.com/runliuv/p/17467994.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

runliuvrunliuv@cnblogs |
环境说明:
.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();
Recommend
-
105
最近一段时间,国内各大网站纷纷用上了https连接,在访问这些网站的时候,很多浏览器会给予“特别关照”,给它们的链接旁边加上一个绿色的小锁,那么,什么是https,它与网络安全又有什么关系呢?今天我们就来谈谈https与tls(传输层安全)。
-
77
程序员 - @GuguguguDa - 下面这个博客看的我很疑惑啊先不论私钥加密,公钥解密有没有意义私钥加密的结果,用公钥解密,还能解出来的吗?我试了下,居然还真可以?https://blog.csdn.net/
-
25
以太坊geth 公私钥地址签名转换基础 以太坊中使用的椭圆曲线是S256,私钥和HASH都为32位,公钥为65位其中第一位是压缩字节0x04,压缩公钥为33字节,地址是是公钥的后64位hash后取后20个字节作为地址。签名数据为65位,R,S...
-
7
零一间2021.04.20 01:16:38字数 1,347阅读 29理解公钥与私钥 一、公钥算法与私钥算法 1、私钥算法 ...
-
28
web3js里有直接从私钥获取公钥的接口吗 是这个web3.shh.getPublicKey吗,我调用直接报错没有这类方法 ...
-
14
V2EX › Python 今天碰到一个对接 Java rsa pkcs1 用公钥解密, chenqh · 1 天前 · 1000...
-
6
在以太坊中,账户、地址、私钥(Private Key)和公钥(Public Key)是非常重要的概念。账户扮演着以太坊的中心角色,地址是我们与以太坊系统进行交互的标识,它是以太坊账户与外界进行交互的名字,而私钥与公钥是保护我们账户安全的重要屏障。 什么是...
-
8
March 22, 2021 一般来说,加密主要用于消息的传递,并且传递的消息只有持有私钥的那个人能解密。因此, 像 RSA 这种非对称密钥加密算法的常用场景是:对于加密,公钥加密,私钥解密。为什么不是 私钥加密...
-
3
使用 java 提取 jks 文件中的公钥和私钥 Full's Blog
-
6
jdk 中的 keytool 的使用,以及提取 jks 文件中的公钥和私钥 Full's Blog
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK