概述
數(shù)據(jù)加密的基本過程就是對(duì)原來為明文的文件或數(shù)據(jù)按某種算法進(jìn)行處理,使其成為不可讀的一段代碼,,通常稱為“密文”,,使其只能在輸入相應(yīng)的密鑰之后才能顯示出本來內(nèi)容,,通過這樣的途徑來達(dá)到保護(hù)數(shù)據(jù)不被非法人竊取,、閱讀的目的,。 該過程的逆過程為解密,,即將該編碼信息轉(zhuǎn)化為其原來數(shù)據(jù)的過程,。加密建立在對(duì)信息進(jìn)行數(shù)學(xué)編碼和解碼的基礎(chǔ)上。加密類型分為兩種,,對(duì)稱加密與非對(duì)稱加密,,對(duì)稱加密雙方采用共同密鑰。非對(duì)稱加密,這種加密方式存在兩個(gè)密鑰,,一個(gè)是公共密鑰(對(duì)外公開),,一種是私人密鑰(對(duì)外保密)。 一,、摘要算法數(shù)據(jù)摘要算法是密碼學(xué)算法中非常重要的一個(gè)分支,,它通過對(duì)所有數(shù)據(jù)提取指紋信息以實(shí)現(xiàn)數(shù)據(jù)簽名、數(shù)據(jù)完整性校驗(yàn)等功能,,由于其不可逆性,,有時(shí)候會(huì)被用做敏感信息的加密。數(shù)據(jù)摘要算法也被稱為哈希(Hash)算法或散列算法,。 從嚴(yán)格意義上講,,摘要算法不是加密算法,但在具體應(yīng)用中類似于加密算法使用,,或者與加密算法一起使用,,這里也拿來介紹下。 應(yīng)用范圍:密碼加密,、數(shù)據(jù)完整性校驗(yàn),、數(shù)字簽名等 這里介紹常用的兩種摘要算法,MD5與SHA1,。 提示:當(dāng)前MD5已經(jīng)被破解,,推薦使用SHA1 1、MD5哈希函數(shù)將任意長(zhǎng)度的二進(jìn)制字符串映射為固定長(zhǎng)度的小型二進(jìn)制字符串,。 加密哈希函數(shù)有這樣一個(gè)屬性:在計(jì)算上不大可能找到散列為相同的值的兩個(gè)不同的輸入,;也就是說,兩組數(shù)據(jù)的哈希值僅在對(duì)應(yīng)的數(shù)據(jù)也匹配時(shí)才會(huì)匹配,。 數(shù)據(jù)的少量更改會(huì)在哈希值中產(chǎn)生不可預(yù)知的大量更改,。MD5 算法的哈希值大小為 128 位。 MD5加密: /// <summary> /// MD5加密為32字符長(zhǎng)度的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(); //將每個(gè)字節(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計(jì)算輸入數(shù)據(jù)的 SHA1 哈希值,。 哈希值用作表示大量數(shù)據(jù)的固定大小的唯一值,。 如果相應(yīng)的數(shù)據(jù)也匹配,則兩個(gè)數(shù)據(jù)集的哈希應(yīng)該匹配,。 數(shù)據(jù)的少量更改會(huì)在哈希值中產(chǎn)生不可預(yù)知的大量更改,。 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); }
二、對(duì)稱加密對(duì)稱加密(也叫私鑰加密)指加密和解密使用相同密鑰的加密算法,。有時(shí)又叫傳統(tǒng)密碼算法,,就是加密密鑰能夠從解密密鑰中推算出來,同時(shí)解密密鑰也可以從加密密鑰中推算出來,。而在大多數(shù)的對(duì)稱算法中,,加密密鑰和解密密鑰是相同的,所以也稱這種加密算法為秘密密鑰算法或單密鑰算法,。 原理圖: 優(yōu)點(diǎn):算法公開,、計(jì)算量小、加密速度快,、加密效率高,。 常用的對(duì)稱加密算法有:DES、IDEA,、RC2,、RC4、SKIPJACK,、RC5,、AES算法等 應(yīng)用場(chǎng)景:數(shù)據(jù)傳輸、大數(shù)據(jù)量加密,、敏感數(shù)據(jù)加密等等 這里重點(diǎn)介紹常用的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月被美國(guó)政府采用,,DES隨后被美國(guó)國(guó)家標(biāo)準(zhǔn)局和美國(guó)國(guó)家標(biāo)準(zhǔn)協(xié)會(huì)(American National Standard Institute,ANSI)承認(rèn),。 但是,,這個(gè)算法,,現(xiàn)在已經(jīng)能夠輕易破解。不過對(duì)于日常的非機(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表示高級(jí)加密標(biāo)準(zhǔn) (AES) 的所有實(shí)現(xiàn)都必須從中繼承的抽象基類。 密碼學(xué)中的高級(jí)加密標(biāo)準(zhǔn)(Advanced Encryption Standard,,AES),,又稱Rijndael加密法,是美國(guó)聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn),。這個(gè)標(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(); } } } } }
三,、非對(duì)稱加密算法概念: 非對(duì)稱加密算法需要兩個(gè)密鑰:公開密鑰(publickey)和私有密鑰(privatekey),。公開密鑰與私有密鑰是一對(duì),如果用公開密鑰對(duì)數(shù)據(jù)進(jìn)行加密,,只有用對(duì)應(yīng)的私有密鑰才能解密,;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密,那么只有用對(duì)應(yīng)的公開密鑰才能解密,。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,,所以這種算法叫作非對(duì)稱加密算法。 非對(duì)稱加密算法實(shí)現(xiàn)機(jī)密信息交換的基本過程是:甲方生成一對(duì)密鑰并將其中的一把作為公用密鑰向其它方公開,;得到該公用密鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方,;甲方再用自己保存的另一把專用密鑰對(duì)加密后的信息進(jìn)行解密,。另一方面,甲方可以使用乙方的公鑰對(duì)機(jī)密信息進(jìn)行簽名后再發(fā)送給乙方,;乙方再用自己的私匙對(duì)數(shù)據(jù)進(jìn)行驗(yàn)簽,。甲方只能用其專用密鑰解密由其公用密鑰加密后的任何信息。 非對(duì)稱加密算法的保密性比較好,,它消除了最終用戶交換密鑰的需要,。 原理圖: 場(chǎng)景1:發(fā)送者用接收者的公鑰加密,接受者用自己的私鑰解密,,具體如下圖 場(chǎng)景2:數(shù)字簽名中應(yīng)用,,這里暫不進(jìn)行介紹,后續(xù)有相關(guān)文章進(jìn)行詳細(xì)介紹,。 見:http://www.cnblogs.com/yank/p/3533998.html
1、RSARSA(Rivest-Shamir-Adleman)算法是基于大數(shù)不可能被質(zhì)因數(shù)分解假設(shè)的公鑰體系,。簡(jiǎn)單地說就是找兩個(gè)很大的質(zhì)數(shù)。一個(gè)對(duì)外公開的為"公鑰"(Public key) ,,另一個(gè)不告訴任何人,,稱為"私鑰"(Private key)。這兩個(gè)密鑰是互補(bǔ)的,,也就是說用公鑰加密的密文可以用私鑰解密,,反過來也一樣。 假設(shè)用戶甲要寄信給用戶乙,,他們互相知道對(duì)方的公鑰,。甲就用乙的公鑰加密郵件寄出,乙收到后就可以用自己的私鑰解密出甲的原文,。由于別人不知道乙的私鑰,,所以即使是甲本人也無法解密那封信,這就解決了信件保密的問題,。另一方面,,由于每個(gè)人都知道乙的公鑰,,他們都可以給乙發(fā)信,那么乙怎么確信是不是甲的來信呢,?那就要用到基于加密技術(shù)的數(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); } }
所有案例,,見測(cè)試DEMO |
|