常见的几种加密算法及其C#代码
常见的加密算法可以分成三类:
对称加密算法,非对称加密算法和Hash算法。
在.net架构中,System.Security.Cryptography库中包含了各种加密解密算法对应的类,直接使用这些类中的函数就可以实现各种加密解密。
对称加密(也叫私钥加密)
指加密和解密使用相同密钥的加密算法。对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。假设两个用户需要使用对称加密方法加密然后交换数据,则用户最少需要2个密钥并交换使用,如果企业内用户有n个,则整个企业共需要n×(n-1) 个密钥,密钥的生成和分发将成为企业信息部门的恶梦。对称加密算法的安全性取决于加密密钥的保存情况,但要求企业中每一个持有密钥的人都保守秘密是不可能的,他们通常会有意无意的把密钥泄漏出去——如果一个用户使用的密钥被入侵者所获得,入侵者便可以读取该用户密钥加密的所有文档,如果整个企业共用一个加密密钥,那整个企业文档的保密性便无从谈起。
这里对称加密采用DES算法为例,具体使用时下面代码中带有说明,C#完整程序代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; using System.Windows.Forms; using System.Globalization; namespace WindowsApplication12 { class DES { //加密方法,注意:这里的密钥sKey必须能转为8个byte,即输入密钥为8半角个字符或者4个全角字符或者4个汉字的字符串 public static string Encrypt(string clearData, string sKey) { try { byte[] data = Encoding.UTF8.GetBytes(clearData); DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //以下两句限定了输入密钥只能为英文文本 //des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); //des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); //注意几种字符编码的区别:ASCII编码对字符串中每个字符使用8位即一个byte来表示,所以这种方式无法表示全角 //字符或者汉字(一个全角字符或汉字需要16位即两个byte来表示)。字符串里的每个全角字符或者汉字都看成一个字符 //Unicode编码对字符串中每个字符使用16位即两个byte来表示,即使是一个半角字符也用16位来表示(虽然一个半角 //字符用8位表示就足够了)。 //Default是指根据需要当遇到一个半角字符时用8位表示,遇到一个全角或者汉字时用16位来表示 //以下两句可以使输入密钥为中文或英文文本 des.Key = System.Text.Encoding.Default.GetBytes(sKey); des.IV = System.Text.Encoding.Default.GetBytes(sKey); ICryptoTransform desencrypt = des.CreateEncryptor(); byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);//进行加密 return BitConverter.ToString(result); } catch (Exception ex) { MessageBox.Show("错误:" + ex.Message, "错误消息提示框", MessageBoxButtons.OKCancel, MessageBoxIcon.Error); return null; } } //解密方法,注意:这里的密钥sKey必须能转为8个byte,即输入密钥为8半角个字符或者4个全角字符或者4个汉字的字符串 public static string Decrypt(string hashedData, string sKey) { try { ////DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //////把密文字符串放到byte数组中 ////byte[] dataArray = new UnicodeEncoding().GetBytes(hashedData); ////////建立加密对象的密钥和偏移向量 //////以下两句可以使输入密钥为中文或英文文本 ////des.Key = System.Text.Encoding.Unicode.GetBytes(sKey); ////des.IV = System.Text.Encoding.Unicode.GetBytes(sKey); ////MemoryStream ms = new MemoryStream();//存储解密后的数据 ////CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); ////cs.Write(dataArray, 0, dataArray.Length);//进行解密 ////cs.FlushFinalBlock(); ////string strRtn = Convert.ToBase64String(ms.ToArray()); ////return strRtn; string[] sInput = hashedData.Split("-".ToCharArray()); byte[] data = new byte[sInput.Length]; for (int i = 0; i < sInput.Length; i++) { data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber); } DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //以下两句限定了输入密钥只能为英文文本 //des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); //des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); //以下两句可以使输入密钥为中文或英文文本 des.Key = System.Text.Encoding.Default.GetBytes(sKey); des.IV = System.Text.Encoding.Default.GetBytes(sKey); ICryptoTransform desencrypt = des.CreateDecryptor(); byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);//进行解密 return Encoding.UTF8.GetString(result); } catch (Exception ex) { MessageBox.Show("错误:" + ex.Message, "错误消息提示框", MessageBoxButtons.OKCancel, MessageBoxIcon.Error); return null; } } } }
非对称加密(公钥加密)
指加密和解密使用不同密钥的加密算法,也称为公私钥加密。假设两个用户要加密交换数据,双方交换公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。由于公钥是可以公开的,用户只要保管好自己的私钥即可,因此加密密钥的分发将变得十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以可以通过信息发送者的公钥来验证信息的来源是否真实,还可以确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。
这里非对称加密采用RSA算法为例,具体使用时下面代码中带有说明,C#完整程序代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; using System.Windows.Forms; using System.Globalization; namespace WindowsApplication12 { class RSA { /// <summary> /// generate private key and public key arr[0] for private key arr[1] for public key /// </summary> /// <returns></returns> public static string[] GenerateKeys() { string[] sKeys = new String[2]; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //从XML文件中读取公钥和私钥 sKeys[0] = rsa.ToXmlString(true); sKeys[1] = rsa.ToXmlString(false); return sKeys; } /// <summary> /// RSA Encrypt /// </summary> /// <param name="sSource" >Source string</param> /// <param name="sPublicKey" >public key</param> /// <returns></returns> public static string EncryptString(string sSource, string sPublicKey) { try { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); string plaintext = sSource; rsa.FromXmlString(sPublicKey); byte[] cipherbytes; byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false); cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(plaintext), false); StringBuilder sbString = new StringBuilder(); for (int i = 0; i < cipherbytes.Length; i++) { sbString.Append(cipherbytes[i] + ","); } return sbString.ToString(); } catch { MessageBox.Show("数据错误"); return null; } } /// <summary> /// RSA Decrypt /// </summary> /// <param name="sSource">Source string</param> /// <param name="sPrivateKey">Private Key</param> /// <returns></returns> public static string DecryptString(String sSource, string sPrivateKey) { try { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(sPrivateKey); byte[] byteEn = rsa.Encrypt(Encoding.UTF8.GetBytes("a"), false); string[] sBytes = sSource.Split(','); for (int j = 0; j < sBytes.Length; j++) { if (sBytes[j] != "") { byteEn[j] = Byte.Parse(sBytes[j]); } } byte[] plaintbytes = rsa.Decrypt(byteEn, false); return Encoding.UTF8.GetString(plaintbytes); } catch { MessageBox.Show("数据错误"); return null; } } } }
Hash算法(哈希值)
Hash算法特别的地方在于它是一种单向算法,用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。
这里Hash算法用MD5算法为例,MD5加密是不可逆的,所以只有加密没有解密。具体使用时下面代码中带有说明,C#完整程序代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; namespace WindowsApplication12 { class MD5 { public static string EncryptCode(string password) { //明文密码由字符串转换为byte数组 byte[] clearBytes = new UnicodeEncoding().GetBytes(password); //由明文的byte数组计算出MD5密文byte数组 byte[] hashedBytes = ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(clearBytes); //把byte数组转换为字符串后返回,BitConverter用于将基础数据类型与字节数组相互转换 return BitConverter.ToString(hashedBytes); } } }