using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace ProjectManagementSystem.Common.Function
{
public class RSAHelper
{
//参考连接:https://www.jianshu.com/p/faefcc58c79b
//工具网址1:https://the-x.cn/certificate/PemToXml.aspx
//工具网址2:https://superdry.apphb.com/tools/online-rsa-key-converter
//需要依赖一个第三方库,叫BouncyCastle ;在线获取安装包的代码是:PM >Install-Package BouncyCastle
//安装步骤:VS中选择 工具(T)---》NuGet包管理器(N)---》程序包管理器控制台(O)---》然后数据以上代码即可
#region Demo示例
public static void Demo()
{
string xmlgy = "";
string xmlsy = "";
string xmlmdata = "";
string xmljdata = "";
string xmlsign = "";
string xmlresult = "";
string pemgy = "";
string pemsy = "";
string pemmdata = "";
string pemjdata = "";
string pemsign = "";
string pemresult = "";
RSAHelper.GetXMLRSAKeys(out xmlsy, out xmlgy);
RSAHelper.GetPEMRSAKeys(out pemsy, out pemgy);
string str1 = "1234567890";
Console.WriteLine("===================xml===================");
Console.WriteLine("===================xml公钥");
Console.WriteLine(xmlgy);
Console.WriteLine("===================xml私钥");
Console.WriteLine(xmlsy);
Console.WriteLine("===================xml公钥加密后的数据");
xmlmdata = RSAHelper.XMLRSAEncrypt(xmlgy, str1);
Console.WriteLine(xmlmdata);
Console.WriteLine("===================xml私钥解密后的字符");
xmljdata = RSAHelper.XMLRSADecrypt(xmlsy, xmlmdata);
Console.WriteLine(xmljdata);
Console.WriteLine("===================xml私钥加签后的sign");
xmlsign = RSAHelper.XMLSign(xmlmdata, xmlsy);
Console.WriteLine(xmlsign);
Console.WriteLine("===================xml公钥验签后的结果");
xmlresult = RSAHelper.XMLSignCheck(xmlmdata, xmlsign, xmlgy).ToString();
Console.WriteLine(xmlresult);
Console.WriteLine("===================xml===================");
Console.WriteLine("=========================================*****=========================================");
Console.WriteLine("===================pem===================");
Console.WriteLine("===================pem公钥");
Console.WriteLine(pemgy);
Console.WriteLine("===================pem私钥");
Console.WriteLine(pemsy);
Console.WriteLine("===================pem公钥加密后的数据");
pemmdata = RSAHelper.PEMRSAEncrypt(pemgy, str1);
Console.WriteLine(pemmdata);
Console.WriteLine("===================pem私钥解密后的字符");
pemjdata = RSAHelper.PEMRSADecrypt(pemsy, pemmdata);
Console.WriteLine(pemjdata);
Console.WriteLine("===================pem私钥加签后的sign");
pemsign = RSAHelper.PEMSign(pemmdata, pemsy);
Console.WriteLine(pemsign);
Console.WriteLine("===================pem公钥验签后的结果");
pemresult = RSAHelper.PEMSignCheck(pemmdata, pemsign, pemgy).ToString();
Console.WriteLine(pemresult);
Console.WriteLine("===================pem===================");
}
#endregion
#region 获取RSA密钥对
///
/// 获取XML格式密钥对
///
/// xml私钥
/// xml公钥
public static void GetXMLRSAKeys(out string xmlprikey, out string xmlpubkey)
{
try
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
xmlprikey = rsa.ToXmlString(true);
xmlpubkey = rsa.ToXmlString(false);
}
catch (Exception ex)
{
throw ex;
}
}
///
/// 获取PEM格式密钥对
///
/// pem私钥
/// pem公钥
public static void GetPEMRSAKeys(out string pemprikey, out string pempubkey)
{
try
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
pemprikey = XMLToPEM_Pri(rsa.ToXmlString(true));
pempubkey = XMLToPEM_Pub(rsa.ToXmlString(false));
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region RSA加密
///
/// 使用XML格式加密
///
/// xml公钥
/// 需要加密的字符串
/// 返回加密后的字符串
public static string XMLRSAEncrypt(string xmlpubkey, string encryptstr)
{
byte[] PlainTextBArray;
byte[] CypherTextBArray;
string Result;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlpubkey);
PlainTextBArray = (new UTF8Encoding()).GetBytes(encryptstr);
CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
Result = Convert.ToBase64String(CypherTextBArray);
return Result;
}
///
/// 使用PEM格式加密
///
/// pem公钥
/// 需要加密的字符串
/// 返回加密后的字符串
public static string PEMRSAEncrypt(string pempubkey, string encryptstr)
{
StringReader sr = new StringReader(pempubkey);
AsymmetricKeyParameter publickey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter;
if (publickey == null)
throw new Exception("PEM格式公钥不能为空");
try
{
var engine = new Pkcs1Encoding(new RsaEngine());
engine.Init(true, publickey);
byte[] bytes = Encoding.UTF8.GetBytes(encryptstr);//Encoding.UTF8.GetBytes(data);
bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
return Convert.ToBase64String(bytes);// Convert.ToBase64String(bytes);
}
catch
{
throw new Exception("加密失败");
}
}
#endregion
#region RSA解密
///
/// 使用XML格式解密
///
/// xml格式私钥
/// 需要解密的字符串
/// 返回解密后的字符串
public static string XMLRSADecrypt(string xmlprikey, string decryptstr)
{
try
{
byte[] PlainTextBArray;
byte[] DypherTextBArray;
string Result;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlprikey);
PlainTextBArray = Convert.FromBase64String(decryptstr);
DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
Result = (new UTF8Encoding()).GetString(DypherTextBArray);
return Result;
}
catch (Exception ex)
{
throw ex;
}
}
///
/// 使用PEM格式解密
///
/// pem格式私钥
/// 需要解密的字符串
/// 返回解密后的字符串
public static string PEMRSADecrypt(string pemprikey, string decryptstr)
{
byte[] bytes = Convert.FromBase64String(decryptstr);// Convert.FromBase64String(data);
StringReader sr = new StringReader(pemprikey);
AsymmetricKeyParameter prikey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter;
if (prikey == null)
throw new Exception("私钥读取失败");
try
{
var engine = new Pkcs1Encoding(new RsaEngine());
engine.Init(false, prikey);
bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
return Encoding.UTF8.GetString(bytes);////Encoding.UTF8.GetString(bytes);
}
catch
{
throw new Exception("解密失败");
}
}
#endregion
#region RSA签名
///
/// 使用XML格式的私钥加签
///
/// 需要加签的字符串
/// xml格式的私钥
/// 返回签名
public static string XMLSign(string str, string xmlprikey)
{
//根据需要加签时的哈希算法转化成对应的hash字符节
byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
var sha256 = new SHA256CryptoServiceProvider();
byte[] rgbHash = sha256.ComputeHash(bt);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(xmlprikey);
RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
byte[] inArray = formatter.CreateSignature(rgbHash);
return Convert.ToBase64String(inArray);
}
///
/// 使用PEM格式的私钥加签
///
/// 需要加签的字符串
/// pem格式的私钥
/// 返回签名
public static string PEMSign(string str, string pemprikey)
{
pemprikey = PEMToXML_All(pemprikey, true);
//根据需要加签时的哈希算法转化成对应的hash字符节
byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
var sha256 = new SHA256CryptoServiceProvider();
byte[] rgbHash = sha256.ComputeHash(bt);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(pemprikey);
RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
byte[] inArray = formatter.CreateSignature(rgbHash);
return Convert.ToBase64String(inArray);
}
#endregion
#region RSA验签
///
/// 使用XML格式的公钥验签
///
/// 需要验签的字符串
/// 签名
/// xml格式的公钥
/// 是/否
public static bool XMLSignCheck(string str, string sign, string xmlpubkey)
{
try
{
byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
var sha256 = new SHA256CryptoServiceProvider();
byte[] rgbHash = sha256.ComputeHash(bt);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(xmlpubkey);
RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
deformatter.SetHashAlgorithm("SHA256");
byte[] rgbSignature = Convert.FromBase64String(sign);
if (deformatter.VerifySignature(rgbHash, rgbSignature))
{
return true;
}
return false;
}
catch
{
return false;
}
}
///
/// 使用XML格式的公钥验签
///
/// 需要验签的字符串
/// 签名
/// pem格式的公钥
/// 是/否
public static bool PEMSignCheck(string str, string sign, string pempubkey)
{
try
{
pempubkey = PEMToXML_All(pempubkey, false);
byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
var sha256 = new SHA256CryptoServiceProvider();
byte[] rgbHash = sha256.ComputeHash(bt);
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(pempubkey);
RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
deformatter.SetHashAlgorithm("SHA256");
byte[] rgbSignature = Convert.FromBase64String(sign);
if (deformatter.VerifySignature(rgbHash, rgbSignature))
{
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
#endregion
#region XML转PEM
///
/// XML格式的公钥转PEM格式的公钥
///
/// xml格式的公钥
/// pem格式的公钥
public static string XMLToPEM_Pub(string xmlpubkey)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlpubkey);
var p = rsa.ExportParameters(false);
RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent));
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string publicKey = Convert.ToBase64String(serializedPublicBytes);
return Format(publicKey, true);
}
///
/// XML格式的私钥转PEM格式的私钥
///
/// xml格式的私钥
/// pem格式的私钥
public static string XMLToPEM_Pri(string xmlprikey)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlprikey);
var p = rsa.ExportParameters(true);
var key = new RsaPrivateCrtKeyParameters(
new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D),
new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ),
new BigInteger(1, p.InverseQ));
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(key);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
string privateKey = Convert.ToBase64String(serializedPrivateBytes);
return Format(privateKey, false);
}
///
/// 格式化公钥/私钥
///
/// 生成的公钥/私钥
/// true:公钥 false:私钥
/// PEM格式的公钥/私钥
private static string Format(string key, bool type)
{
string result = string.Empty;
int length = key.Length / 64;
for (int i = 0; i < length; i++)
{
int start = i * 64;
result = result + key.Substring(start, 64) + "\r\n";
}
result = result + key.Substring(length * 64);
//if (type)
//{
// result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n");
// result += "\r\n-----END PUBLIC KEY-----";
//}
//else
//{
// result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n");
// result += "\r\n-----END PRIVATE KEY-----";
//}
return result;
}
#endregion
#region PEM转XML
///
/// PEM格式的密钥转XML格式
///
/// pem格式的密钥
/// true:私钥;false:公钥
/// xml格式密钥
public static string PEMToXML_All(string pemkey, bool isprikey)
{
if (isprikey)
{
pemkey = pemkey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "");
}
else
{
pemkey = pemkey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
}
string rsaKey = string.Empty;
object pemObject = null;
RSAParameters rsaPara = new RSAParameters();
using (StringReader sReader = new StringReader(pemkey))
{
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader);
pemObject = pemReader.ReadObject();
}
//RSA私钥
if (isprikey)
{
RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pemkey));
rsaPara = new RSAParameters
{
Modulus = key.Modulus.ToByteArrayUnsigned(),
Exponent = key.PublicExponent.ToByteArrayUnsigned(),
D = key.Exponent.ToByteArrayUnsigned(),
P = key.P.ToByteArrayUnsigned(),
Q = key.Q.ToByteArrayUnsigned(),
DP = key.DP.ToByteArrayUnsigned(),
DQ = key.DQ.ToByteArrayUnsigned(),
InverseQ = key.QInv.ToByteArrayUnsigned(),
};
}
//RSA公钥
else
{
RsaKeyParameters key = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pemkey));
rsaPara.Modulus = key.Modulus.ToByteArrayUnsigned();
rsaPara.Exponent = key.Exponent.ToByteArrayUnsigned();
}
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaPara);
using (StringWriter sw = new StringWriter())
{
sw.Write(rsa.ToXmlString(isprikey ? true : false));
rsaKey = sw.ToString();
}
return rsaKey;
}
#endregion
}
}