08.加密解密Encrypt

1. 加密解密简述

对称加密

对称加密的思路非常简单,就是含有一个称为密钥的东西,在消息发送前使用密钥对消息进行加密,在对方收到消息之后,使用相同的密钥进行解密。根据密钥来产生加密后的消息(密文)的这一加工过程,由加密算法来完成

对称加密存在问题:如何确保密钥安全

非对称加密

非对称加密的接收者和发送者都持有两个密钥,一个是对外公开的,称为公钥,一个是自行保管的,称为私钥。非对称加密的规则是由A的公钥加密的消息,只能由A的私钥进行解密;由A的私钥加密的消息只能由A的公钥解密

2. MD5加密,验证

MD5不可逆加密:原文通过加密得到密文,密文不可解密为原文

相同的原文加密的结果一致文件加密(文件摘要)无论文件多大,都能根据文件内容产生一个32位的字符串

应用场景:密码加密,文件防篡改

2.1 示例一:简易方式

示例一:一般加解密

MD5帮助类

using System;
using System.Security.Cryptography;
using System.Text;

namespace jjm1.Util
{
    public static class MD5Helper
    {
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">需要加密的内容</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string MD5Encrypt(string input, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            MD5 md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(encoding.GetBytes(input));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }

        /// <summary>
        /// MD5验证传入的密文是否经由传入的明文加密所得
        /// </summary>
        /// <param name="input">明文</param>
        /// <param name="hash">密文</param>
        /// <returns>密文是否由明文加密所得</returns>
        public static bool MD5Verify(string input, string hash, Encoding encoding = null)
        {
            string hashOfInput = MD5Encrypt(input, encoding);
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;
            return 0 == comparer.Compare(hashOfInput, hash);
        }
    }
}

测试示例

using jjm1.Util;
using System;

namespace jjm1
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "a123";

            Console.Write(MD5Helper.MD5Encrypt(text));
            Console.Write(MD5Helper.MD5Verify(text, "80c9ef0fb86369cd25f90af27ef53a9e"));
        }
    }
}

示例二:MD5加盐(追加额外标识)

MD5帮助类,定义了一个标识(增加防暴力概率)

using System;
using System.Security.Cryptography;
using System.Text;

namespace jjm1.Util
{
    public static class MD5Helper
    {
        const string key = "ka54a";

        public static string MD5Encrypt(string input, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            MD5 md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(encoding.GetBytes(input + key));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }

        public static bool MD5Verify(string input, string hash, Encoding encoding = null)
        {
            string hashOfInput = MD5Encrypt(input, encoding);
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;
            return 0 == comparer.Compare(hashOfInput, hash);
        }
    }
}

测试示例

using jjm1.Util;
using System;

namespace jjm1
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "a123";

            Console.Write(MD5Helper.MD5Encrypt(text));
            Console.Write(MD5Helper.MD5Verify(text, "0c084adb3b6696706c57e9159112bc8a"));
        }
    }
}

2.2 示例二:其它方式

MD5帮助类,提供文本加密,文件加密,可增加标识

using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace jjm2.Utils
{
    public class MD5Helper
    {
        /// <summary>
        /// MD5内容加密
        /// </summary>
        /// <param name="source">加密数据</param>
        /// <param name="length">长度【16,32】</param>
        /// <returns></returns>
        public static string MD5Encrypt(string source, int length = 32)
        {
            if (string.IsNullOrEmpty(source)) return string.Empty;
            HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm;
            byte[] bytes = Encoding.UTF8.GetBytes(source);  // 这里需要区别编码的
            byte[] hashValue = provider.ComputeHash(bytes);
            StringBuilder sb = new StringBuilder();
            switch (length)
            {
                case 16:    // 16位密文是32位密文的9到24位字符
                    for (int i = 4; i < 12; i++)
                    {
                        sb.Append(hashValue[i].ToString("x2"));
                    }
                    break;
                case 32:
                    for (int i = 0; i < 16; i++)
                    {
                        sb.Append(hashValue[i].ToString("x2"));
                    }
                    break;
                default:
                    for (int i = 0; i < hashValue.Length; i++)
                    {
                        sb.Append(hashValue[i].ToString("x2"));
                    }
                    break;
            }
            return sb.ToString();
        }

        /// <summary>
        /// MD5效验
        /// </summary>
        /// <param name="input">原文</param>
        /// <param name="hash">密文</param>
        /// <returns></returns>
        public static bool MD5Verify(string input, string hash)
        {
            string hashOfInput = MD5Encrypt(input);
            return hashOfInput == hash;
        }

        /// <summary>
        /// 获取文件的MD5摘要
        /// </summary>
        /// <param name="fileName">文件全路径</param>
        /// <returns></returns>
        public static string AbstractFile(string fileName)
        {
            using (FileStream file = new FileStream(fileName, FileMode.Open))
            {
                return AbstractFile(file);
            }
        }

        /// <summary>
        /// 根据stream获取文件摘要
        /// </summary>
        /// <param name="stream">文件流</param>
        /// <returns></returns>
        public static string AbstractFile(Stream stream)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(stream);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }
    }
}

测试示例

using jjm2.Utils;
using System;

namespace jjm2
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "a123";
            Console.Write(MD5Helper.MD5Encrypt(text));
            Console.Write(MD5Helper.MD5Verify(text, "80c9ef0fb86369cd25f90af27ef53a9e"));

            string filePath = "X:\\1.txt";
            Console.Write(MD5Helper.AbstractFile(filePath));
        }
    }
}

3. SHA1加密,验证

3.1 示例一:简易方式

using System;
using System.Security.Cryptography;
using System.Text;

namespace jjm1.Util
{
    public class SHA1Helper
    {
        /// <summary>
        /// SHA1加密
        /// </summary>
        public static string SHA1Encrypt(string input, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            SHA1 sha1 = SHA1.Create();
            byte[] data = sha1.ComputeHash(encoding.GetBytes(input));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }
        /// <summary>
        /// 验证
        /// </summary>
        /// <returns></returns>
        public static bool SHA1Verify(string input, string hash, Encoding encoding = null)
        {
            string hashOfInput = SHA1Encrypt(input, encoding);
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;
            return 0 == comparer.Compare(hashOfInput, hash);
        }
    }
}
using jjm1.Util;
using System;

namespace jjm1
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "a123";

            Console.WriteLine(SHA1Helper.SHA1Encrypt(text));
            Console.WriteLine(SHA1Helper.SHA1Verify(text, "76af7efae0d034d1e3335ed1b90f24b6cadf2bf1"));
        }
    }
}

4. Des加密,解密

Des对称可逆加密:原文通过密钥加密,密文通过密钥解密

对称加密:加密解密都是同一个密钥

4.1 示例一:简易方式

DES帮助类

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace jjm1.Util
{
    public static class DESHelper
    {
        /// <summary>
        /// DES 加密 注意:密钥必须为8位
        /// </summary>
        /// <param name="inputString">待加密字符串</param>
        /// <param name="encryptKey">密钥</param>
        /// <returns>加密后的字符串</returns>
        public static string DesEncrypt(string inputString, string encryptKey)
        {
            byte[] byKey = null;
            byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
            byKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Encoding.UTF8.GetBytes(inputString);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    return Convert.ToBase64String(ms.ToArray());
                }
            }
        }

        /// <summary>
        /// DES 解密 注意:密钥必须为8位
        /// </summary>
        /// <param name="inputString">待解密字符串</param>
        /// <param name="decryptKey">密钥</param>
        /// <returns>解密后的字符串</returns>
        public static string DesDecrypt(string inputString, string decryptKey)
        {
            byte[] byKey = null;
            byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
            byte[] inputByteArray = new Byte[inputString.Length];
            byKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8));
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            inputByteArray = Convert.FromBase64String(inputString);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
        }
    }
}

测试示例

using jjm1.Util;
using System;

namespace jjm1
{
    class Program
    {
        static void Main(string[] args)
        {
            string key = "wyg@1024";
            string text = "a123";

            Console.WriteLine(DESHelper.DesEncrypt(text, key));
            Console.WriteLine(DESHelper.DesDecrypt("5/hnclmUQNc=", key));
        }
    }
}

4.2 示例二:其它方式

DES帮助类

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace jjm2.Utils
{
    public class DESHelper
    {
        /// <summary>
        /// DES 加密
        /// </summary>
        /// <param name="text">需要加密的值</param>
        /// <returns>加密后的结果</returns>
        public static string Encrypt(string text, string key)
        {
            byte[] _rgbKey = ASCIIEncoding.ASCII.GetBytes(key.Substring(0, 8));
            byte[] _rgbIV = ASCIIEncoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));

            DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateEncryptor(_rgbKey, _rgbIV), CryptoStreamMode.Write);
                StreamWriter sWriter = new StreamWriter(crypStream);
                sWriter.Write(text);
                sWriter.Flush();
                crypStream.FlushFinalBlock();
                memStream.Flush();
                return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="encryptText"></param>
        /// <returns>解密后的结果</returns>
        public static string Decrypt(string encryptText, string key)
        {
            byte[] _rgbKey = ASCIIEncoding.ASCII.GetBytes(key.Substring(0, 8));
            byte[] _rgbIV = ASCIIEncoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));

            DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();
            byte[] buffer = Convert.FromBase64String(encryptText);

            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateDecryptor(_rgbKey, _rgbIV), CryptoStreamMode.Write);
                crypStream.Write(buffer, 0, buffer.Length);
                crypStream.FlushFinalBlock();
                return ASCIIEncoding.UTF8.GetString(memStream.ToArray());
            }
        }
    }
}

测试使用

using jjm2.Utils;
using System;

namespace jjm2
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "a123";
            string key = "1234567a";
            Console.WriteLine(DESHelper.Encrypt(text, key));
            Console.WriteLine(DESHelper.Decrypt("v3/jktaVX+8=", key));
        }
    }
}

5. RSA非对称可逆加密

应用场景

公开加密KEY时,A用户知道加密KEY,B用于知道解密KEY,那么A用户就可以发送一封加密的内容给B用户,内容只有B用户能看得懂,其他人截获了也没有解密KEY也看不懂,保证了数据的安全性

公开解密KEY时,A用户知道加密KEY,B用于知道解密KEY,那么A用户发布了一份文章,只有知道解密KEY的才可以看懂

5.1 示例一:简易版本

Rsa帮助类

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace MyEncrypt
{
    /// <summary>
    /// RSA ECC
    /// </summary>
    public class RsaEncrypt
    {
        /// <summary>
        /// 获取加密/解密对
        /// </summary>
        /// <returns></returns>
        public static KeyValuePair<string, string> GetKeyPair()
        {
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            string publicKey = RSA.ToXmlString(false);
            string privateKey = RSA.ToXmlString(true);
            return new KeyValuePair<string, string>(publicKey, privateKey);
        }

        /// <summary>
        /// 加密:内容+加密key
        /// </summary>
        public static string Encrypt(string content, string encryptKey)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(encryptKey);
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] DataToEncrypt = ByteConverter.GetBytes(content);
            byte[] resultBytes = rsa.Encrypt(DataToEncrypt, false);
            return Convert.ToBase64String(resultBytes);
        }

        /// <summary>
        /// 解密  内容+解密key
        /// </summary>
        public static string Decrypt(string content, string decryptKey)
        {
            byte[] dataToDecrypt = Convert.FromBase64String(content);
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(decryptKey);
            byte[] resultBytes = RSA.Decrypt(dataToDecrypt, false);
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            return ByteConverter.GetString(resultBytes);
        }


        /// <summary>
        /// 可以合并在一起的,每次产生一组新的密钥
        /// </summary>
        /// <param name="content"></param>
        /// <param name="encryptKey">加密key</param>
        /// <param name="decryptKey">解密key</param>
        /// <returns>加密后结果</returns>
        private static string Encrypt(string content, out string publicKey, out string privateKey)
        {
            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
            publicKey = rsaProvider.ToXmlString(false);
            privateKey = rsaProvider.ToXmlString(true);

            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] DataToEncrypt = ByteConverter.GetBytes(content);
            byte[] resultBytes = rsaProvider.Encrypt(DataToEncrypt, false);
            return Convert.ToBase64String(resultBytes);
        }
    }
}

测试使用

KeyValuePair<string, string> encryptDecrypt = RsaEncrypt.GetKeyPair();
string rsaEn1 = RsaEncrypt.Encrypt("net", encryptDecrypt.Key);
string rsaDe1 = RsaEncrypt.Decrypt(rsaEn1, encryptDecrypt.Value);
posted @ 2022-03-05 11:23  位永光  阅读(339)  评论(0编辑  收藏  举报