C#开发中常用加密解密方法解析
一、MD5加密算法
我想这是大家都常听过的算法,可能也用的比较多。那么什么是MD5算法呢?MD5全称是
message-digest algorithm 5【|ˈmesidʒ|-|daiˈdʒest|-|ˈælɡəriðəm|】,简单的说就是单向的加密,即是说无法根据密文推导出明文。
MD5主要用途:
1、对一段信息生成信息摘要,该摘要对该信息具有唯一性,可以作为数字签名。
2、用于验证文件的有效性(是否有丢失或损坏的数据),
3、对用户密码的加密,
4、在哈希函数中计算散列值
从上边的主要用途中我们看到,由于算法的某些不可逆特征,在加密应用上有较好的安全性。通过使用MD5加密算法,我们输入一个任意长度的字节串,都会生成一个128位的整数。所以根据这一点MD5被广泛的用作密码加密。下面我就像大家演示一下怎样进行密码加密。
先看下演示效果:
具体代码如下:
首先需要引入命名空间:
using System.Security; using System.Security.Cryptography; private void btnmd5_Click(object sender, EventArgs e) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] palindata = Encoding.Default.GetBytes(txtyuan.Text);//将要加密的字符串转换为字节数组 byte[] encryptdata=md5.ComputeHash(palindata);//将字符串加密后也转换为字符数组 txtjiami.Text = Convert.ToBase64String(encryptdata);//将加密后的字节数组转换为加密字符串 }
这里我们需要注意的是,不论是在加密的过程中,加密前要将加密字符串转为字节数组,加密后也要生成密文的字节数据,然后再转化为密文。
二、RSA加密算法
在谈RSA加密算法之前,我们需要先了解下两个专业名词,对称加密和非对称加密。
对称加密即:含有一个称为密钥的东西,在消息发送前使用密钥对消息进行加密,在对方收到消息之后,使用相同的密钥进行解密
非对称加密即:加密和解密使用不同的密钥的一类加密算法。这类加密算法通常有两个密钥A和B,使用密钥A加密数据得到的密文,只有密钥B可以进行解密操作(即使密钥A也无法解密),相反,使用了密钥B加密数据得到的密文,只有密钥A可以解密。这两个密钥分别称为私钥和公钥,顾名思义,私钥就是你个人保留,不能公开的密钥,而公钥则是公开给加解密操作的另一方的。根据不同用途,对数据进行加密所使用的密钥也不相同(有时用公钥加密,私钥解密;有时相反用私钥加密,公钥解密)。非对称加密的代表算法是RSA算法。
了解了这两个名词下面来讲,RSA加密算法。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,多用于数据加密和数字签名。虽然有这么大的影响力,但是同时它也有一些弊端,它产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密,分组长度太大等。
下面通过示例演示使用RSA加密、解密,引用名称空间System.Security.Cryptography;
//加密 private string Encryption(string express) { CspParameters param = new CspParameters(); param.KeyContainerName = "oa_erp_dowork";//密匙容器的名称,保持加密解密一致才能解密成功 using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(param)) { byte[] plaindata = Encoding.Default.GetBytes(express);//将要加密的字符串转换为字节数组 byte[] encryptdata = rsa.Encrypt(plaindata, false);//将加密后的字节数据转换为新的加密字节数组 return Convert.ToBase64String(encryptdata);//将加密后的字节数组转换为字符串 } } //解密 private string Decrypt(string ciphertext) { CspParameters param = new CspParameters(); param.KeyContainerName = "oa_erp_dowork"; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(param)) { byte[] encryptdata = Convert.FromBase64String(ciphertext); byte[] decryptdata = rsa.Decrypt(encryptdata, false); return Encoding.Default.GetString(decryptdata); } }
下面我再通过一个示例向大家演示,通过使用RSA加密算法产出公匙和私匙
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); using (StreamWriter sw = new StreamWriter(Server.MapPath("PublicKey.xml")))//产生公匙 { sw.WriteLine(rsa.ToXmlString(false)); } using (StreamWriter sw = new StreamWriter(Server.MapPath("PrivateKey.xml")))//产生私匙(也包含私匙) { sw.WriteLine(rsa.ToXmlString(true)); }
三、DES加密
DES加密:使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。额专业术语就看看得了,下面直接给大家演示一个小demo,以帮助大家的理解。
先定义一个全局的字节数组和实例化一个全局的DESCryptoServiceProvider对象
byte[] buffer;
DESCryptoServiceProvider DesCSP = new DESCryptoServiceProvider();
加密: private void button2_Click(object sender, EventArgs e) { MemoryStream ms = new MemoryStream();//先创建 一个内存流 CryptoStream cryStream = new CryptoStream(ms, DesCSP.CreateEncryptor(), CryptoStreamMode.Write);//将内存流连接到加密转换流 StreamWriter sw = new StreamWriter(cryStream); sw.WriteLine(txtyuan.Text);//将要加密的字符串写入加密转换流 sw.Close(); cryStream.Close(); buffer = ms.ToArray();//将加密后的流转换为字节数组 txtjiami.Text =Convert.ToBase64String(buffer);//将加密后的字节数组转换为字符串 } 解密: private void button1_Click(object sender, EventArgs e) { MemoryStream ms = new MemoryStream(buffer);//将加密后的字节数据加入内存流中 CryptoStream cryStream = new CryptoStream(ms, DesCSP.CreateDecryptor(), CryptoStreamMode.Read);//内存流连接到解密流中 StreamReader sr = new StreamReader(cryStream); txthjiemi.Text = sr.ReadLine();//将解密流读取为字符串 sr.Close(); cryStream.Close(); ms.Close(); }
此外还有AES加密算法,但是AES加密是一个新的可以用于保护电子数据的加密算法。其产生的密码是迭代对称的分组密码,代加密使用一个循环结构,在该循环中重复置换和替换输入数据。因为用的不是很多,在这里就不再做具体的演示了。
1 //SHA-1算法 2 string password = 3 System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Password.Text, 4 "SHA1"); 5 //MD5算法 6 string password1 = 7 System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Password.Text, 8 "MD5"); 9 10 加密后生成不可逆密文保存到数据库中。用户登录时用加密计算后的密文与数据库中的密码密文比较。一致则通过验证,不一致则返回登录错误。 11 这种加密算法是不可逆的,所以除了用户自己,其他人无法得知用户的真实密码内容。 12 13 SHA-1算法和MD5算法的区别: 14 SHA-1比MD5多32位密文,所以更安全。由于同样的原因,MD5比SHA-1的运算速度更快。 15 16 17 18 19 加密算法总汇 20 方法一: 21 22 //须添加对System.Web的引用 23 using System.Web.Security; 24 25 ... 26 27 28 /// <summary> 29 /// SHA1加密字符串 30 /// 31 </summary> 32 /// <param name="source">源字符串</param> 33 34 /// <returns>加密后的字符串</returns> 35 public string 36 SHA1(string source) 37 { 38 return 39 FormsAuthentication.HashPasswordForStoringInConfigFile(source, "SHA1"); 40 41 } 42 43 44 /// <summary> 45 /// MD5加密字符串 46 /// 47 </summary> 48 /// <param name="source">源字符串</param> 49 50 /// <returns>加密后的字符串</returns> 51 public string 52 MD5(string source) 53 { 54 return 55 FormsAuthentication.HashPasswordForStoringInConfigFile(source, "MD5");; 56 57 } 58 59 60 方法二(可逆加密解密): 61 using System.Security.Cryptography; 62 63 64 ... 65 66 public string Encode(string data) 67 { 68 69 byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64); 70 71 byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64); 72 73 74 DESCryptoServiceProvider cryptoProvider = new 75 DESCryptoServiceProvider(); 76 int i = cryptoProvider.KeySize; 77 78 MemoryStream ms = new MemoryStream(); 79 CryptoStream cst = 80 new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), 81 CryptoStreamMode.Write); 82 83 StreamWriter sw = new 84 StreamWriter(cst); 85 sw.Write(data); 86 sw.Flush(); 87 88 cst.FlushFinalBlock(); 89 sw.Flush(); 90 return 91 Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length); 92 93 } 94 95 96 public string Decode(string data) 97 { 98 byte[] 99 byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64); 100 byte[] 101 byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64); 102 103 104 byte[] byEnc; 105 try 106 { 107 byEnc = 108 Convert.FromBase64String(data); 109 } 110 catch 111 { 112 113 return null; 114 } 115 116 117 DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider(); 118 119 MemoryStream ms = new MemoryStream(byEnc); 120 CryptoStream 121 cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), 122 CryptoStreamMode.Read); 123 StreamReader sr = new StreamReader(cst); 124 125 return sr.ReadToEnd(); 126 } 127 128 方法三(MD5不可逆): 129 using 130 System.Security.Cryptography; 131 132 ... 133 134 //MD5不可逆加密 135 136 137 //32位加密 138 139 public string GetMD5_32(string s, 140 string _input_charset) 141 { 142 MD5 md5 = new 143 MD5CryptoServiceProvider(); 144 byte[] t = 145 md5.ComputeHash(Encoding.GetEncoding(_input_charset).GetBytes(s)); 146 147 StringBuilder sb = new StringBuilder(32); 148 for (int i = 0; i < 149 t.Length; i++) 150 { 151 152 sb.Append(t[i].ToString("x").PadLeft(2, '0')); 153 } 154 return 155 sb.ToString(); 156 } 157 158 //16位加密 159 public static string 160 GetMd5_16(string ConvertString) 161 { 162 MD5CryptoServiceProvider 163 md5 = new MD5CryptoServiceProvider(); 164 string t2 = 165 BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 166 4, 8); 167 t2 = t2.Replace("-", ""); 168 return t2; 169 170 } 171 172 方法四(对称加密): 173 using System.IO; 174 using 175 System.Security.Cryptography; 176 177 ... 178 179 private 180 SymmetricAlgorithm mobjCryptoService; 181 private string Key; 182 /// 183 <summary> 184 /// 对称加密类的构造函数 185 /// </summary> 186 187 public SymmetricMethod() 188 { 189 mobjCryptoService = new 190 RijndaelManaged(); 191 Key = 192 "Guz(%&hj7x89H$yuBI0456FtmaT5&fvHUFCy76*h%(HilJ$lhj!y6&(*jkP87jH7"; 193 194 } 195 /// <summary> 196 /// 获得密钥 197 /// 198 </summary> 199 /// <returns>密钥</returns> 200 201 private byte[] GetLegalKey() 202 { 203 string sTemp = Key; 204 205 mobjCryptoService.GenerateKey(); 206 byte[] bytTemp = 207 mobjCryptoService.Key; 208 int KeyLength = bytTemp.Length; 209 210 if (sTemp.Length > KeyLength) 211 sTemp = sTemp.Substring(0, 212 KeyLength); 213 else if (sTemp.Length < KeyLength) 214 215 sTemp = sTemp.PadRight(KeyLength, ' '); 216 return 217 ASCIIEncoding.ASCII.GetBytes(sTemp); 218 } 219 /// <summary> 220 221 /// 获得初始向量IV 222 /// </summary> 223 /// 224 <returns>初试向量IV</returns> 225 private byte[] GetLegalIV() 226 227 { 228 string sTemp = 229 "E4ghj*Ghg7!rNIfb&95GUY86GfghUb#er57HBh(u%g6HJ($jhWk7&!hg4ui%$hjk"; 230 231 mobjCryptoService.GenerateIV(); 232 byte[] bytTemp = 233 mobjCryptoService.IV; 234 int IVLength = bytTemp.Length; 235 if 236 (sTemp.Length > IVLength) 237 sTemp = sTemp.Substring(0, 238 IVLength); 239 else if (sTemp.Length < IVLength) 240 241 sTemp = sTemp.PadRight(IVLength, ' '); 242 return 243 ASCIIEncoding.ASCII.GetBytes(sTemp); 244 } 245 /// <summary> 246 247 /// 加密方法 248 /// </summary> 249 /// <param 250 name="Source">待加密的串</param> 251 /// 252 <returns>经过加密的串</returns> 253 public string Encrypto(string 254 Source) 255 { 256 byte[] bytIn = UTF8Encoding.UTF8.GetBytes(Source); 257 258 MemoryStream ms = new MemoryStream(); 259 260 mobjCryptoService.Key = GetLegalKey(); 261 mobjCryptoService.IV = 262 GetLegalIV(); 263 ICryptoTransform encrypto = 264 mobjCryptoService.CreateEncryptor(); 265 CryptoStream cs = new 266 CryptoStream(ms, encrypto, CryptoStreamMode.Write); 267 cs.Write(bytIn, 268 0, bytIn.Length); 269 cs.FlushFinalBlock(); 270 ms.Close(); 271 272 byte[] bytOut = ms.ToArray(); 273 return 274 Convert.ToBase64String(bytOut); 275 } 276 /// <summary> 277 278 /// 解密方法 279 /// </summary> 280 /// <param 281 name="Source">待解密的串</param> 282 /// 283 <returns>经过解密的串</returns> 284 public string Decrypto(string 285 Source) 286 { 287 byte[] bytIn = Convert.FromBase64String(Source); 288 289 MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length); 290 291 mobjCryptoService.Key = GetLegalKey(); 292 293 mobjCryptoService.IV = GetLegalIV(); 294 ICryptoTransform encrypto = 295 mobjCryptoService.CreateDecryptor(); 296 CryptoStream cs = new 297 CryptoStream(ms, encrypto, CryptoStreamMode.Read); 298 StreamReader sr = 299 new StreamReader(cs); 300 return sr.ReadToEnd(); 301 302 } 303 304 方法五: 305 using System.IO; 306 using 307 System.Security.Cryptography; 308 using System.Text; 309 310 ... 311 312 313 //默认密钥向量 314 private static byte[] Keys = { 0x12, 0x34, 315 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; 316 /// <summary> 317 /// 318 DES加密字符串 319 /// </summary> 320 /// <param 321 name="encryptString">待加密的字符串</param> 322 /// <param 323 name="encryptKey">加密密钥,要求为8位</param> 324 /// 325 <returns>加密成功返回加密后的字符串,失败返回源串</returns> 326 public static string 327 EncryptDES(string encryptString, string encryptKey) 328 { 329 330 try 331 { 332 byte[] rgbKey = 333 Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8)); 334 byte[] rgbIV 335 = Keys; 336 byte[] inputByteArray = 337 Encoding.UTF8.GetBytes(encryptString); 338 DESCryptoServiceProvider 339 dCSP = new DESCryptoServiceProvider(); 340 MemoryStream mStream = 341 new MemoryStream(); 342 CryptoStream cStream = new 343 CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), 344 CryptoStreamMode.Write); 345 cStream.Write(inputByteArray, 0, 346 inputByteArray.Length); 347 cStream.FlushFinalBlock(); 348 349 return Convert.ToBase64String(mStream.ToArray()); 350 } 351 352 catch 353 { 354 return encryptString; 355 356 } 357 } 358 359 /// <summary> 360 /// DES解密字符串 361 362 /// </summary> 363 /// <param 364 name="decryptString">待解密的字符串</param> 365 /// <param 366 name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param> 367 /// 368 <returns>解密成功返回解密后的字符串,失败返源串</returns> 369 public static string 370 DecryptDES(string decryptString, string decryptKey) 371 { 372 373 try 374 { 375 byte[] rgbKey = 376 Encoding.UTF8.GetBytes(decryptKey); 377 byte[] rgbIV = Keys; 378 379 byte[] inputByteArray = Convert.FromBase64String(decryptString); 380 381 DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider(); 382 383 MemoryStream mStream = new MemoryStream(); 384 385 CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, 386 rgbIV), CryptoStreamMode.Write); 387 cStream.Write(inputByteArray, 388 0, inputByteArray.Length); 389 cStream.FlushFinalBlock(); 390 391 return Encoding.UTF8.GetString(mStream.ToArray()); 392 } 393 394 catch 395 { 396 return decryptString; 397 398 } 399 } 400 401 方法六(文件加密): 402 using System.IO; 403 using 404 System.Security.Cryptography; 405 using System.Text; 406 407 ... 408 409 410 //加密文件 411 private static void EncryptData(String inName, 412 String outName, byte[] desKey, byte[] desIV) 413 { 414 //Create the 415 file streams to handle the input and output files. 416 FileStream fin = 417 new FileStream(inName, FileMode.Open, FileAccess.Read); 418 FileStream 419 fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write); 420 421 fout.SetLength(0); 422 423 //Create variables to help 424 with read and write. 425 byte[] bin = new byte[100]; //This is 426 intermediate storage for the encryption. 427 long rdlen = 428 0; //This is the total number of bytes written. 429 long 430 totlen = fin.Length; //This is the total length of the input file. 431 432 int len; //This is the number of bytes to be 433 written at a time. 434 435 DES des = new 436 DESCryptoServiceProvider(); 437 CryptoStream encStream = new 438 CryptoStream(fout, des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write); 439 440 441 //Read from the input file, then encrypt and write to the 442 output file. 443 while (rdlen < totlen) 444 { 445 446 len = fin.Read(bin, 0, 100); 447 encStream.Write(bin, 0, len); 448 449 rdlen = rdlen + len; 450 } 451 452 453 encStream.Close(); 454 fout.Close(); 455 fin.Close(); 456 } 457 458 459 //解密文件 460 private static void DecryptData(String inName, 461 String outName, byte[] desKey, byte[] desIV) 462 { 463 //Create the 464 file streams to handle the input and output files. 465 FileStream fin = 466 new FileStream(inName, FileMode.Open, FileAccess.Read); 467 FileStream 468 fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write); 469 470 fout.SetLength(0); 471 472 //Create variables to help 473 with read and write. 474 byte[] bin = new byte[100]; //This is 475 intermediate storage for the encryption. 476 long rdlen = 477 0; //This is the total number of bytes written. 478 long 479 totlen = fin.Length; //This is the total length of the input file. 480 481 int len; //This is the number of bytes to be 482 written at a time. 483 484 DES des = new 485 DESCryptoServiceProvider(); 486 CryptoStream encStream = new 487 CryptoStream(fout, des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Write); 488 489 490 //Read from the input file, then encrypt and write to the 491 output file. 492 while (rdlen < totlen) 493 { 494 495 len = fin.Read(bin, 0, 100); 496 encStream.Write(bin, 0, len); 497 498 rdlen = rdlen + len; 499 } 500 501 502 encStream.Close(); 503 fout.Close(); 504 fin.Close(); 505 506 507 } 508 509 using System; 510 using 511 System.Security.Cryptography;//这个是处理文字编码的前提 512 using System.Text; 513 using 514 System.IO; 515 /// <summary> 516 /// DES加密方法 517 /// </summary> 518 /// 519 <param name="strPlain">明文</param> 520 /// <param 521 name="strDESKey">密钥</param> 522 /// <param 523 name="strDESIV">向量</param> 524 /// 525 <returns>密文</returns> 526 public string DESEncrypt(string 527 strPlain,string strDESKey,string strDESIV) 528 { 529 //把密钥转换成字节数组 530 byte[] 531 bytesDESKey=ASCIIEncoding.ASCII.GetBytes(strDESKey); 532 //把向量转换成字节数组 533 byte[] 534 bytesDESIV=ASCIIEncoding.ASCII.GetBytes(strDESIV); 535 //声明1个新的DES对象 536 DESCryptoServiceProvider 537 desEncrypt=new DESCryptoServiceProvider(); 538 //开辟一块内存流 539 MemoryStream 540 msEncrypt=new MemoryStream(); 541 //把内存流对象包装成加密流对象 542 CryptoStream 543 csEncrypt=new 544 CryptoStream(msEncrypt,desEncrypt.CreateEncryptor(bytesDESKey,bytesDESIV),CryptoStreamMode.Write); 545 //把加密流对象包装成写入流对象 546 StreamWriter 547 swEncrypt=new 548 StreamWriter(csEncrypt); 549 //写入流对象写入明文 550 swEncrypt.WriteLine(strPlain); 551 //写入流关闭 552 swEncrypt.Close(); 553 //加密流关闭 554 csEncrypt.Close(); 555 //把内存流转换成字节数组,内存流现在已经是密文了 556 byte[] 557 bytesCipher=msEncrypt.ToArray(); 558 //内存流关闭 559 msEncrypt.Close(); 560 //把密文字节数组转换为字符串,并返回 561 return 562 UnicodeEncoding.Unicode.GetString(bytesCipher); 563 } 564 565 566 567 568 /// 569 <summary> 570 /// DES解密方法 571 /// </summary> 572 /// <param 573 name="strCipher">密文</param> 574 /// <param 575 name="strDESKey">密钥</param> 576 /// <param 577 name="strDESIV">向量</param> 578 /// 579 <returns>明文</returns> 580 public string DESDecrypt(string 581 strCipher,string strDESKey,string strDESIV) 582 { 583 //把密钥转换成字节数组 584 byte[] 585 bytesDESKey=ASCIIEncoding.ASCII.GetBytes(strDESKey); 586 //把向量转换成字节数组 587 byte[] 588 bytesDESIV=ASCIIEncoding.ASCII.GetBytes(strDESIV); 589 //把密文转换成字节数组 590 byte[] 591 bytesCipher=UnicodeEncoding.Unicode.GetBytes(strCipher); 592 //声明1个新的DES对象 593 DESCryptoServiceProvider 594 desDecrypt=new 595 DESCryptoServiceProvider(); 596 //开辟一块内存流,并存放密文字节数组 597 MemoryStream 598 msDecrypt=new MemoryStream(bytesCipher); 599 //把内存流对象包装成解密流对象 600 CryptoStream 601 csDecrypt=new 602 CryptoStream(msDecrypt,desDecrypt.CreateDecryptor(bytesDESKey,bytesDESIV),CryptoStreamMode.Read); 603 //把解密流对象包装成读出流对象 604 StreamReader 605 srDecrypt=new StreamReader(csDecrypt); 606 //明文=读出流的读出内容 607 string 608 strPlainText=srDecrypt.ReadLine(); 609 //读出流关闭 610 srDecrypt.Close(); 611 //解密流关闭 612 csDecrypt.Close(); 613 //内存流关闭 614 msDecrypt.Close(); 615 //返回明文 616 return 617 strPlainText; 618 }