using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using CryptographyRSA = System.Security.Cryptography.RSA; // 别名避免与当前类名冲突
namespace System
{
///
/// RSA操作类(跨平台实现)
///
public class RSA
{
// 记录当前实例是否仅包含公钥(替代原来的 rsa.PublicOnly)
private bool publicOnly;
///
/// 导出XML格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
///
public string ToXML(bool convertToPublic = false)
{
bool includePrivate = !publicOnly && !convertToPublic;
return rsa.ToXmlString(includePrivate);
}
///
/// 导出PEM PKCS#1格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
///
public string ToPEM_PKCS1(bool convertToPublic = false)
{
if (!publicOnly && !convertToPublic)
{
return rsa.ExportRSAPrivateKeyPem();
}
return rsa.ExportRSAPublicKeyPem();
}
///
/// 导出PEM PKCS#8格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
///
public string ToPEM_PKCS8(bool convertToPublic = false)
{
if (!publicOnly && !convertToPublic)
{
return rsa.ExportPkcs8PrivateKeyPem();
}
return rsa.ExportSubjectPublicKeyInfoPem();
}
///
/// 加密字符串(utf-8),出错抛异常
///
public string Encode(string str)
{
return RSA_Unit.Base64EncodeBytes(Encode(Encoding.UTF8.GetBytes(str)));
}
///
/// 加密数据,出错抛异常
///
public byte[] Encode(byte[] data)
{
int blockLen = rsa.KeySize / 8 - 11;
if (data.Length <= blockLen)
{
return rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
}
using (var dataStream = new MemoryStream(data))
using (var enStream = new MemoryStream())
{
byte[] buffer = new byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0)
{
byte[] block = new byte[len];
Array.Copy(buffer, 0, block, 0, len);
byte[] enBlock = rsa.Encrypt(block, RSAEncryptionPadding.Pkcs1);
enStream.Write(enBlock, 0, enBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return enStream.ToArray();
}
}
///
/// 解密字符串(utf-8),解密异常返回null
///
public string DecodeOrNull(string str)
{
if (string.IsNullOrEmpty(str))
return null;
var bytes = RSA_Unit.Base64DecodeBytes(str);
if (bytes == null)
return null;
var decrypted = DecodeOrNull(bytes);
if (decrypted == null)
return null;
return Encoding.UTF8.GetString(decrypted);
}
///
/// 解密数据,解密异常返回null
///
public byte[] DecodeOrNull(byte[] data)
{
try
{
int blockLen = rsa.KeySize / 8;
if (data.Length <= blockLen)
{
return rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
}
using (var dataStream = new MemoryStream(data))
using (var deStream = new MemoryStream())
{
byte[] buffer = new byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0)
{
byte[] block = new byte[len];
Array.Copy(buffer, 0, block, 0, len);
byte[] deBlock = rsa.Decrypt(block, RSAEncryptionPadding.Pkcs1);
deStream.Write(deBlock, 0, deBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return deStream.ToArray();
}
}
catch
{
return null;
}
}
///
/// 对str进行签名,并指定hash算法(如:SHA256)
///
public string Sign(string hash, string str)
{
return RSA_Unit.Base64EncodeBytes(Sign(hash, Encoding.UTF8.GetBytes(str)));
}
///
/// 对data进行签名,并指定hash算法(如:SHA256)
///
public byte[] Sign(string hash, byte[] data)
{
return rsa.SignData(data, new HashAlgorithmName(hash), RSASignaturePadding.Pkcs1);
}
///
/// 验证字符串str的签名是否是sgin,并指定hash算法(如:SHA256)
///
public bool Verify(string hash, string sgin, string str)
{
var bytes = RSA_Unit.Base64DecodeBytes(sgin);
if (bytes == null)
return false;
return Verify(hash, bytes, Encoding.UTF8.GetBytes(str));
}
///
/// 验证data的签名是否是sgin,并指定hash算法(如:SHA256)
///
public bool Verify(string hash, byte[] sgin, byte[] data)
{
try
{
return rsa.VerifyData(data, sgin, new HashAlgorithmName(hash), RSASignaturePadding.Pkcs1);
}
catch
{
return false;
}
}
private CryptographyRSA rsa;
public RSA() : this(2048)
{
}
///
/// 用指定密钥大小创建一个新的RSA,出错抛异常
///
public RSA(int keySize)
{
rsa = CryptographyRSA.Create();
rsa.KeySize = keySize;
publicOnly = false; // 新生成的密钥对包含私钥
}
///
/// 通过指定的密钥,创建一个RSA,xml内可以只包含一个公钥或私钥,或都包含,出错抛异常
///
public RSA(string xml)
{
rsa = CryptographyRSA.Create();
rsa.FromXmlString(xml);
// 判断是否仅包含公钥
publicOnly = false;
try
{
rsa.ExportParameters(true); // 能导出私钥参数说明含私钥
}
catch (CryptographicException)
{
publicOnly = true;
}
}
///
/// 通过一个pem文件创建RSA,pem为公钥或私钥,出错抛异常
///
public RSA(string pem, bool noop)
{
rsa = CryptographyRSA.Create();
// 1. 兼容文件路径
string pemContent = pem;
if (!pemContent.Contains("BEGIN"))
{
pemContent = File.ReadAllText(pem);
}
// 2. 提取 Base64 部分(忽略标签)
var match = Regex.Match(pemContent,
@"-----BEGIN [^-]+-----([\s\S]*?)-----END [^-]+-----",
RegexOptions.Singleline);
if (!match.Success)
throw new CryptographicException("无效的 PEM 格式。");
string base64 = match.Groups[1].Value
.Replace("\r", "")
.Replace("\n", "")
.Replace(" ", "")
.Replace("\t", "")
.Trim();
byte[] der = Convert.FromBase64String(base64);
// 3. 依次尝试常见 RSA 密钥格式(顺序可调整)
// 先尝试 PKCS#8 私钥,再尝试 PKCS#1 私钥,然后公钥
try
{
rsa.ImportPkcs8PrivateKey(der, out _);
publicOnly = false;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportRSAPrivateKey(der, out _);
publicOnly = false;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportSubjectPublicKeyInfo(der, out _);
publicOnly = true;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportRSAPublicKey(der, out _);
publicOnly = true;
return;
}
catch (CryptographicException) { }
throw new CryptographicException("无法识别的 RSA 密钥格式。");
}
}
}