RSA非对称式加解密笔记
1、服务器生成【公钥】和【私钥】,成对生成;
2、客户端生成证书信息,使用【公钥】进行加密,前提是有公钥,并生成证书信息;
3、客户端发送自身的计算机名、MAC、用户名、证书内容给服务器;
4、服务器使用【私钥】对证书内容进行解密,并验证证书信息中的计算机名、MAC、用户名是否一致,首先是能否解密,其次是信息是否一致。
能解决表明客户端拥有相应公钥;
----------------------
备注:签名信息需要使用私钥生成,用于客户端验证数据是否来自服务器,这种情况下,客户端可以使用公钥对签名进行验证,签名正确的情况下,
则可以认为密文没有被修改,可以将密文解密得到目标信息。
-----------------------
上面,在服务器端生成【公钥】和【私钥】密钥对;
然后,客户端使用公钥,生成证书,生成后即删除公钥,确保不会后期更换电脑被重新生成;即无公钥的情况下,客户端无法生成有效的证书。
服务器使用【私钥】进行解密,得到明文信息,并做校验。
-----------------------------------------------------------------
公私钥可以互相加解密,由公钥加密私钥解密,或者由私钥加密公钥解密,相当来说,加密使用公钥,解密使用私钥,因为私钥长度更长,不容易被破解。
通常服务器一方掌握私钥,而公钥提供给多个客户端,客户端可以使用公钥来进行解密和验证,而服务器使用私钥来加密和生成签名;
生成签名的形式通常用于对明文,进行签名;防止明文数据被修改,若产生签名,通常就不产生密文。
------------------------------------------------------------------------------------------------------------------
签名和验签也是使用公私钥一一对应的,签名和验证执行效率相对较高,加解密比较耗资源。签名和加解密文没有必然联系;
/// <summary> /// 基于RSA公私钥的加密解密验证算法 /// </summary> public class RSA { public class KeyGenerator { /// <summary> /// 随机生成秘钥(对称算法) /// </summary> /// <param name="key">秘钥(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize,每8个byte是一个字节,注意每种算法支持的KeySize均有差异,实际可通过输出LegalKeySizes来得到支持的值</param> public static void CreateSymmetricAlgorithmKey<T>(out string key, out string iv, int keySize) where T : SymmetricAlgorithm, new() { using (T t = new T()) { t.KeySize = keySize; t.GenerateIV(); t.GenerateKey(); iv = Convert.ToBase64String(t.IV); key = Convert.ToBase64String(t.Key); } } /// <summary> /// 随机生成秘钥(非对称算法) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="publicKey">公钥(Xml格式)</param> /// <param name="privateKey">私钥(Xml格式)</param> /// <param name="provider">用于生成秘钥的非对称算法实现类,因为非对称算法长度需要在构造函数传入,所以这里只能传递算法类</param> public static void CreateAsymmetricAlgorithmKey<T>(out string publicKey, out string privateKey, T provider = null) where T : AsymmetricAlgorithm, new() { if (provider == null) { provider = new T(); } using (provider) { publicKey = provider.ToXmlString(false); privateKey = provider.ToXmlString(true); } } } public class AsymmetricAlgorithmHelper<T> where T : AsymmetricAlgorithm, new() { protected static TResult Execute<TResult>(string key, Func<T, TResult> func) { using (T algorithm = new T()) { algorithm.FromXmlString(key); return func(algorithm); } } /// <summary> /// 按默认规则生成公钥、私钥 /// </summary> /// <param name="publicKey">公钥(Xml格式)</param> /// <param name="privateKey">私钥(Xml格式)</param> public static void Create(out string publicKey, out string privateKey) { KeyGenerator.CreateAsymmetricAlgorithmKey<T>(out publicKey, out privateKey); } } public class RSAHelper : AsymmetricAlgorithmHelper<RSACryptoServiceProvider> { //加密、解密、签名和验证示例代码 //using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider(2048)) //{ // KeyGenerator.CreateAsymmetricAlgorithmKey<RSACryptoServiceProvider>(out string publicKey, out string privateKey, provider); // Console.WriteLine(privateKey); // Console.WriteLine(publicKey); // //测试定义需要加密的字符串 // var test = "abc"; // //执行加密 // var ends = Encrypt.RSA.RSAHelper.Encrypt(publicKey, test, true); // //获得签名 // var sign = Encrypt.RSA.RSAHelper.SignData(privateKey, test, null); // //执行验证 // var verify = Encrypt.RSA.RSAHelper.VerifyData(publicKey, test, sign, null); // //执行解密 // var des = Encrypt.RSA.RSAHelper.Decrypt(privateKey, ends, true); // Console.ReadLine(); //} /// <summary> /// RSA加密 /// </summary> /// <param name="publickey">公钥</param> /// <param name="content">加密前的原始数据</param> /// <param name="fOAEP">如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 System.Security.Cryptography.RSA加密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。</param> /// <returns>加密后的结果(base64格式)</returns> public static string Encrypt(string publickey, string content, bool fOAEP = false) { return Execute(publickey, algorithm => Convert.ToBase64String(algorithm.Encrypt(Encoding.UTF8.GetBytes(content), fOAEP))); } /// <summary> /// RSA解密 /// </summary> /// <param name="privatekey">私钥</param> /// <param name="content">加密后的内容(base64格式)</param> /// <param name="fOAEP">如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 System.Security.Cryptography.RSA加密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。</param> /// <returns></returns> public static string Decrypt(string privatekey, string content, bool fOAEP = false) { return Execute(privatekey, algorithm => Encoding.UTF8.GetString(algorithm.Decrypt(Convert.FromBase64String(content), fOAEP))); } /// <summary> /// RSA签名 /// </summary> /// <param name="privatekey">私钥</param> /// <param name="content">需签名的原始数据(utf-8)</param> /// <param name="halg">签名采用的算法,如果传null,则采用MD5算法</param> /// <returns>签名后的值(base64格式)</returns> public static string SignData(string privatekey, string content, object halg = null) { return Execute(privatekey, algorithm => Convert.ToBase64String(algorithm.SignData(Encoding.UTF8.GetBytes(content), GetHalg(halg)))); } /// <summary> /// RSA验签 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="content">需验证签名的数据(utf-8)</param> /// <param name="signature">需验证的签名字符串(base64格式)</param> /// <param name="halg">签名采用的算法,如果传null,则采用MD5算法</param> /// <returns></returns> public static bool VerifyData(string publicKey, string content, string signature, object halg = null) { return Execute(publicKey, algorithm => algorithm.VerifyData(Encoding.UTF8.GetBytes(content), GetHalg(halg), Convert.FromBase64String(signature))); } private static object GetHalg(object halg) { if (halg == null) { halg = "MD5"; } return halg; } /// <summary> /// 生成公钥、私钥 /// </summary> /// <param name="publicKey">公钥(Xml格式)</param> /// <param name="privateKey">私钥(Xml格式)</param> /// <param name="keySize">要生成的KeySize,支持的MinSize:384 MaxSize:16384 SkipSize:8</param> public static void Create(out string publicKey, out string privateKey, int keySize = 1024) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(keySize); KeyGenerator.CreateAsymmetricAlgorithmKey(out publicKey, out privateKey, provider); } } public class DSAHelper : AsymmetricAlgorithmHelper<DSACryptoServiceProvider> { /// <summary> /// DSA签名 /// </summary> /// <param name="privatekey">私钥</param> /// <param name="content">需签名的原始数据(utf-8)</param> /// <returns>签名后的值(base64格式)</returns> public static string SignData(string privatekey, string content) { return Execute(privatekey, algorithm => Convert.ToBase64String(algorithm.SignData(Encoding.UTF8.GetBytes(content)))); } /// <summary> /// DSA验签 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="content">需验证签名的数据(utf-8)</param> /// <param name="signature">需验证的签名字符串(base64格式)</param> /// <returns></returns> public static bool VerifyData(string publicKey, string content, string signature) { return Execute(publicKey, algorithm => algorithm.VerifyData(Encoding.UTF8.GetBytes(content), Convert.FromBase64String(signature))); } /// <summary> /// 生成公钥、私钥 /// </summary> /// <param name="publicKey">公钥(Xml格式)</param> /// <param name="privateKey">私钥(Xml格式)</param> /// <param name="keySize">要生成的KeySize,支持的MinSize:512 MaxSize:1024 SkipSize:64</param> public static void Create(out string publicKey, out string privateKey, int keySize = 1024) { DSACryptoServiceProvider provider = new DSACryptoServiceProvider(keySize); KeyGenerator.CreateAsymmetricAlgorithmKey(out publicKey, out privateKey, provider); } } }