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 密钥格式。"); } } }