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);
到达胜利之前无法回头!