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);
            }
        }
    }

 

posted @ 2019-11-24 13:17  soleds  阅读(289)  评论(0编辑  收藏  举报