C#中的那些常用加密算法
前言
本文主要講解一下C#常用的那些加密算法。
本文源碼
本文所用源碼均以為大家整理完畢,大家使用以下方式獲取
需要的小伙伴,請(qǐng)關(guān)注微信公眾號(hào): 程序員零距離, 或者掃描下方公眾號(hào)二維碼,回復(fù)關(guān)鍵字:加密算法 , 即可獲取本文所用的所有源碼資源。
關(guān)注上方公眾號(hào),回復(fù) 加密算法獲取
MD5加密
MD5加密是最常見(jiàn)的加密方式,因?yàn)镸D5是不可逆的,所以很多系統(tǒng)的密碼都是用MD5加密保存的。
雖然MD5是不可以解碼的,但因?yàn)镸D5加密的字符串是固定的,所以,理論上只需要建立一個(gè)龐大的數(shù)據(jù)庫(kù),把所有的字符串都加密一遍,那就可以解碼所有的MD5密文了。
雖然建立一個(gè)可以解碼全部MD5的數(shù)據(jù)庫(kù)不太現(xiàn)實(shí),但一個(gè)五六百億數(shù)據(jù)量的數(shù)據(jù)庫(kù)就可以解碼絕大部分字符串了,畢竟大部分情況下,我們的密碼也是有長(zhǎng)度限制的。
實(shí)際應(yīng)用中MD5有64位和32位加密之分,代碼如下:
#region MD5加密 32和64 public static string GetMd532(string ConvertString) { MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8); t2 = t2.Replace("-", ""); return t2; } public static string Get64Md5(string str) { string cl = str; string pwd = ""; var md5 = MD5.Create(); byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl)); for (int i = 0; i < s.Length; i++) { pwd = pwd + s[i].ToString("X2"); } return pwd; } #endregion
我們運(yùn)行一下,加密函數(shù)。
Console.WriteLine($"MD5-64:{ MD5Helper.Get64Md5("Kiba518")}"); Console.WriteLine($"MD5-32:{ MD5Helper.Get32Md5("Kiba518")}");
結(jié)果如下圖所示:
SHA1加密
SHA1加密算法與MD5加密類似,都是不可逆的,只是算法不同。所以也和MD5一樣,存在容易被大數(shù)據(jù)解碼的問(wèn)題。
代碼如下:
private static readonly Encoding Encoder = Encoding.UTF8; public static String Sha1(String content ) { try { SHA1 sha1 = new SHA1CryptoServiceProvider();//創(chuàng)建SHA1對(duì)象 byte[] bytes_in = Encoder.GetBytes(content);//將待加密字符串轉(zhuǎn)為byte類型 byte[] bytes_out = sha1.ComputeHash(bytes_in);//Hash運(yùn)算 sha1.Dispose();//釋放當(dāng)前實(shí)例使用的所有資源 String result = BitConverter.ToString(bytes_out);//將運(yùn)算結(jié)果轉(zhuǎn)為string類型 result = result.Replace("-", "").ToUpper(); return result; } catch (Exception ex) { return ex.Message; } }
運(yùn)行加密函數(shù),結(jié)果如下圖所示:
Base64加密
準(zhǔn)確的來(lái)說(shuō),Base64是一種編碼,而不是加密,通常Base64編碼后字符串會(huì)用于傳輸數(shù)據(jù)。不過(guò)也因?yàn)锽ase64編碼后字符串具有不可讀性,所以,不少人也把他當(dāng)做加密算法來(lái)使用。
代碼如下:
private static readonly Encoding Encoder = Encoding.UTF8; public static string EncodeBase64(string source) { string target = ""; byte[] bytes = Encoder.GetBytes(source); try { target = Convert.ToBase64String(bytes); } catch { target = source; } return target; } public static string DecodeBase64(string result) { string decode = ""; byte[] bytes = Convert.FromBase64String(result); try { decode = Encoder.GetString(bytes); } catch { decode = result; } return decode; }
運(yùn)行Base64編碼函數(shù)。
string base64Str = Base64Helper.EncodeBase64("Kiba518"); Console.WriteLine($"SHA1編碼:{ base64Str}"); Console.WriteLine($"SHA1解碼:{ Base64Helper.DecodeBase64(base64Str)}");
結(jié)果如下圖所示:
Des加密
DES加密算法是對(duì)密鑰進(jìn)行保密,而公開算法,即只有擁有相同密鑰的人才能解密。
DES加密算法對(duì)密鑰有要求,必須是8個(gè)字符,如abcdefgh這樣的。
代碼如下:
public static string Encrypt(string stringToEncrypt, string shortKey) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] inputByteArray = Encoding.GetEncoding("UTF-8").GetBytes(stringToEncrypt); des.Key = ASCIIEncoding.UTF8.GetBytes(shortKey); des.IV = ASCIIEncoding.UTF8.GetBytes(shortKey); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); StringBuilder ret = new StringBuilder(); foreach (byte b in ms.ToArray()) { ret.AppendFormat("{0:X2}", b); } ret.ToString(); return ret.ToString(); } public static string Decrypt(string stringToDecrypt, string sKey) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); byte[] inputByteArray = new byte[stringToDecrypt.Length / 2]; for (int x = 0; x < stringToDecrypt.Length / 2; x++) { int i = (Convert.ToInt32(stringToDecrypt.Substring(x * 2, 2), 16)); inputByteArray[x] = (byte)i; } des.Key = ASCIIEncoding.UTF8.GetBytes(sKey); des.IV = ASCIIEncoding.UTF8.GetBytes(sKey); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); StringBuilder ret = new StringBuilder(); return System.Text.Encoding.Default.GetString(ms.ToArray()); }
如代碼所示,我們使用DESCryptoServiceProvider類來(lái)進(jìn)行DES加密。
DESCryptoServiceProvider類的Mode屬性可以指定加密運(yùn)算模式。
加密運(yùn)算模式如下:
- CBC:密碼塊鏈模式。
- ECB:電子密碼本模式。
- OFB:輸出反饋模式。
- CFB:密碼反饋模式。
- CTS:密碼文本竊取模式。
在C#中默認(rèn)的加密運(yùn)算模式是CBC—密碼塊鏈模式。
在Java中默認(rèn)的加密運(yùn)算模式是ECB—電子密碼本模式。
即,如果密文是在C#項(xiàng)目和Java項(xiàng)目之間傳遞,那么必須配置相同的加密運(yùn)算模式。
運(yùn)行DES加密函數(shù)代碼如下:
string key_8 = "abcdefgh"; string desShortKeyStr = DESHelper.Encrypt("Kiba518", key_8); Console.WriteLine($"DES加密:{ desShortKeyStr}"); Console.WriteLine($"DES解密:{ DESHelper.Decrypt(desShortKeyStr, key_8)}");
結(jié)果如下圖所示:
有時(shí)候,我們的密鑰不是正好8個(gè)字符,那我們就截取前8為作為密鑰就可以了。
RSA加密
RSA加密采用公鑰加密,私鑰解密的模式。Https的數(shù)字證書也是使用這種模式加密的。
代碼如下:
public static string RSADecrypt(string xmlPrivateKey, string enptStr) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPrivateKey); byte[] rgb = Convert.FromBase64String(enptStr); byte[] bytes = provider.Decrypt(rgb, RSAEncryptionPadding.OaepSHA1); return new UnicodeEncoding().GetString(bytes); } public static string RSAEncrypt(string xmlPublicKey, string enptStr) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPublicKey); byte[] bytes = new UnicodeEncoding().GetBytes(enptStr); return Convert.ToBase64String(provider.Encrypt(bytes, RSAEncryptionPadding.OaepSHA1)); }
運(yùn)行DES加密函數(shù)代碼如下:
//加密公鑰 string publicKey = "18+I2j3HU/fXQasRXOWGegP3dG75I/It2n42rgeIATeftBkoQNH73Rz0IYW++arqd0Yy5hFpNkqzY/dOmD+bDXWUheWA0P/dVZf+qeWwVV+iW3lRAU8SmnPcaD35Ic1jMEPFQVeX1zGI2ofD8aGodeSRA4+JKo+KLgyGVGDI+d0=AQAB"; //解密私鑰 string privateKey = " 18+I2j3HU/fXQasRXOWGegP3dG75I/It2n42rgeIATeftBkoQNH73Rz0IYW++arqd0Yy5hFpNkqzY/dOmD+bDXWUheWA0P/dVZf+qeWwVV+iW3lRAU8SmnPcaD35Ic1jMEPFQVeX1zGI2ofD8aGodeSRA4+JKo+KLgyGVGDI+d0=AQAB 2EEAI+cO1fyvmGpg3ywMLHHZ1/X3ZrF6xZBNM2AL7bJFVfL8RS8UznUCdsL/R/o1b+lGo1CetlI++n6IvYYwyw== /3muAXWOU3SMKFWSDpHUgeM9kZev0ekQDefRSayXM8q9ItkaWTOJcIN614A0UGdYE6VX1ztPgveQFzm0qJDy9w==NM/i/eGewOmd5IYONFJogq4nOlOKYNz1E6yC/gn1v83qmuvlaevuk+EFggVrHKPhSvxYUOgOao45bSlbsZVE8w==MKU7w91dh3iWw4tfr1SHUWAytglbGi41t2Af0taBSARftUX/pWKR1hHDD0vDKlgzRjJiooIRps966WE8jChliw==YEIfQArVNP27AJn3WOBswHP/+gJ6Bk434MZ80CJONp4b6e+Ilxd2dwloxGKNbGgCyaNJEFI5J8qYSNNe0KqPkw==ZAscSPesqLtS+WlBMkxgy719AGfVbRl+sjQiSwjIvq+3hDjJVUtCs90RO10SDBF0gfhz7f2SRY3ZnXTu5VtPF9KEQyUaY0F6eXwz4YQNzJTI2c1o5SFXZP8Ynqwltg8gNIhMe8bB6nVgASeADBim22DlSFCzmD3vt1gTI8nxmO0="; string myname = "my name is Kiba518!my name is Kiba518!!!!43"; //最大長(zhǎng)度43 string rsaStr = RSAHelper.RSAEncrypt(publicKey, myname); Console.WriteLine($"RSA加密:{ rsaStr}"); string dersaStr = RSAHelper.RSADecrypt(privateKey, rsaStr); Console.WriteLine($"RSA解密:{ dersaStr}");
結(jié)果如下圖所示:
RSA加密有個(gè)特點(diǎn),就是他對(duì)被加密的字符串有長(zhǎng)度限制。
長(zhǎng)度限制規(guī)則:待加密的字節(jié)數(shù)不能超過(guò)密鑰的長(zhǎng)度值除以 8 再減去 11(即:RSACryptoServiceProvider.KeySize / 8 - 11),而加密后得到密文的字節(jié)數(shù),正好是密鑰的長(zhǎng)度值除以 8(即:RSACryptoServiceProvider.KeySize / 8)。注:該長(zhǎng)度指的是byte[]數(shù)組的長(zhǎng)度,而不是字符串的長(zhǎng)度。
簡(jiǎn)單來(lái)說(shuō),就是被加密字符串不能太長(zhǎng)。
但是,在真實(shí)的業(yè)務(wù)中,我們需要加密的字符串往往會(huì)很長(zhǎng),那么,RSA又對(duì)被加密字符串有長(zhǎng)度限制,我們?cè)撛趺崔k呢?很簡(jiǎn)單,把待加密的字符串拆開,每段長(zhǎng)度都小于等于限制長(zhǎng)度,然后分段加密,這樣,問(wèn)題就解決了。
分段加密代碼如下:
public static String SubRSAEncrypt(string xmlPublicKey, string enptStr) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPublicKey); Byte[] bytes = Encoder.GetBytes(enptStr); int MaxBlockSize = provider.KeySize / 8 - 11; //加密塊最大長(zhǎng)度限制 if (bytes.Length <= MaxBlockSize) return Convert.ToBase64String(provider.Encrypt(bytes, false)); using (MemoryStream PlaiStream = new MemoryStream(bytes)) using (MemoryStream CrypStream = new MemoryStream()) { Byte[] Buffer = new Byte[MaxBlockSize]; int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize); while (BlockSize > 0) { Byte[] ToEncrypt = new Byte[BlockSize]; Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize); Byte[] Cryptograph = provider.Encrypt(ToEncrypt, false); CrypStream.Write(Cryptograph, 0, Cryptograph.Length); BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize); } return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None); } } /// /// 分段解密,應(yīng)對(duì)長(zhǎng)字符串 /// /// /// /// public static String SubRSADecrypt(string xmlPublicKey, string enptStr) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); provider.FromXmlString(xmlPublicKey); Byte[] bytes = Convert.FromBase64String(enptStr); int MaxBlockSize = provider.KeySize / 8; //解密塊最大長(zhǎng)度限制 if (bytes.Length <= MaxBlockSize) return Encoder.GetString(provider.Decrypt(bytes, false)); using (MemoryStream CrypStream = new MemoryStream(bytes)) using (MemoryStream PlaiStream = new MemoryStream()) { Byte[] Buffer = new Byte[MaxBlockSize]; int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize); while (BlockSize > 0) { Byte[] ToDecrypt = new Byte[BlockSize]; Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize); Byte[] Plaintext = provider.Decrypt(ToDecrypt, false); PlaiStream.Write(Plaintext, 0, Plaintext.Length); BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize); } return Encoder.GetString(PlaiStream.ToArray()); } }
結(jié)果如下圖所示:
結(jié)語(yǔ)
到此C#常用的那些加密算法就介紹完了,下面我們一起看一下,同一字符串,加密后情況。
可以看到,不同加密方式得到的密文長(zhǎng)度都不一樣,其中DES加密后在Base64編碼的模式的密文長(zhǎng)度最短。RSA加密的密文最長(zhǎng)。
本文源碼
本文所用源碼均以為大家整理完畢,大家使用以下方式獲取
需要的小伙伴,請(qǐng)關(guān)注微信公眾號(hào): 程序員零距離, 或者掃描下方公眾號(hào)二維碼,回復(fù)關(guān)鍵字:加密算法 , 即可獲取本文所用的所有源碼資源。
關(guān)注上方公眾號(hào),回復(fù) 加密算法獲取
到此這篇關(guān)于C#中的那些常用加密算法的文章就介紹到這了,更多相關(guān)C#加密算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#生成站點(diǎn)地圖(SiteMapPath)文件示例程序
這篇文章主要介紹了c#生成站點(diǎn)地圖(SiteMapPath)文件的示例,大家參考使用2013-11-11將DataTable轉(zhuǎn)換成List<T>實(shí)現(xiàn)思路及示例代碼
首先,這是我寫的一個(gè)通用轉(zhuǎn)換類,完成此類操作。也是實(shí)現(xiàn)這個(gè)功能最核心的部分。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11Winform開發(fā)框架中如何使用DevExpress的內(nèi)置圖標(biāo)資源
這篇文章主要給大家介紹了關(guān)于在Winform開發(fā)框架中如何使用DevExpress的內(nèi)置圖標(biāo)資源的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們一起來(lái)看看吧2018-12-12C#由當(dāng)前日期計(jì)算相應(yīng)的周一和周日的實(shí)例代碼
這篇文章介紹了C#由當(dāng)前日期計(jì)算相應(yīng)的周一和周日的實(shí)例代碼,有需要的朋友可以參考一下2013-09-09