1、RSA非对称加密算法
RSA加密算法是最常用的非对称加密算法,由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)于1977年一起提出,RSA就是他们三人姓氏开头字母拼在一起组成的。非对称加密算法的特点就是加密秘钥和解密秘钥不同,秘钥分为公钥和私钥,用私钥加密的明文,只能用公钥解密;用公钥加密的明文,只能用私钥解密。
RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。RSA的安全基于大数分解的难度。其公钥和私钥是一对大素数(100到200位十进制数或更大)的函数。从一个公钥和密文恢复出明文的难度,等价于分解两个大素数之积。
2、通过扩展方法写入和读取xml配置文件参数
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using System.Xml; namespace CJavaPy.Encrypt { public static class RSACryptoServiceProviderExtensions { public static void FromXmlString(this RSACryptoServiceProvider rsa, string xmlString) { RSAParameters parameters = new RSAParameters(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlString); if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) { foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) { switch (node.Name) { case "Modulus": parameters.Modulus = Convert.FromBase64String(node.InnerText); break; case "Exponent": parameters.Exponent = Convert.FromBase64String(node.InnerText); break; case "P": parameters.P = Convert.FromBase64String(node.InnerText); break; case "Q": parameters.Q = Convert.FromBase64String(node.InnerText); break; case "DP": parameters.DP = Convert.FromBase64String(node.InnerText); break; case "DQ": parameters.DQ = Convert.FromBase64String(node.InnerText); break; case "InverseQ": parameters.InverseQ = Convert.FromBase64String(node.InnerText); break; case "D": parameters.D = Convert.FromBase64String(node.InnerText); break; } } } else { throw new Exception("Invalid XML RSA key."); } rsa.ImportParameters(parameters); } public static string ToXmlString(this RSACryptoServiceProvider rsa, bool includePrivateParameters) { RSAParameters parameters = rsa.ExportParameters(includePrivateParameters); 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(parameters.Modulus), Convert.ToBase64String(parameters.Exponent), Convert.ToBase64String(parameters.P), Convert.ToBase64String(parameters.Q), Convert.ToBase64String(parameters.DP), Convert.ToBase64String(parameters.DQ), Convert.ToBase64String(parameters.InverseQ), Convert.ToBase64String(parameters.D)); } } }
3、实现公钥和私钥加解密工具类
using System; using System.IO; using System.Reflection; using System.Security.Cryptography; using Microsoft.AspNetCore.Hosting; namespace CJavaPy.Encrypt { public class EncryptService { private const string Path = "Encrypt/"; private const string PrivateKeyFile = "Private.config"; private const string PublicKeyFile = "Public.config"; private readonly string _folder; private readonly string _privateKeyFileName; private readonly string _publicKeyFileName; public EncryptService(IWebHostEnvironment hostingEnvironment) { _folder = System.IO.Path.Combine(hostingEnvironment.ContentRootPath, Path); _privateKeyFileName = System.IO.Path.Combine(_folder, PrivateKeyFile); _publicKeyFileName = System.IO.Path.Combine(_folder, PublicKeyFile); } public byte[] Encrypt(byte[] source) { Func<byte[], byte[]> encrypt = sou => { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { if (!Directory.Exists(_folder)) { Directory.CreateDirectory(_folder); } if (!File.Exists(_privateKeyFileName)) { File.WriteAllText(_privateKeyFileName, rsa.ToXmlString(true)); File.WriteAllText(_publicKeyFileName, rsa.ToXmlString(false)); } rsa.FromXmlString(File.ReadAllText(_publicKeyFileName)); int maxBlockSize = rsa.KeySize / 8 - 11; if (sou.Length <= maxBlockSize) return rsa.Encrypt(sou, false); using (MemoryStream plaiStream = new MemoryStream(sou)) { using (MemoryStream crypStream = new MemoryStream()) { byte[] buffer = new byte[maxBlockSize]; int blockSize = plaiStream.Read(buffer, 0, maxBlockSize); while (blockSize > 0) { byte[] toEncrypt = new byte[blockSize]; Array.Copy(buffer, 0, toEncrypt, 0, blockSize); byte[] cryptograph = rsa.Encrypt(toEncrypt, false); crypStream.Write(cryptograph, 0, cryptograph.Length); blockSize = plaiStream.Read(buffer, 0, maxBlockSize); } return crypStream.ToArray(); } } } }; return MarkData(encrypt(source)); } public byte[] Decrypt(byte[] source) { if (IsEncrypt(source)) { Func<byte[], byte[]> decrypt = sou => { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { if (File.Exists(_folder + PrivateKeyFile)) { rsa.FromXmlString(File.ReadAllText(_privateKeyFileName)); } int maxBlockSize = rsa.KeySize / 8; if (sou.Length <= maxBlockSize) return rsa.Decrypt(sou, false); using (MemoryStream crypStream = new MemoryStream(sou)) { using (MemoryStream plaiStream = new MemoryStream()) { byte[] buffer = new byte[maxBlockSize]; int blockSize = crypStream.Read(buffer, 0, maxBlockSize); while (blockSize > 0) { byte[] toDecrypt = new byte[blockSize]; Array.Copy(buffer, 0, toDecrypt, 0, blockSize); byte[] plaintext = rsa.Decrypt(toDecrypt, false); plaiStream.Write(plaintext, 0, plaintext.Length); blockSize = crypStream.Read(buffer, 0, maxBlockSize); } return plaiStream.ToArray(); } } } }; return decrypt(ClearDataMark(source)); } return source; } private byte[] MarkData(byte[] source) { byte[] newBytes = new byte[source.Length + 200]; for (int i = 0; i < newBytes.Length; i++) { if (i < 100 || i > newBytes.Length - 100 - 1) { newBytes[i] = 0; } else { newBytes[i] = source[i - 100]; } } return newBytes; } private byte[] ClearDataMark(byte[] source) { byte[] newBytes = new byte[source.Length - 200]; for (int i = 100; i < source.Length - 100; i++) { newBytes[i - 100] = source[i]; } return newBytes; } private bool IsEncrypt(byte[] source) { for (int i = 0; i < 100; i++) { if (source[i] != 0 || source[source.Length - i - 1] != 0) { return false; } } return true; } } }
4、使用方法
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using CJavaPy.Encrypt; namespace CJavaPy.Encrypt { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } //调用示例代码 EncryptService encryptService = new EncryptService(env); //配置文件不存在会自动生成 byte[] data= encryptService.Encrypt(System.Text.Encoding.UTF8.GetBytes("www.cjavapy.com")); string val = System.Text.Encoding.UTF8.GetString(encryptService.Decrypt(data)); string valOrigin = System.Text.Encoding.UTF8.GetString(data); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); } } }