RSA加密及其在C#中的使用

5 篇文章 0 订阅

RSA算法简介

笔者使用场景

Java作为服务端生成一对公私钥,C#作为客户端拥有公钥。
C#使用公钥对上行byte[]类型数据进行加密,服务端Java使用私钥解密。

规范

  • 公私钥都是base64字符串

过程

1,Java服务端开发人员给到客户端这边公、私钥(之所以给了私钥是方便客户端这边自己来测试)

2,C#客户端这边发现Java给到的公私钥,客户端这边并不能直接用。C#支持的公私钥格式有点类似XML格式。

比如Java公钥,其在C#中对应的格式如下:

    public string java_publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv2NbWPuQwPegAcydw3+xO3GOCKMMyUme9bUuEEmds4CogvasV1f2savwiXA5mKqawoxDjbsjUgdgPHQbmlrhpNBBMa83Us9w5xjgl5tZFyDusnO/r8IQa9pGW7NAJ6xJX5vYbv4rZWon1D8/N7l/ybsR6nZTt+rEcL1V78POXIwIDAQAB";

    public string csharp_publicKey = "<RSAKeyValue><Modulus>r9jW1j7kMD3oAHMncN/sTtxjgijDMlJnvW1LhBJnbOAqIL2rFdX9rGr8IlwOZiqmsKMQ427I1IHYDx0G5pa4aTQQTGvN1LPcOcY4JebWRcg7rJzv6/CEGvaRluzQCesSV+b2G7+K2VqJ9Q/Pze5f8m7Eep2U7fqxHC9Ve/DzlyM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

可见二者不仅仅是加了几个XML标签那么简单,内容也发生了变化,因此需要提供工具把Java公钥转换为C#支持的格式。

3,C#控制台应用实现把Java公私钥转换为C#支持的格式
笔者使用BouncyCastle.Cryptography库,可以使用NuGet安装。实现了C#和Java的公私钥格式互转。
核心代码

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using System;
using System.Xml;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Pkcs;

namespace RSA_Java2CSharp
{
    /// <summary>  
    /// RSA密钥格式转换  
    /// </summary>  
    public class RSAKeyConvert
    {
        /// <summary>  
        /// RSA私钥格式转换,java->.net  
        /// </summary>  
        /// <param name="privateKey">java生成的RSA私钥</param>  
        /// <returns></returns>  
        public static string RSAPrivateKeyJava2DotNet(string privateKey)
        {
            var data = Convert.FromBase64String(privateKey);
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));

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

        /// <summary>  
        /// RSA私钥格式转换,.net->java  
        /// </summary>  
        /// <param name="privateKey">.net生成的私钥</param>  
        /// <returns></returns>  
        public static string RSAPrivateKeyDotNet2Java(string privateKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(privateKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
            BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
            BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
            BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
            BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));

            RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);

            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
            byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
            return Convert.ToBase64String(serializedPrivateBytes);
        }

        /// <summary>  
        /// RSA公钥格式转换,java->.net  
        /// </summary>  
        /// <param name="publicKey">java生成的公钥</param>  
        /// <returns></returns>  
        public static string RSAPublicKeyJava2DotNet(string publicKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
        }

        /// <summary>  
        /// RSA公钥格式转换,.net->java  
        /// </summary>  
        /// <param name="publicKey">.net生成的公钥</param>  
        /// <returns></returns>  
        public static string RSAPublicKeyDotNet2Java(string publicKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(publicKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            RsaKeyParameters pub = new RsaKeyParameters(false, m, p);

            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            return Convert.ToBase64String(serializedPublicBytes);
        }

    }
}

4,测试

CSharp加解密接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;


namespace RSA_Java2CSharp
{
    public class UEncrypt
    {
        /// <summary>
        /// 生成RSA私钥 公钥
        /// </summary>
        /// <param name="privateKey"></param>
        /// <param name="publicKey"></param>
        public static void RSAGenerateKey(ref string privateKey, ref string publicKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            privateKey = rsa.ToXmlString(true);
            publicKey = rsa.ToXmlString(false);
        }

        /// <summary>
        /// 用RSA公钥 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static byte[] RSAEncrypt(byte[] data, string publicKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(publicKey);
            byte[] encryptData = rsa.Encrypt(data, false);
            return encryptData;
        }

        /// <summary>
        /// 用RSA私钥 解密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static byte[] RSADecrypt(byte[] data, string privateKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(privateKey);
            byte[] decryptData = rsa.Decrypt(data, false);
            return decryptData;
        }
    }

}

测试

using RSA_Java2CSharp;
//java侧生成的RSA公钥 base64编码
string java_pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv2NbWPuQwPegAcydw3+xO3GOCKMMyUme9bUuEEmds4CogvasV1f2savwiXA5mKqawoxDjbsjUgdgPHQbmlrhpNBBMa83Us9w5xjgl5tZFyDusnO/r8IQa9pGW7NAJ6xJX5vYbv4rZWon1D8/N7l/ybsR6nZTt+rEcL1V78POXIwIDAQAB";

//java侧生成的RSA私钥 base64编码
string java_prikey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAK/Y1tY+5DA96ABzJ3Df7E7cY4IowzJSZ71tS4QSZ2zgKiC9qxXV/axq/CJcDmYqprCjEONuyNSB2A8dBuaWuGk0EExrzdSz3DnGOCXm1kXIO6yc7+vwhBr2kZbs0AnrElfm9hu/itlaifUPz83uX/JuxHqdlO36sRwvVXvw85cjAgMBAAECgYAL/8fpJrF7eT3ziegPE7iUSQWhRBbNwEHD80lL4dWc4E7/nPGns8pzkXlS/uUco5xsQTRN0Klzlsiff2ORKIe8yLxPlq8CjK2+LmS08lUwFa3EFEXaZ2EC3yj/YS28I+MosqVk/TjnVJGOXURt8JWGNpnuG4KpsdpSBv6eXQcPQQJBAPdnMCh/fiq2jwZOYYKnIAQ1TTfrFP62wyhs4dPdBIoIO8RtPsXYV/DCAAfYp+QmwxRvfNWdXBM7tAqEaUZxuEcCQQC19R0B5do3nQfv1Wz50KtTfVd+GJuRb1UMNFyWI0KnJch0KSuYRbVOte3FZrUYOMu9PkgeBQLDDMUI2Bfz7bRFAkEAq2l8LWMAKFnqSIU//EUM4r2Hbcnb9wrrtnOSF7dXcMd5mYPTbUKS04Wmfck3sdTFbsA77skjRVQlTvAk/KDH+wJBAKzdX1+MNRKctwudIdj766h37gU376Ptt0jO/h8NBKezd4sUCfyyTRuoL2pYtzd5zeXOI8mRTRxtJ0vNsIPnklkCQQCs+JyzCxH6fFDAw6dg3oKLrBYS9tgsBzedzQDEzkISy5eXOIqcMaZOcfDERkoWX5rQfvQcY7LoluUmSi8xTrhP";


string csharp_pubKey = RSAKeyConvert.RSAPublicKeyJava2DotNet(java_pubkey);
Console.WriteLine("csharp_pubkey:" + csharp_pubKey);
string csharp_prikey = RSAKeyConvert.RSAPrivateKeyJava2DotNet(java_prikey);
Console.WriteLine("csharp_prikey:" + csharp_prikey);


string msg = "123666666哪里(=@__@=)hehe"; ;
byte[] msgCrypted = UEncrypt.RSAEncrypt(System.Text.Encoding.Default.GetBytes(msg), csharp_pubKey);

byte[] msgDecrypted = UEncrypt.RSADecrypt(msgCrypted, csharp_prikey);
string result = System.Text.Encoding.Default.GetString(msgDecrypted);

Console.WriteLine(result); 
Console.ReadLine();

扩展阅读

C#实现RSA加密解密

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,用于加密和解密数据。C#提供了对RSA算法的支持。下面是一个简单的示例代码,展示如何使用RSA算法进行加密和解密: ```csharp using System; using System.Security.Cryptography; using System.Text; public class RSADemo { public static void Main() { // 创建RSA实例 using (RSA rsa = RSA.Create()) { try { // 生成RSA的公钥和私钥对 RSAParameters publicKey; RSAParameters privateKey; rsa.KeySize = 2048; // 设置密钥长度 // 生成密钥对 publicKey = rsa.ExportParameters(false); privateKey = rsa.ExportParameters(true); // 要加密的数据 string dataToEncrypt = "Hello, RSA!"; // 加密数据 byte[] encryptedData = EncryptData(Encoding.UTF8.GetBytes(dataToEncrypt), publicKey); // 解密数据 byte[] decryptedData = DecryptData(encryptedData, privateKey); // 显示结果 Console.WriteLine("原始数据: {0}", dataToEncrypt); Console.WriteLine("加密后的数据: {0}", Convert.ToBase64String(encryptedData)); Console.WriteLine("解密后的数据: {0}", Encoding.UTF8.GetString(decryptedData)); } catch (CryptographicException e) { Console.WriteLine(e.Message); } } } // 使用RSA算法加密数据 public static byte[] EncryptData(byte[] dataToEncrypt, RSAParameters publicKey) { using (RSA rsa = RSA.Create()) { try { rsa.ImportParameters(publicKey); return rsa.Encrypt(dataToEncrypt, RSAEncryptionPadding.OaepSHA256); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } } // 使用RSA算法解密数据 public static byte[] DecryptData(byte[] dataToDecrypt, RSAParameters privateKey) { using (RSA rsa = RSA.Create()) { try { rsa.ImportParameters(privateKey); return rsa.Decrypt(dataToDecrypt, RSAEncryptionPadding.OaepSHA256); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } } } ``` 这个示例代码,我们使用`RSA.Create()`创建了一个RSA实例,并设置了密钥长度为2048位。然后,调用`ExportParameters()`方法生成公钥和私钥对。接下来,我们使用公钥加密数据,然后再用私钥解密数据。最后,我们将结果打印到控制台上。 需要注意的是,RSA算法对于较大的数据加密耗时较长,因此通常会使用RSA算法加密对称加密算法(如AES)的密钥,从而提高加密效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iningwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值