个人理解c#对称加密 非对称加密 散列算法的应用场景

时间:2022-10-12 15:15:23

c#类库默认实现了一系列加密算法在System.Security.Cryptography; 命名空间下

对称加密

通过同一密匙进行加密和解密。往往应用在内部数据传输情况下。比如公司a程序 和B程序 。a程序要给B程序发送数据 但是为了防止明文发送 数据被窃取。那么我就定了一个协议传输的数据的byte字节都统一+1  而接收数据的情况下将Byte字节统一-1 然后就能获得正确的 数据(当然这个是一个简单的加密) ,真正应用的加密肯定比这个复杂很多

非对称加密

传输数据的双方有各自的公钥和私钥  公钥对外公开 私钥自己保留,当像B用户发送数据 使用B用户的公钥进行加密 加密的数据只有B用户的私钥可以解密 那么如果在传输过程中 如果消息被截取 那么也破解不了

比如支付操作 a用户输入银行卡 卡号和密码 进行支付 那么在传输过程中 如果别抓包截取数据。是很危险的 。那么统一在客户端将参数信息 通过服务器提供的公钥进行加密。如果在传输过程中被截取

我们都知道https请求在传输过程中数据是安全的

https请求客户端需要安装证书 证书就类似公钥和私钥 客户端发起请求获得服务器的公钥 并将自己的公钥发送给服务器。  在传输过程中都使用双方的公钥进行加密传输 保证了数据的安全性

https请求与普通请求的区别是 https是长连接 同时增加了 双方公钥交换的握手

列子

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace SecureTranferTest
{
    class Program
    {
        /// <summary>
        /// 安妮的私匙
        /// </summary>
        public static System.Security.Cryptography.CngKey anlikey = null;

        //安妮的公钥
        public static byte[] anlipulicKey = null;
        //鲍勃的私匙
        public static System.Security.Cryptography.CngKey bobkey = null;
        public static byte[] bobpulicKey = null;

        static void Main(string[] args)
        {
            CreateKey();
            AnliSendMessage("今天天气很好");//安妮开始向bob发送消息
            AnliSendMessage("啦啦啦");//安妮开始向bob发送消息
            Console.ReadKey();
        }

        public static void CreateKey()
        {

            //以ECDsaP256创建私钥
            anlikey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
            //根据私钥生成公钥
            anlipulicKey = anlikey.Export(CngKeyBlobFormat.EccPublicBlob);
            //以ECDsaP256创建私钥
            bobkey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
            //根据公钥获得私钥
            bobpulicKey = bobkey.Export(CngKeyBlobFormat.EccPublicBlob);

        }

        public  static void AnliSendMessage(string message)
        {
            byte[] rowData = Encoding.UTF8.GetBytes(message); //将发送消息转换成二进制格式
            //同annli的私匙生成一个新的随机的密钥对
            using (ECDiffieHellmanCng cng = new ECDiffieHellmanCng(anlikey))
            {
                //通过bob的公钥byte[]获得一个cngKey密钥对象
                using (CngKey bobkey = CngKey.Import(bobpulicKey, CngKeyBlobFormat.EccPublicBlob))
                {
                    //通过anli的密钥对与bob的公钥生成一个对称密钥
                    var sumKey = cng.DeriveKeyMaterial(bobkey);
                    //创建一个对称加密和解密的(AEC)高级算法实现
                    using (var aes = new AesCryptoServiceProvider())
                    {
                        aes.Key = sumKey; //设置对称加密密钥
                        aes.GenerateIV();
                        //生成对称加sh密对象
                        using (ICryptoTransform encryptor = aes.CreateEncryptor())
                        {
                            using (MemoryStream ms = new MemoryStream())
                            {
                                //定义一个加密转换流
                                var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
                                //写入加密初始化向量(IV)
                                ms.Write(aes.IV, , aes.IV.Length);
                                //写如传递数据
                                cs.Write(rowData,, rowData.Length);
                                cs.Close();//使用完后必须关闭 否则会丢失数据
                               var data= ms.ToArray();
                                //安妮向鲍勃发送加密数据消息 加密数据的二进制数据()
                                Console.WriteLine("安妮向鲍勃发送加密数据消息 加密数据的二进制数据");
                                BobReceivesData(data);
                            }
                            aes.Clear();
                        }
                    }
                }
            }
        }

        //Bob接收信息
        public static void BobReceivesData(byte[] data)
        {
            Console.WriteLine("鲍勃接收到 并开始解密");
            byte[] rowData = null;
            //首先读取未加密的初始化向量(IV) 在data里面
            //1.通过对称加密高级算法实现AesCryptoServiceProvider 获得IV的长度
            using (var aes = new AesCryptoServiceProvider())
            {
                ;//他的操作块二进制长度转换成byte存储的十进制长度
                byte[] ivdata = new byte[ivlength];
                Array.Copy(data, ivdata, ivlength);
                //同bob的私匙生成一个新的随机的密钥对
                using (ECDiffieHellmanCng cng = new ECDiffieHellmanCng(bobkey))
                {
                    //通过anni的公钥byte[]获得一个cngKey密钥对象
                    using (CngKey anikey = CngKey.Import(anlipulicKey, CngKeyBlobFormat.EccPublicBlob))
                    {
                        //通过anli的密钥对与bob的公钥生成一个对称密钥
                        var sumKey = cng.DeriveKeyMaterial(anikey);
                        aes.Key = sumKey; //设置对称加密密钥
                        aes.IV = ivdata;
                        using (ICryptoTransform decryptor = aes.CreateDecryptor())
                        using (MemoryStream me = new MemoryStream())
                        {
                           //定义一个加密转换流
                            var cs = new CryptoStream(me, decryptor, CryptoStreamMode.Write);
                            cs.Write(data, ivlength, data.Length - ivlength);//将加密信息进行解密
                            cs.Close();//一定要关闭 否则将丢失最后一位数据
                            rowData = me.ToArray();
                            Console.WriteLine("解密成功 信息为:");
                            Console.WriteLine(Encoding.UTF8.GetString(rowData));
                        }
                    }
                }
            }

        }

    }
}

散列算法

同样的字符串 通过散列算法 算出唯一的散列值。 比如md5加密

应用场景 接口防止参数被篡改 参数用md5加密将md5散列算出的字符串提交到服务器 如果服务器也通过散列参数的字符串跟提交的一样 那么代表没有呗篡改