NET中各种加密解密方法

Posted li150dan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NET中各种加密解密方法相关的知识,希望对你有一定的参考价值。

    /// <summary>
    /// 各种加密解密方法 
    /// </summary>
    public static class EncryptDemo
    {     
        /// <summary>
        /// AES对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB),这三种的区别,主要来自于密钥的长度,16位密钥=128位,24位密钥=192位,32位密钥=256位
        /// 检验密钥是否有效长度【16|24|32】
        /// </summary>
        /// <param name="key">密钥</param>
        /// <returns>bool</returns>
        private static bool AesCheckKey(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                return false;
            if (16.Equals(key.Length) || 24.Equals(key.Length) || 32.Equals(key.Length))
                return true;
            else
                return false;
        }
            
        #region 参数是string类型的
        /// <summary>
        ///  AES加密 参数:string
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="key">密钥</param>     
        /// <param name="model">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>加密后的字符串</returns>
        public static string AesEncrypt(string source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null)
        {
            if (string.IsNullOrWhiteSpace(source)) return null;
            if (!AesCheckKey(key)) return source;
            if (encoding == null) encoding = Encoding.UTF8;
            using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
            {              
                aesProvider.Key = encoding.GetBytes(key);
                aesProvider.Mode = model;
                aesProvider.Padding = padding;
                //aesProvider.KeySize = 128;
                //aesProvider.BlockSize = 128;             
                using (ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor())
                {
                    byte[] toEncryptArray = encoding.GetBytes(source);
                    byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                    aesProvider.Clear();
                    return Convert.ToBase64String(resultArray, 0, resultArray.Length);
                }
            }          
        }

        /// <summary>
        ///  AES解密 参数:string
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="key">密钥</param>     
        /// <param name="model">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>解密后的字符串</returns>
        public static string AesDecrypt(string source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null)
        {
            if (string.IsNullOrWhiteSpace(source)) return null;
            if (!AesCheckKey(key)) return source;
            if (encoding == null) encoding = Encoding.UTF8;
            using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
            {
                aesProvider.Key = encoding.GetBytes(key);
                aesProvider.Mode = model;
                aesProvider.Padding = padding;
                //aesProvider.KeySize = 128;
                //aesProvider.BlockSize = 128;      
                using (ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor())
                {
                    byte[] toEncryptArray = Convert.FromBase64String(source);                   
                    byte[] resultArray = cryptoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                    aesProvider.Clear();
                    return encoding.GetString(resultArray);
                }
            }     
        }
        #endregion

        #region 参数是byte[]类型的
        /// <summary>  
        /// AES加密 参数:byte[] 
        /// </summary>  
        /// <param name="source">源字符字节组</param>
        /// <param name="key">密钥</param>     
        /// <param name="model">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>加密后的字符字节组</returns>  
        public static byte[] AesEncrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null)
        {
            if (source == null) return null;
            if (!AesCheckKey(key)) return source;
            if (encoding == null) encoding = Encoding.UTF8;
            byte[] bKey = encoding.GetBytes(key);       
            byte[] cryptograph = null; // 加密后的密文  
            Rijndael Aes = Rijndael.Create();
            Aes.Key = bKey;          
            //开辟一块内存流  
            using (MemoryStream Memory = new MemoryStream())
            {
                //把内存流对象包装成加密流对象  
                using (CryptoStream Encryptor = new CryptoStream(Memory, Aes.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    //明文数据写入加密流  
                    Encryptor.Write(source, 0, source.Length);
                    Encryptor.FlushFinalBlock();
                    cryptograph = Memory.ToArray();
                }
            }
            return cryptograph;
        }

        /// <summary>  
        /// AES解密  参数:byte[] 
        /// </summary>  
        /// <param name="source">源字符字节组</param>
        /// <param name="key">密钥</param>     
        /// <param name="model">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>解密后的字符字节组</returns>  
        public static byte[] AesDecrypt(byte[] source, string key, CipherMode model = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7, Encoding encoding = null)
        {
            if (source == null) return null;
            if (!AesCheckKey(key)) return source;
            if (encoding == null) encoding = Encoding.UTF8;
            byte[] bKey = encoding.GetBytes(key);      
            byte[] original = null; // 解密后的明文  
            Rijndael Aes = Rijndael.Create();
            //开辟一块内存流,存储密文  
            using (MemoryStream Memory = new MemoryStream(source))
            {
                //把内存流对象包装成加密流对象  
                using (CryptoStream Decryptor = new CryptoStream(Memory, Aes.CreateDecryptor(bKey, null), CryptoStreamMode.Read))
                {
                    //明文存储区  
                    using (MemoryStream originalMemory = new MemoryStream())
                    {
                        byte[] Buffer = new byte[1024];
                        int readBytes = 0;
                        while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
                        {
                            originalMemory.Write(Buffer, 0, readBytes);
                        }
                        original = originalMemory.ToArray();
                    }
                }
            }
            return original;
        }
        #endregion        

        /// <summary>
        /// 对字符串SHA1加密
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>加密后的十六进制字符串</returns>
        public static string Sha1Encrypt(string source, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;

            // 第一种方式
            byte[] byteArray = encoding.GetBytes(source);
            using (HashAlgorithm hashAlgorithm = new SHA1CryptoServiceProvider())
            {
                byteArray = hashAlgorithm.ComputeHash(byteArray);
                StringBuilder stringBuilder = new StringBuilder(256);
                foreach (byte item in byteArray)
                {
                    stringBuilder.AppendFormat("{0:x2}", item);
                }
                hashAlgorithm.Clear();
                return stringBuilder.ToString();
            }

            //// 第二种方式
            //using (SHA1 sha1 = SHA1.Create())
            //{
            //    byte[] hash = sha1.ComputeHash(encoding.GetBytes(source));
            //    StringBuilder stringBuilder = new StringBuilder();
            //    for (int index = 0; index < hash.Length; ++index)
            //        stringBuilder.Append(hash[index].ToString("x2"));
            //    sha1.Clear();
            //    return stringBuilder.ToString();
            //}
        }

        /// <summary>
        /// 对字符串MD5加密
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="encoding">编码类型</param>
        /// <returns>加密后的十六进制字符串</returns>
        public static string Md5Encrypt(string source, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;

            byte[] byteArray = encoding.GetBytes(source);
            using (HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider())
            {
                byteArray = hashAlgorithm.ComputeHash(byteArray);
                StringBuilder stringBuilder = new StringBuilder();
                foreach (byte item in byteArray)
                {
                    stringBuilder.AppendFormat("{0:x2}", item);
                }
                hashAlgorithm.Clear();
                return stringBuilder.ToString();
            }
        }
    }

AES加密方式中关于PKCS5Padding与PKCS7Padding的区别

在PKCS5Padding中,明确定义Block的大小是8位,而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间(块长度超出255的尚待研究),填充值的算法都是一样的:

value=k - (l mod k) ,K=块大小,l=数据长度,如果l=8, 则需要填充额外的8个byte的8

在.net中,例如TripleDESCryptoServiceProvider ,默认BlockSize=64bits=8bytes,所以在这种情况下在PKCS5Padding=PKCS7Padding。

如果在C#中自己定义了一个不是64bits的加密块大小,同时使用PKCS7Padding,那么在java中使用JDK标准的PKCS5Padding就不能解密了。

以上是关于NET中各种加密解密方法的主要内容,如果未能解决你的问题,请参考以下文章

ASP.net MVC 代码片段问题中的 Jqgrid 实现

小程序各种功能代码片段整理---持续更新

为 asp.net 存储密钥、密码的安全方法

在 ASP.NET 中加密 cookie

Asp.Net Core Data Protection API 用于保护数据库中的数据

vbscript 各种自定义代码片段 - 有关详细信息,请参阅注释