C#编程总结(七)数据加密——附源码
C#編程總結(jié)(七)數(shù)據(jù)加密——附源碼
?概述
數(shù)據(jù)加密的基本過程就是對原來為明文的文件或數(shù)據(jù)按某種算法進(jìn)行處理,使其成為不可讀的一段代碼,通常稱為“密文”,使其只能在輸入相應(yīng)的密鑰之后才能顯示出本來內(nèi)容,通過這樣的途徑來達(dá)到保護(hù)數(shù)據(jù)不被非法人竊取、閱讀的目的。 該過程的逆過程為解密,即將該編碼信息轉(zhuǎn)化為其原來數(shù)據(jù)的過程。加密建立在對信息進(jìn)行數(shù)學(xué)編碼和解碼的基礎(chǔ)上。加密類型分為兩種,對稱加密與非對稱加密,對稱加密雙方采用共同密鑰。非對稱加密,這種加密方式存在兩個密鑰,一個是公共密鑰(對外公開),一種是私人密鑰(對外保密)。 ?
一、摘要算法
數(shù)據(jù)摘要算法是密碼學(xué)算法中非常重要的一個分支,它通過對所有數(shù)據(jù)提取指紋信息以實現(xiàn)數(shù)據(jù)簽名、數(shù)據(jù)完整性校驗等功能,由于其不可逆性,有時候會被用做敏感信息的加密。數(shù)據(jù)摘要算法也被稱為哈希(Hash)算法或散列算法。
從嚴(yán)格意義上講,摘要算法不是加密算法,但在具體應(yīng)用中類似于加密算法使用,或者與加密算法一起使用,這里也拿來介紹下。
應(yīng)用范圍:密碼加密、數(shù)據(jù)完整性校驗、數(shù)字簽名等
這里介紹常用的兩種摘要算法,MD5與SHA1。
提示:當(dāng)前MD5已經(jīng)被破解,推薦使用SHA1
1、MD5
哈希函數(shù)將任意長度的二進(jìn)制字符串映射為固定長度的小型二進(jìn)制字符串。 加密哈希函數(shù)有這樣一個屬性:在計算上不大可能找到散列為相同的值的兩個不同的輸入;也就是說,兩組數(shù)據(jù)的哈希值僅在對應(yīng)的數(shù)據(jù)也匹配時才會匹配。 數(shù)據(jù)的少量更改會在哈希值中產(chǎn)生不可預(yù)知的大量更改。MD5 算法的哈希值大小為 128 位。
MD5 類的 ComputeHash 方法將哈希作為 16 字節(jié)的數(shù)組返回。 請注意,某些 MD5 實現(xiàn)會生成 32 字符的十六進(jìn)制格式哈希。 若要與此類實現(xiàn)進(jìn)行互操作,請將 ComputeHash 方法的返回值格式化為十六進(jìn)制值。
?MD5加密:
/// <summary>/// MD5加密為32字符長度的16進(jìn)制字符串/// </summary>/// <param name="input"></param>/// <returns></returns>public static string EncryptByMD5(string input){MD5 md5Hasher = MD5.Create();byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(input));StringBuilder sBuilder = new StringBuilder();//將每個字節(jié)轉(zhuǎn)為16進(jìn)制for (int i = 0; i < data.Length; i++){sBuilder.Append(data[i].ToString("x2"));}return sBuilder.ToString(); }??
2、SHA1
計算輸入數(shù)據(jù)的 SHA1 哈希值。
哈希值用作表示大量數(shù)據(jù)的固定大小的唯一值。 如果相應(yīng)的數(shù)據(jù)也匹配,則兩個數(shù)據(jù)集的哈希應(yīng)該匹配。 數(shù)據(jù)的少量更改會在哈希值中產(chǎn)生不可預(yù)知的大量更改。
SHA1 算法的哈希值大小為 160 位。
?SHA1加密:
/// <summary>/// SHA1加密/// </summary>/// <param name="input"></param>/// <returns></returns>public static string EncryptBySHA1(string input){SHA1 sha = new SHA1CryptoServiceProvider(); byte[] bytes = Encoding.Unicode.GetBytes(input);byte[] result = sha.ComputeHash(bytes);return BitConverter.ToString(result);}??
?二、對稱加密
對稱加密(也叫私鑰加密)指加密和解密使用相同密鑰的加密算法。有時又叫傳統(tǒng)密碼算法,就是加密密鑰能夠從解密密鑰中推算出來,同時解密密鑰也可以從加密密鑰中推算出來。而在大多數(shù)的對稱算法中,加密密鑰和解密密鑰是相同的,所以也稱這種加密算法為秘密密鑰算法或單密鑰算法。
原理圖:
優(yōu)點:算法公開、計算量小、加密速度快、加密效率高。
缺點:密鑰管理困難,使用成本較高。與公開密鑰加密算法比起來,對稱加密算法能夠提供加密和認(rèn)證卻缺乏了簽名功能,使得使用范圍有所縮小。
常用的對稱加密算法有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等
應(yīng)用場景:數(shù)據(jù)傳輸、大數(shù)據(jù)量加密、敏感數(shù)據(jù)加密等等
這里重點介紹常用的DES與AES加密算法。
提示: DES已經(jīng)被破解,推薦使用3DES或AES
1、DES?
最早、最著名的保密密鑰或?qū)ΨQ密鑰加密算法DES(Data?Encryption Standard)是由IBM公司在70年代發(fā)展起來的,并經(jīng)政府的加密標(biāo)準(zhǔn)篩選后,于1976年11月被美國政府采用,DES隨后被美國國家標(biāo)準(zhǔn)局和美國國家標(biāo)準(zhǔn)協(xié)會(American National Standard Institute,ANSI)承認(rèn)。
DES使用56位密鑰對64位的數(shù)據(jù)塊進(jìn)行加密,并對64位的數(shù)據(jù)塊進(jìn)行16輪編碼。與每輪編碼時,一個48位的"每輪"密鑰值由56位的完整密鑰得出來。DES用軟件進(jìn)行解碼需用很長時間,而用硬件解碼速度非常快。幸運的是,當(dāng)時大多數(shù)黑客并沒有足夠的設(shè)備制造出這種硬件設(shè)備。在1977年,人們估計要耗資兩千萬美元才能建成一個專門計算機(jī)用于DES的解密,而且需要12個小時的破解才能得到結(jié)果。當(dāng)時DES被認(rèn)為是一種十分強(qiáng)大的加密方法。
隨著計算機(jī)硬件的速度越來越快,制造一臺這樣特殊的機(jī)器的花費已經(jīng)降到了十萬美元左右,而用它來保護(hù)十億美元的銀行,那顯然是不夠保險了。另一方面,如果只用它來保護(hù)一臺普通服務(wù)器,那么DES確實是一種好的辦法,因為黑客絕不會僅僅為入侵一個服務(wù)器而花那么多的錢破解DES密文。
但是,這個算法,現(xiàn)在已經(jīng)能夠輕易破解。不過對于日常的非機(jī)密文件同樣可以繼續(xù)使用。
?加密:
/// <summary>/// 加密字符串/// </summary>/// <param name="input"></param>/// <param name="sKey"></param>/// <returns></returns>public static string EncryptString(string input, string sKey){byte[] data = Encoding.UTF8.GetBytes(input);using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()){des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);ICryptoTransform desencrypt = des.CreateEncryptor();byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);return BitConverter.ToString(result);} }解密:
/// <summary>/// 解密字符串/// </summary>/// <param name="input"></param>/// <param name="sKey"></param>/// <returns></returns>public static string DecryptString(string input, string sKey){string[] sInput = input.Split("-".ToCharArray());byte[] data = new byte[sInput.Length];for (int i = 0; i < sInput.Length; i++){data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);}using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()){des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);ICryptoTransform desencrypt = des.CreateDecryptor();byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);return Encoding.UTF8.GetString(result);}}??
2、AES
表示高級加密標(biāo)準(zhǔn) (AES) 的所有實現(xiàn)都必須從中繼承的抽象基類。
密碼學(xué)中的高級加密標(biāo)準(zhǔn)(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。
加密:
/// <summary> /// AES加密算法 /// </summary> /// <param name="input">明文字符串</param> /// <param name="key">密鑰</param> /// <returns>字符串</returns> public static string EncryptByAES(string input, string key){byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 32));using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider()){aesAlg.Key = keyBytes;aesAlg.IV = AES_IV;ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msEncrypt = new MemoryStream()){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)){using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)){swEncrypt.Write(input);}byte[] bytes = msEncrypt.ToArray();//return Convert.ToBase64String(bytes);//此方法不可用return BitConverter.ToString(bytes);}}}}解密:
/// <summary> /// AES解密 /// </summary> /// <param name="input">密文字節(jié)數(shù)組</param> /// <param name="key">密鑰</param> /// <returns>返回解密后的字符串</returns> public static string DecryptByAES(string input, string key){//byte[] inputBytes = Convert.FromBase64String(input); //Encoding.UTF8.GetBytes(input);string[] sInput = input.Split("-".ToCharArray());byte[] inputBytes = new byte[sInput.Length];for (int i = 0; i < sInput.Length; i++){inputBytes[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);}byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 32)); using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider()){aesAlg.Key = keyBytes;aesAlg.IV = AES_IV;ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);using (MemoryStream msEncrypt = new MemoryStream(inputBytes)){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read)){using (StreamReader srEncrypt = new StreamReader(csEncrypt)){return srEncrypt.ReadToEnd();}}}} }?
三、非對稱加密算法?
概念:
非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數(shù)據(jù)進(jìn)行加密,只有用對應(yīng)的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進(jìn)行加密,那么只有用對應(yīng)的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。 非對稱加密算法實現(xiàn)機(jī)密信息交換的基本過程是:甲方生成一對密鑰并將其中的一把作為公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對加密后的信息進(jìn)行解密。另一方面,甲方可以使用乙方的公鑰對機(jī)密信息進(jìn)行簽名后再發(fā)送給乙方;乙方再用自己的私匙對數(shù)據(jù)進(jìn)行驗簽。甲方只能用其專用密鑰解密由其公用密鑰加密后的任何信息。 非對稱加密算法的保密性比較好,它消除了最終用戶交換密鑰的需要。
原理圖:
場景1:發(fā)送者用接收者的公鑰加密,接受者用自己的私鑰解密,具體如下圖
場景2:發(fā)送者用自己的私鑰加密,接收者用發(fā)送者公布的公鑰解密,具體如下圖
場景3:數(shù)字簽名中應(yīng)用,這里暫不進(jìn)行介紹,后續(xù)有相關(guān)文章進(jìn)行詳細(xì)介紹。
見:http://www.cnblogs.com/yank/p/3533998.html
優(yōu)點:非對稱加密體系不要求通信雙方事先傳遞密鑰或有任何約定就能完成保密通信,并且密鑰管理方便,可實現(xiàn)防止假冒和抵賴,因此,更適合網(wǎng)絡(luò)通信中的保密通信要求
主要算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)。
?
1、RSA
RSA(Rivest-Shamir-Adleman)算法是基于大數(shù)不可能被質(zhì)因數(shù)分解假設(shè)的公鑰體系。簡單地說就是找兩個很大的質(zhì)數(shù)。一個對外公開的為"公鑰"(Public key) ,另一個不告訴任何人,稱為"私鑰"(Private key)。這兩個密鑰是互補的,也就是說用公鑰加密的密文可以用私鑰解密,反過來也一樣。
假設(shè)用戶甲要寄信給用戶乙,他們互相知道對方的公鑰。甲就用乙的公鑰加密郵件寄出,乙收到后就可以用自己的私鑰解密出甲的原文。由于別人不知道乙的私鑰,所以即使是甲本人也無法解密那封信,這就解決了信件保密的問題。另一方面,由于每個人都知道乙的公鑰,他們都可以給乙發(fā)信,那么乙怎么確信是不是甲的來信呢?那就要用到基于加密技術(shù)的數(shù)字簽名了。
甲用自己的私鑰將簽名內(nèi)容加密,附加在郵件后,再用乙的公鑰將整個郵件加密(注意這里的次序,如果先加密再簽名的話,別人可以將簽名去掉后簽上自己的簽名,從而篡改了簽名)。這樣這份密文被乙收到以后,乙用自己的私鑰將郵件解密,得到甲的原文和數(shù)字簽名,然后用甲的公鑰解密簽名,這樣一來就可以確保兩方面的安全了。
加密:
/// <summary>/// RSA加密/// </summary>/// <param name="plaintext">明文</param>/// <param name="publicKey">公鑰</param>/// <returns>密文字符串</returns>public static string EncryptByRSA(string plaintext, string publicKey){ UnicodeEncoding ByteConverter = new UnicodeEncoding(); byte[] dataToEncrypt = ByteConverter.GetBytes(plaintext);using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()){RSA.FromXmlString(publicKey);byte[] encryptedData = RSA.Encrypt(dataToEncrypt, false);return Convert.ToBase64String(encryptedData);}}?
解密:
/// <summary>/// RSA解密/// </summary>/// <param name="ciphertext">密文</param>/// <param name="privateKey">私鑰</param>/// <returns>明文字符串</returns>public static string DecryptByRSA(string ciphertext, string privateKey){UnicodeEncoding byteConverter = new UnicodeEncoding();using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()){RSA.FromXmlString(privateKey);byte[] encryptedData = Convert.FromBase64String(ciphertext);byte[] decryptedData = RSA.Decrypt(encryptedData, false);return byteConverter.GetString(decryptedData);}}?
所有案例,見測試DEMO
源碼地址:http://files.cnblogs.com/yank/EncriptSample.zip
總結(jié)
以上是生活随笔為你收集整理的C#编程总结(七)数据加密——附源码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Appboy 基于 MongoDB 的数
- 下一篇: C#外部方法