子曰:“工欲善其事,必先利其器”
github地址:https://github.com/redAntCpp/CSharpTools
加密解密在日常开发中也是经常用到,尤其是在写登录功能时,对用户的密码进行加密,有时,对信息安全要求较高时,也需要对传输的数据进行加密,然后本地解密后得到相应的报文,然后继续进行业务。比如银行的金额,医院的患者病历信息等。
简单的加密方式介绍
加密分为:对称加密和非对称加密。
对称加密就是,信息发送方跟信息接收方同时拥有相同的秘钥,发送方使用秘钥对明文加密,而接收方也使用这个秘钥进行解密。
详细介绍参考百度百科或者wiki百科,这里不再赘述,百度百科:对称加密
非对称加密:对称加密要求发送跟接收双方都必须持有相同的秘钥,对秘钥的保管要求较高。如果秘钥被非发送跟接收双方获得,那么通信的双方的信息安全就得不到保障。而非对称加密,则可以做到,双方可以持有不一样的秘钥,也可以完成通信,
- 公钥: 可以公开的秘钥,用来对明文进行加密。由发送方持有。
- 私钥:接收者持有的秘钥,不予公开,用来对明文进行解密。由接收方持有。
从逻辑上看,只要私钥保管好,就可以得到安全的信息通信。
当然,以上只是一个简单的介绍,有兴趣的可以参考百度百科或者wiki百科的详细介绍,百度百科非对称加密
如果对安全性要求较高,上述两种方式也可以组合起来使用,称为混合加密,通常的做法是,使用对称加密对重要信息进行加密,使用非对称加密,对信息体本身进行加密。
本工具,实现了对称加密算法:3DES,非对称加密:RSA,以及信息摘要算法:MD5加密算法。(注意,我不认为MD5是一个严格意义上的加密,因为原则上它不应该被解密。可以参考百度百科)。
使用工具集
using System.Security.Cryptography;
加密类
3DES
//----------------------------------3DES BEGIN----------------------------------------------------
/// <summary>
/// 3DES加密算法
/// </summary>
/// <param name="strContent">要加密的文本</param>
/// <param name="strKey">对称密钥</param>
/// <param name="encoding">编码方式,默认default</param>
/// <returns></returns>
public static string T_DESEEncrypt(string strContent, string strKey, Encoding encoding)
{
TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();
DES.Key = hashMD5.ComputeHash(encoding.GetBytes(strKey));
DES.Mode = CipherMode.ECB;
//创建加密器
ICryptoTransform DESEncrypt = DES.CreateEncryptor();
byte[] Buffer = encoding.GetBytes(strContent);
//转为64为的字符串
return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
}
RSA
此加密方式需要使用较多的辅助方法,首先,加密前,需要将公钥、私钥生成,然后在加密解密时使用,这里先假设已经有了公钥:
//---------------------------------------RSA BEGIN--------------------------------------------
//RSA加密算法,第一个参数为公钥,第二个参数为要加密的数据
public static string RSAEncrypt(string PublicKey, string EncryptString)
{
string str2;
try
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(PublicKey);
byte[] bytes = Encoding.Default.GetBytes(EncryptString);
str2 = Convert.ToBase64String(provider.Encrypt(bytes, false));
}
catch (Exception exception)
{
throw exception;
}
return str2;
}
MD5(64位)
public static string MD5EncryptFor64(string strContent)
{
MD5 md5 = MD5.Create(); //实例化一个md5对像
// 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(strContent));
return Convert.ToBase64String(s);
}
解密类
3DES
/// <summary>
/// 3DES解密
/// </summary>
/// <param name="strContent">被加密文本</param>
/// <param name="strKey">加密秘钥</param>
/// <param name="encoding">编码方式</param>
/// <returns></returns>
public static string T_DESDecrypt(string strContent, string strKey, Encoding encoding)
{
TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();
DES.Key = hashMD5.ComputeHash(encoding.GetBytes(strKey));
DES.Mode = CipherMode.ECB;
ICryptoTransform DESEncrypt = DES.CreateDecryptor();
byte[] Buffer = Convert.FromBase64String(strContent);
return encoding.GetString(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
}
RSA
public static string RSADecrypt(string PrivateKey, string DecryptString)
{
string str2;
try
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(PrivateKey);
//FromBase64String( ) 将 Base64 数字编码的等效字符串轮换为8位无符号整数的数组。
byte[] rgb = Convert.FromBase64String(DecryptString);
//Decrypt()方法是使用 RSA 算法对数据进行解密。
byte[] buffer2 = provider.Decrypt(rgb, false);
str2 = Encoding.Default.GetString(buffer2);
}
catch (Exception exception)
{
throw exception;
}
return str2;
}
辅助方法
这里用到了几个辅助方法:
- RSAKey:该函数用来生成RSA加密算法的私钥和公钥,两个参数分别表示私钥和公钥文件存放的路径。
- CreateKeyXML:将秘钥写入到xml文件。
- ReadKey:从指定路径中读取秘钥。
详细实现方法见github。这里展示一下生成的
公钥:
<RSAKeyValue><Modulus>u65I/FEnXx4hgzTRFdGqzFciJUQ3Mz07clToe0CflypaKfoIJX4ZAMYCYkZp7hID7DlPG3v6ocGGISzo06d2jq78P5RrJk86FjyiUQY6Yy1O2Wer/jiqjggLBZRIQd8Ku9x01z8hkJyXEpI8E662dZ5hplj+BxmwZk4XX4vZKJE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
私钥:
<RSAKeyValue><Modulus>u65I/FEnXx4hgzTRFdGqzFciJUQ3Mz07clToe0CflypaKfoIJX4ZAMYCYkZp7hID7DlPG3v6ocGGISzo06d2jq78P5RrJk86FjyiUQY6Yy1O2Wer/jiqjggLBZRIQd8Ku9x01z8hkJyXEpI8E662dZ5hplj+BxmwZk4XX4vZKJE=</Modulus><Exponent>AQAB</Exponent><P>9gzLCZ5O87uJlLHQlDRGG0X3RGr8s9XkL3rJYohD1h5+JzObCUciYAzLsaWxvYBjJHaYMeVrOpHEgAMiTl28iw==</P><Q>w0U7Lhv4KL6mBu8pOemLhljQLKUdFM7lrlFVv+OaLim5wp/SkW2O37R7USyTALzOmxbTUZ3N6+WaEkZ5inKG0w==</Q><DP>tJuLZhIITix4vucO/dqpI1fmOxh1SeRVTOzKakMv2Doly8y7nsHSX8LEui+wGjPlklxjNyz52tIo9PZX9kIkJQ==</DP><DQ>mGmkHIRGOP89tbHcmtA4UB9oNUCXJ1OqIFpptMHg6OE2lbuLbml2GBPWIPDKuMul85VoUY77WIG4tUT+vtpPcw==</DQ><InverseQ>jfOG+woJA62juB0VDH2sVNgefjSZTvIOTqj2QGmyYJzyJirQVyzM8F8o7JkAJDni7PDE2/2wVj5tIQWBuceg1g==</InverseQ><D>MNmCQbpVxxoumtoKeeVi0WD0kEKbI4kSigWzpTEC2PO7GCXuLOQPWfYv9KhjNgYWY0vfXUX9zFB0uvnXeA+kebgPoHKRzuaEsGDD2pHOTcvP/jz0ApdtyMs+J/kG5i6wZmumu7qCY/jj5OHlJmnNBm9fShj6p9RgybSGMCPPcuk=</D></RSAKeyValue>
实战演练
3des加密、解密示例:
private void button1_Click(object sender, EventArgs e)
{
string C_message = textBox1.Text; //明文
string Des_Key = textBox2.Text; //加密密钥
textBox3.Text = Encrypt.T_DESEEncrypt(C_message, Des_Key, Encoding.UTF8);//3DES加密
textBox5.Text = Encrypt.T_DESDecrypt(textBox3.Text, Des_Key, Encoding.UTF8); //3DES解密
}
RSA加密、解密示例
private void button2_Click(object sender, EventArgs e)
{
string C_message = textBox1.Text;
//生成key
Encrypt.RSAKey("G:\\PrivateKey.txt", "G:\\PublicKey.txt");
//读取key
string PublicKey = Encrypt.ReadKey("G:\\PublicKey.txt");
string PrivateKey = Encrypt.ReadKey("G:\\privateKey.txt");
//展示key
textBox5.Text = PrivateKey;
textBox2.Text = PublicKey;
//加密语句
textBox3.Text = Encrypt.RSAEncrypt(PublicKey, C_message);
//解密语句
textBox4.Text = Decrypt.RSADecrypt(PrivateKey, textBox3.Text);
}
MD5加密示例
private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = Encrypt.MD5EncryptFor64(textBox1.Text);
}
使用建议
- MD5由于其不可逆性,通常使用在对用户密码的加密。广泛用于登录接口。
- 对称加密虽然相对容易泄密,但是加密速度快,解密速度也快,加密后字符数较少。
- 非对称假面虽然相对安全,但是加密速度相对比对称加密较慢,且解密速度较慢,加密后字符数较多。根据场景合理选取。必要时可以选择混合加密。
ps:有兴趣的朋友可以在github补充其他常用的加密解密算法。