• 探讨.NET Core中实现AES加密和解密以及.NET Core为我们提供了什么方便!


    前言

    对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣,知其所以然那就达不到了,利用AES加密更加安全,上一篇园友又提出,所以借着这个机会刚好用到加密和解密,同时我也已将项目中DES加密已替换为AES,在这里介绍一下。

    AES加密介绍

    高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。它要求区块大小必须为128位,而密钥长度则可以为128、196、256位。基于此我们来实现.NET Framework版本和.NET Core版本。

    在.NET Framework中实现AES加密和解密

    AES加密

            public static string EncryptText(string input, string key)
            {
    
                byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
                byte[] passwordBytes = Encoding.UTF8.GetBytes(key);
    
                passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
    
                byte[] bytesEncrypted = AESEncryptBytes(bytesToBeEncrypted, passwordBytes);
    
                string result = Convert.ToBase64String(bytesEncrypted);
    
                return result;
            }
            public static byte[] AESEncryptBytes(byte[] bytesToBeEncrypted, byte[] passwordBytes)
            {
                byte[] encryptedBytes = null;
    
                var saltBytes = new byte[9] { 13, 34, 27, 67, 189, 255, 104, 219 ,122};
    
                using (var ms = new MemoryStream())
                {
                    using (var AES = new RijndaelManaged())
                    {
                        AES.KeySize = 256;
                        AES.BlockSize = 128;
    
                        var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                        AES.Key = key.GetBytes(32);
                        AES.IV = key.GetBytes(16);
    
                        AES.Mode = CipherMode.CBC;
    
                        using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), 
                            CryptoStreamMode.Write))
                        {
                            cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                            cs.Close();
                        }
    
                        encryptedBytes = ms.ToArray();
                    }
                }
    
                return encryptedBytes;
            }

    上述盐字节必须为至少8个字节,否则报错如下:

    AES解密

            public static string DecryptText(string input, string key)
            {
                byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
    
                byte[] passwordBytes = Encoding.UTF8.GetBytes(key);
    
                passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
    
                byte[] bytesDecrypted = AESDecryptBytes(bytesToBeDecrypted, passwordBytes);
    
                string result = Encoding.UTF8.GetString(bytesDecrypted);
    
                return result;
            }
            public static byte[] AESDecryptBytes(byte[] bytesToBeDecrypted, byte[] passwordBytes)
            {
                byte[] decryptedBytes = null;
    
                var saltBytes = new byte[9] { 13, 34, 27, 67, 189, 255, 104, 219 ,122};
    
                using (var ms = new MemoryStream())
                {
                    using (var AES = new RijndaelManaged())
                    {
                        AES.KeySize = 256;
                        AES.BlockSize = 128;
    
                        var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                        AES.Key = key.GetBytes(32);
                        AES.IV = key.GetBytes(16);
    
                        AES.Mode = CipherMode.CBC;
    
                        using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                            cs.Close();
                        }
    
                        decryptedBytes = ms.ToArray();
                    }
                }
    
                return decryptedBytes;
            }

    测试如下:

                var encrptText = "Jeffcky";
                var key = Guid.NewGuid().ToString("N");
                Console.WriteLine("加密前内容:" + encrptText);
                var input = EncryptText(encrptText,key);
                Console.WriteLine("加密后字符串为:" + input);
                var text = DecryptText(input, key);
                Console.WriteLine("解密后内容:" + text);

    上述利用 RijndaelManaged 来实例化AES,最终该类继承自 SymmetricAlgorithm 对称算法类。通过我们实例化一个 Rfc2898DeriveBytes 来对密钥密钥和盐循环迭代1000次从而实现加密,同理解密反向操作。

    在.NET Core中实现AES加密和解密

    在.NET Core中对于对称加密统一接口不再利用不同类而实现,对于非对称加密当然和对称加密接口就不同了,创建起来格外方便,不再是实例化对应的类,如下

                //对称加密
                var aes = Aes.Create();
                var tripleDES = TripleDES.Create();
    
                //非对称加密
                var rsa = RSA.Create();

    由下可以看出直接定义了一个静态方法来创建加密

        public abstract class Aes : SymmetricAlgorithm
        {
            protected Aes();
    
            public override KeySizes[] LegalBlockSizes { get; }
            public override KeySizes[] LegalKeySizes { get; }
    
            public static Aes Create();
        }
        public abstract class RSA : AsymmetricAlgorithm
        {
            protected RSA();
    
            public static RSA Create();
            ...
        }

    当然命名空间依然是 System.Security.Cryptography 。我们直接看实现。

    AES加密

            public static string AESEncrypt(string input, string key)
            {
                var encryptKey = Encoding.UTF8.GetBytes(key);
    
                using (var aesAlg = Aes.Create())
                {
                    using (var encryptor = aesAlg.CreateEncryptor(encryptKey, aesAlg.IV))
                    {
                        using (var msEncrypt = new MemoryStream())
                        {
                            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor,
                                CryptoStreamMode.Write))
    
                            using (var swEncrypt = new StreamWriter(csEncrypt))
                            {
                                swEncrypt.Write(input);
                            }
    
                            var iv = aesAlg.IV;
    
                            var decryptedContent = msEncrypt.ToArray();
    
                            var result = new byte[iv.Length + decryptedContent.Length];
    
                            Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
                            Buffer.BlockCopy(decryptedContent, 0, result,
                                iv.Length, decryptedContent.Length);
    
                            return Convert.ToBase64String(result);
                        }
                    }
                }
            }

    AES解密(修改:2019-11-13)

            public static string AESDecrypt(string input, string key)
            {
                var fullCipher = Convert.FromBase64String(input);
    
                var iv = new byte[16];
                var cipher = new byte[fullCipher.Length-iv.Length];
     
                Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
                Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, fullCipher.Length- iv.Length);
                var decryptKey = Encoding.UTF8.GetBytes(key);
    
                using (var aesAlg = Aes.Create())
                {
                    using (var decryptor = aesAlg.CreateDecryptor(decryptKey, iv))
                    {
                        string result;
                        using (var msDecrypt = new MemoryStream(cipher))
                        {
                            using (var csDecrypt = new CryptoStream(msDecrypt,
                                decryptor, CryptoStreamMode.Read))
                            {
                                using (var srDecrypt = new StreamReader(csDecrypt))
                                {
                                    result = srDecrypt.ReadToEnd();
                                }
                            }
                        }
    
                        return result;
                    }
                }
            }

    测试如下:

                var key = Guid.NewGuid().ToString("N");
                var name = "Jeffcky";
                Console.WriteLine($"加密字符串为{name}");
                var encryptStr = AESEncrypt(name, key);
                Console.WriteLine($"加密后结果为:{encryptStr}");
                var decryptStr = AESDecrypt(encryptStr, key);
                Console.WriteLine($"解密后字符串为{decryptStr}");

     

    总结

    在.NET Core中实现对称加密和非对称加密无论是实现还是创建都更加简洁,之前也并未去具体了解加密和解密相关内容,借此机会稍微了解下对应的加密所以花了一点时间。对于AES加密还没怎么具体去了解内部原理,只是参照了一点资料,以此作为备忘录,目前.NET Core仅支持AES、TripleDES、RSA。希望对在.NET Core项目中需要实现加密的童鞋提供一点帮助。接下来有时间我们继续巩固下线程基础知识,敬请期待,待我学习完毕再来更新博客和大家一起分享。

  • 相关阅读:
    堆的应用
    1155 Heap Paths (30 分)(堆+dfs遍历)
    1099 Build A Binary Search Tree (30 分)(查找二叉树)
    1064 Complete Binary Search Tree (30 分)(二叉查找树)
    1043 Is It a Binary Search Tree (25 分)(二叉查找树)
    1053 Path of Equal Weight (30 分)(树的遍历)
    1106 Lowest Price in Supply Chain (25 分)(树的遍历)
    洛谷P1031均分纸牌(贪心平均数)
    洛谷P1045麦森数(高精度乘法)
    洛谷P1255数楼梯(大数,高精度加法)
  • 原文地址:https://www.cnblogs.com/CreateMyself/p/6771652.html
Copyright © 2020-2023  润新知