C# RSA非对称加密、解密及格式转换
前言
本文主要介绍如何使用.Net自带API结合BouncyCastle类库实现RSA加密和解密,密钥生成和密钥格式转换。
一、RSA介绍
RSA加密算法是1977年由Ron Rivest、Adi Shamirh和Len Adleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。
RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙。因为加密的钥匙是公开的,所又称公钥,解密的钥匙是不公开的,所以称为私钥。
RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
RSA的缺点主要有:
产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。
分组长度太大,为保证安全性,
n至少也要600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048bits长的密钥,其他实体使用1024bits的密钥。RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。保密级别 对称密钥长度(bit) RSA密钥长度(bit) ECC密钥长度(bit) 保密年限 80 80 1024 160 2010 112 112 2048 224 2030 128 128 3072 256 2040 192 192 7680 384 2080 256 256 15360 512 2120
RSA的算法在这里就不赘述了,可以看看下面这张图有利于理解。

二、C#代码实现
2.1 生成公钥/私钥
struct RSASecretKey
{
public RSASecretKey(string privateKey, string publicKey)
{
PrivateKey = privateKey;
PublicKey = publicKey;
}
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public override string ToString()
{
return string.Format("PrivateKey: {0}\r\nPublicKey: {1}", PrivateKey, PublicKey);
}
}
/// <summary>
/// 生成`RSA`密钥
/// </summary>
/// <param name="keySize">密钥的大小,从384位到16384位,每8位递增 </param>
/// <returns></returns>
RSASecretKey GenerateRSASecretKey(int keySize)
{
RSASecretKey rsaKey = new RSASecretKey();
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize))
{
rsaKey.PrivateKey = rsa.ToXmlString(true);
rsaKey.PublicKey = rsa.ToXmlString(false);
}
return rsaKey;
}

2.2 公钥加密/私钥解密
string RSAEncrypt(string xmlPublicKey, string content)
{
string encryptedContent = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPublicKey);
byte[] encryptedData = rsa.Encrypt(Encoding.Default.GetBytes(content), false);
encryptedContent = Convert.ToBase64String(encryptedData);
}
return encryptedContent;
}
string RSADecrypt(string xmlPrivateKey, string content)
{
string decryptedContent = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPrivateKey);
byte[] decryptedData = rsa.Decrypt(Convert.FromBase64String(content), false);
decryptedContent = Encoding.GetEncoding("gb2312").GetString(decryptedData);
}
return decryptedContent;
}


2.3 密钥格式转换
C#中RSA公钥和私钥的格式都是XML的,而在其他语言如java中,生成的RSA密钥就是普通的Base64字符串,所以需要将C# xml格式的密钥转换成普通的Base64字符串,同时也要实现Base64密钥字符串生成C# xml格式的密钥。
安装 BouncyCastle 这个Nuget包 PM > Install-Package BouncyCastle
构造一个RSAKeyConventer类
using System;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
namespace RSA
{
public class RSAKeyConverter
{
/// <summary>
/// 转换"私钥"格式
/// </summary>
/// <param name="xmlPrivateKey">xml格式私钥</param>
/// <returns>base64格式私钥</returns>
public static string ToBase64PrivateKey(string xmlPrivateKey)
{
string result = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPrivateKey);
RSAParameters param = rsa.ExportParameters(true);
RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(
new BigInteger(1, param.Modulus), new BigInteger(1, param.Exponent),
new BigInteger(1, param.D), new BigInteger(1, param.P),
new BigInteger(1, param.Q), new BigInteger(1, param.DP),
new BigInteger(1, param.DQ), new BigInteger(1, param.InverseQ));
PrivateKeyInfo privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
result = Convert.ToBase64String(privateKey.ToAsn1Object().GetEncoded());
}
return result;
}
/// <summary>
/// 转换"公钥"格式
/// </summary>
/// <param name="xmlPublicKey">xml格式公钥</param>
/// <returns>base64格式公钥</returns>
public static string ToBase64PublicKey(string xmlPublicKey)
{
string result = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(xmlPublicKey);
RSAParameters p = rsa.ExportParameters(false);
RsaKeyParameters keyParams = new RsaKeyParameters(
false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent));
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyParams);
result = Convert.ToBase64String(publicKeyInfo.ToAsn1Object().GetEncoded());
}
return result;
}
/// <summary>
/// 转换"私钥"格式
/// </summary>
/// <param name="privateKey">base64格式私钥</param>
/// <returns>xml格式私钥</returns>
public static string ToXmlPrivateKey(string privateKey)
{
RsaPrivateCrtKeyParameters privateKeyParams =
PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)) as RsaPrivateCrtKeyParameters;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsaParams = new RSAParameters()
{
Modulus = privateKeyParams.Modulus.ToByteArrayUnsigned(),
Exponent = privateKeyParams.PublicExponent.ToByteArrayUnsigned(),
D = privateKeyParams.Exponent.ToByteArrayUnsigned(),
DP = privateKeyParams.DP.ToByteArrayUnsigned(),
DQ = privateKeyParams.DQ.ToByteArrayUnsigned(),
P = privateKeyParams.P.ToByteArrayUnsigned(),
Q = privateKeyParams.Q.ToByteArrayUnsigned(),
InverseQ = privateKeyParams.QInv.ToByteArrayUnsigned()
};
rsa.ImportParameters(rsaParams);
return rsa.ToXmlString(true);
}
}
/// <summary>
/// 转换"公钥"格式
/// </summary>
/// <param name="pubilcKey">base64格式公钥</param>
/// <returns>xml格式公钥</returns>
public static string ToXmlPublicKey(string pubilcKey)
{
RsaKeyParameters p =
PublicKeyFactory.CreateKey(Convert.FromBase64String(pubilcKey)) as RsaKeyParameters;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsaParams = new RSAParameters
{
Modulus = p.Modulus.ToByteArrayUnsigned(),
Exponent = p.Exponent.ToByteArrayUnsigned()
};
rsa.ImportParameters(rsaParams);
return rsa.ToXmlString(false);
}
}
}
}
C# RSA非对称加密、解密及格式转换的更多相关文章
- CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互
(以下代码中都只做测试用,有些地方没有释放内存...这个自己解决下) 1.RSA非对称的,首先提供一个供测试用的证书和私钥的数据 1)pem格式的证书和私钥(公私钥是对应的)的base64编码 voi ...
- javascript版前端页面RSA非对称加密解密
最近由于项目需要做一个url传参,并在页面显示参数内容的需求,这样就会遇到一个url地址可能会被假冒, 并传递非法内容显示在页面的尴尬情况 比如xxx.shtml?server=xxx是坏人& ...
- ios php RSA 非对称加密解密 der 和pem生成
ios 使用public_key.der加密 php 使用 private_key.pem解密 openssl req -x509 -out public_key.der -outform der - ...
- Java对称与非对称加密解密,AES与RSA
加密技术可以分为对称与非对称两种. 对称加密,解密,即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等 而非对称技术,加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等 为什么 ...
- 使用java实现对称加密解密(AES),非对称加密解密(RSA)
对称加密:双方采用同样的秘钥进行加密和解密.特点是速度快,但是安全性没有非对称加密高 非对称加密:接收方生成的公有秘钥公布给发送方,发送方使用该公有秘钥加密之后,发送给接收方,然后接收方使用私有秘钥解 ...
- php 非对称加密解密类
<?phpnamespace app\Parentclient\model;header("Content-Type: text/html;charset=utf-8");/ ...
- RSA 非对称加密,私钥转码为pkcs8 错误总结
RSA 非对称加密,私钥转码为pkcs8 错误总结 最近在和某上市公司对接金融方面的业务时,关于RSA对接过程中遇到了一个坑,特来分享下解决方案. 该上市公司简称为A公司,我们简称为B公司.A-B两家 ...
- RSA的密钥把JAVA格式转换成C#的格式(2)
把C#格式转换成Java:RSA的密钥把JAVA格式转换成C#的格式(1) 我已经在第一篇介绍过如何把C#格式转换成Java,现在来看看如何把Java格式转换成C#. /// <summary& ...
- php rsa 非对称加解密类
<?php header("Content-Type: text/html;charset=utf-8"); /* 生成公钥.私钥对,私钥加密的内容能通过公钥解密(反过来亦可 ...
- Atitit RSA非对称加密原理与解决方案
Atitit RSA非对称加密原理与解决方案 1.1. 一.一点历史 1 1.2. 八.加密和解密 2 1.3. 二.基于RSA的消息传递机制 3 1.4. 基于rsa的授权验证机器码 4 1.5. ...
随机推荐
- centos7系统的七个运行级别和设置默认运行级别
一.系统七个运行级别概述 0 系统停机模式,系统默认运行级别不能设置为0,否则不能正常启动,机器关的 1 单用户模式,root权限,用于系统维护,禁止远程登陆,就像Windows下的安全模式登录 2 ...
- 在Cocos2d中拖动组件并吸附到节点
最近在学习制作小游戏,要实现一个拖动吸附效果,这里简单实现一下 代码实现 定义节点和函数功能 在properties里新建一个对象,用来接收目标区域的节点 properties:{ sense: { ...
- Stable Diffusion WebUI详细使用指南
Stable Diffusion WebUI(AUTOMATIC1111,简称A1111)是一个为高级用户设计的图形用户界面(GUI),它提供了丰富的功能和灵活性,以满足复杂和高级的图像生成需求.由于 ...
- matplotlib学习:搞明白plt. /ax./ fig
原文章一:https://zhuanlan.zhihu.com/p/93423829,原文章二:https://jishuin.proginn.com/p/763bfbd23e20 感谢作者的讲 ...
- C语言——函数基本知识
什么是函数 函数的定义 函数就是程序中独立的功能.(简单来说就是把代码打包成整体,起个名字,方便以后使用) 函数的使用 定义函数的格式 格式: 返回值类型 函数名(形参1,形参2,...) { 函数体 ...
- Symbol.for()
当我们在不同的模块或文件中需要共享一个特定的Symbol时,可以使用Symbol.for()方法来实现. 假设我们有两个模块,分别是module1.js和module2.js.我们希望在这两个模块中使 ...
- 在ftl模板中调整表格
- xxlJob Cron表达式 0 0 8,13 * * ?
xxlJob Cron表达式 0 0 8,13 * * ? Cron有如下两种语法格式:(1)Seconds Minutes Hours DayofMonth Month DayofWeek Yea ...
- 订单推送设计思路-基于支付ID而不是订单号来推送
订单推送设计思路-基于支付ID而不是订单号来推送 方案:不是基于订单号来核销和分账的,抖音是基于每一笔抖音支付来做订单推送,核销和分账现象:这样会在抖音的订单中心中会出现很多条订单推送的记录. 抖音A ...
- window10设置保护眼睛的颜色
1.调出运行菜单.右击开始键选择运行,或者同时按下键盘上的WIN+R打开运行框,输入 regedit 回车转到注册表编辑器.2.选择第二项 HKEY_CURRENT_USER 点击进入.进入后点击 C ...