本筆記摘抄自:https://www.cnblogs.com/skylaugh/archive/2011/07/12/2103572.html,記錄一下學習過程以備後續查用。 數據加密技術是網路中最基本的安全技術,主要是通過對網路中傳輸的信息進行數據加密來保障其安全性,這是一種主動安全防禦策略,用很 ...
本筆記摘抄自:https://www.cnblogs.com/skylaugh/archive/2011/07/12/2103572.html,記錄一下學習過程以備後續查用。
數據加密技術是網路中最基本的安全技術,主要是通過對網路中傳輸的信息進行數據加密來保障其安全性,這是一種主動安全防禦策略,用很小的代價
即可為信息提供相當大的安全保護。
一、加密的基本概念
"加密",是一種限制對網路上傳輸數據的訪問權的技術。原始數據(也稱為明文,plaintext)被加密設備(硬體或軟體)和密鑰加密而產生的經過編碼的數據
稱為密文(ciphertext)。將密文還原為原始明文的過程稱為解密,它是加密的反向處理,但解密者必須利用相同類型的加密設備和密鑰對密文進行解密。
加密的基本功能包括:
1)防止不速之客查看機密的數據文件。
2)防止機密數據被泄露或篡改。
3)防止特權用戶(如系統管理員)查看私人數據文件。
4)使入侵者不能輕易地查找一個系統的文件。
數據加密是確保電腦網路安全的一種重要機制,雖然由於成本、技術和管理上的複雜性等原因,目前尚未在網路中普及,但數據加密的確是實現分佈
式系統和網路環境下數據安全的重要手段之一。
數據加密可在網路OSI七層協議(OSI是Open System Interconnect的縮寫,意為開放式系統互聯。國際標準組織(國際標準化組織)制定了OSI模型。這
個模型把網路通信的工作分為7層,分別是物理層、數據鏈路層、網路層、傳輸層、會話層、表示層和應用層。)的多層上實現,所以從加密技術應用的邏
輯位置看,有三種方式:
1)鏈路加密:通常把網路層以下的加密叫鏈路加密,主要用於保護通信節點間傳輸的數據,加解密由置於線路上的密碼設備實現。根據傳遞的數據的同
步方式又可分為同步通信加密和非同步通信加密兩種,同步通信加密又包含位元組同步通信加密和位同步通信加密。
2)節點加密:是對鏈路加密的改進。在協議傳輸層上進行加密,主要是對源節點和目標節點之間傳輸數據進行加密保護,與鏈路加密類似,只是加密算
法要結合在依附於節點的加密模件中,剋服了鏈路加密在節點處易遭非法存取的缺點。
3)端對端加密:網路層以上的加密稱為端對端加密,是面向網路層主體。對應用層的數據信息進行加密,易於用軟體實現,且成本低,但密鑰管理問題
困難,主要適合大型網路系統中信息在多個發方和收方之間傳輸的情況。
二、數據加密的應用
1)媒體加密:DRM
2)文件加密:文本加密、pdf、word
3)數據加密:C#中的數據加密
4)硬體加密:加密狗
三、加密技術發展趨勢
1)私用密鑰加密技術與公開密鑰加密技術相結合:鑒於兩種密碼體制加密的特點,在實際應用中可以採用折衷方案,即結合使用DES/IDEA和RSA,以
DES為"內核",RSA為"外殼",對於網路中傳輸的數據可用DES或IDEA加密,而加密用的密鑰則用RSA加密傳送,此種方法既保證了數據安全又提高了加密
和解密的速度,這也是目前加密技術發展的新方向之一。
2)尋求新演算法:跳出以常見的迭代為基礎的構造思路,脫離基於某些數學問題複雜性的構造方法。如劉尊全先生提出的劉氏演算法,是一種基於密鑰的公
開密鑰體制。它採用隨機性原理構造加解密變換,並將其全部運算控制隱匿於密鑰中,密鑰長度可變;它採用選取一定長度的分割來構造大的搜索空間,從
而實現一次非線性變換。此種加密演算法加密強度高、速度快、計算開銷低。
3)加密最終將被集成到系統和網路中,例如IPV6協議就已有了內置加密的支持,在硬體方面,Intel公司正研製一種加密協處理器,它可以集成到微機的
主板上。
四、加密技術的分類
加密類型可以簡單地分為四種:
1)根本不考慮解密問題。
2)私用密鑰加密技術--對稱式加密(Symmetric Key Encryption):對稱式加密方式對加密和解密使用相同的密鑰。通常,這種加密方式在應用中難以實
施,因為用同一種安全方式共用密鑰很難,如:RC4、RC2、DES和AES系列加密演算法。
3)公開密鑰加密技術--非對稱密鑰加密(Asymmetric Key Encryption):非對稱密鑰加密使用一組公共/私人密鑰系統,加密時使用一種密鑰,解密時使
用另一種密鑰。公共密鑰可以廣泛的共用和透露,當需要用加密方式向伺服器外部傳送數據時,這種加密方式更方便,如: RSA。
4)數字證書(Certificate):數字證書是一種非對稱密鑰加密,但是,一個組織可以使用證書並通過數字簽名將一組公鑰和私鑰與其擁有者相關聯。
五、對稱加密之DES加密與解密
5.1對稱加密簡述
對稱加密,是一種比較傳統的加密方式,其加密運算、解密運算使用的是同樣的密鑰,信息的發送者和信息的接收者在進行信息的傳輸與處理時,必須共
同持有該密碼(稱為對稱密碼)。因此,通信雙方都必須獲得這把鑰匙,並保持鑰匙的秘密。
單鑰密碼系統的安全性依賴於以下兩個因素:
第一、加密演算法必須是足夠強,僅僅基於密文本身去解密信息在實踐上是不可能的。
第二、加密方法的安全性依賴於密鑰的秘密性,而不是演算法的秘密性,因此,我們沒有必要確保演算法的秘密性(事實上,現實中使用的很多單鑰密碼系統
的演算法都是公開的),但是我們一定要保證密鑰的秘密性。
DES(Data Encryption Standard)和TripleDES是對稱加密的兩種實現:
1)DES和TripleDES基本演算法一致,只是TripleDES演算法提供的key位數更多,加密可靠性更高。
2)DES使用的密鑰key為8位元組,初始向量IV也是8位元組。
3)TripleDES的密鑰key為24位元組,初始向量IV也是8位元組。
4)兩種演算法都是以8位元組為一個塊進行加密,一個數據塊一個數據塊的加密,一個8位元組的明文加密後的密文也是8位元組。如果明文長度不為8位元組的整數
倍,添加值為0的位元組湊滿8位元組整數倍,所以加密後的密文長度一定為8位元組的整數倍。
5.2加密解密過程
上圖是整個DES和TripleDES演算法的加密解密過程,下麵以TripleDES為例,結合dotnet分析加密解密的各個步驟,並給出相關實現代碼。
5.2.1生成Key和IV
System.Security.Cryptography.TripleDESCryptoServiceProvider類是.NET中實現TripleDES演算法的主要類。
TripleDESCryptoServiceProvider類只有一個構造方法TripleDESCryptoServiceProvider(),這個方法把一些屬性初始化:
KeySize(加密密鑰長度,以位為單位)= 192(24位元組)
BlockSize(加密處理的數據塊大小,以位為單位)= 64(8位元組)
FeedbackSize(加密數據塊後返回的數據大小,以位為單位)= 64(8位元組)
TripleDESCryptoServiceProvider構造方法同時會初始化一組隨機的Key和IV。
預設的TripleDESCryptoServiceProvider的Key為24位元組,IV為8位元組,加密數據塊為8位元組。
生成Key和IV的代碼很簡單:
TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); byte[] keyArray = tripleDES.Key; byte[] ivArray = tripleDES.IV;
5.2.2字元串明文轉成編碼位元組流
待加密的數據可能有兩種形式:一種是二進位的數據,本身就是一組位元組流,這樣的數據可以跳過這一步,直接進入加密步驟;還有一種情況是字元串數
據,字元串中同樣的字元使用不同的編碼會生成不同的位元組碼,所以從字元串到位元組流的轉換是需要指定使用的編碼。在解密之後,要從位元組流轉換到字元
串就要使用相同的編碼解碼,否則會出現亂碼。
//待加密的字元串 string plainTextString = "Here is some data to encrypt."; //使用utf-8編碼(也可以使用其它的編碼) Encoding encoding = Encoding.GetEncoding("utf-8"); //把字元串明文轉換成utf-8編碼的位元組流 byte[] plainTextArray = encoding.GetBytes(plainTextString);
5.2.3加密操作
加密的原料是明文位元組流,TripleDES演算法對位元組流進行加密,返回的是加密後的位元組流,同時要給定加密使用的Key和IV。
/// <summary> /// 加密解密幫助類 /// </summary> public static class CryptoHelper { /// <summary> /// 對稱加密之TripleDes加密 /// </summary> /// <param name="plainTextArray">明文位元組數組</param> /// <param name="Key">Key</param> /// <param name="IV">IV</param> /// <returns>返回位元組數組</returns> public static byte[] TripleDesEncrypt(string plainText, byte[] Key, byte[] IV) { //將明文字元串轉成明文位元組數組 Encoding encoding = Encoding.GetEncoding("utf-8"); byte[] plainTextArray = encoding.GetBytes(plainText); //新建一個MemoryStream對象存放加密後的數據流 MemoryStream memoryStream = new MemoryStream(); //新建一個CryptoStream對象 CryptoStream cryptoStream = new CryptoStream ( memoryStream, new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV), CryptoStreamMode.Write ); //將加密後的位元組流寫入到memoryStream cryptoStream.Write(plainTextArray, 0, plainTextArray.Length); //把緩衝區中的最後狀態更新到memoryStream,並清除cryptoStream的緩存區。 cryptoStream.FlushFinalBlock(); //把加密後的數據流轉成位元組流 byte[] result = memoryStream.ToArray(); //關閉兩個Stream cryptoStream.Close(); memoryStream.Close(); //返回結果 return result; } }View Code
5.2.4解密操作
解密5.2.3生成的密文byte[],需要使用到加密步驟使用的同一組Key和IV。
/// <summary> /// 加密解密幫助類 /// </summary> public static class CryptoHelper { /// <summary> /// 對稱加密之TripleDes解密 /// </summary> /// <param name="encryptTextArray">加密位元組數組</param> /// <param name="Key">Key</param> /// <param name="IV">IV</param> /// <returns>返回字元串</returns> public static string TripleDesDecrypt(byte[] encryptTextArray, byte[] Key, byte[] IV) { //將加密字元串轉成加密位元組數組 Encoding encoding = Encoding.GetEncoding("utf-8"); //新建一個MemoryStream對象存放解密後的數據流 MemoryStream memoryStream = new MemoryStream(encryptTextArray); //新建一個CryptoStream對象 CryptoStream cryptoStream = new CryptoStream ( memoryStream, new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV), CryptoStreamMode.Read ); //新建一個存放解密後的明文位元組數組(可能比加密前的明文長) byte[] decryptTextArray = new byte[encryptTextArray.Length]; //把解密後的數據流讀到 cryptoStream.Read(decryptTextArray, 0, decryptTextArray.Length); //關閉兩個Stream memoryStream.Close(); cryptoStream.Close(); return encoding.GetString(decryptTextArray); } }View Code
有一點需要註意,DES加密是以數據塊為單位加密的,8個位元組一個數據塊。如果待加密明文byte[]的長度不是8位元組的整數倍,演算法先用值為“0”的byte補
足8個位元組,然後再進行加密,所以加密後的密文長度一定是8的整數倍。這樣的密文解密後如果補了0值的byte,則解密後這些0值的byte依然存在。
5.2.5示例
class Program { static void Main(string[] args) { #region 對稱加密之TripleDes加密與解密 //明文數據 string plainText = "人生如戲,全靠演技。"; //生成Key和IV TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); byte[] keyArray = tripleDES.Key; byte[] ivArray = tripleDES.IV; //加密 byte[] encryptTextArray = CryptoHelper.TripleDesEncrypt(plainText, keyArray, ivArray); //解密 string decryptText = CryptoHelper.TripleDesDecrypt(encryptTextArray, keyArray, ivArray); //輸出 Console.WriteLine($"明文數據:{plainText}"); Console.WriteLine($"解密後數據:{decryptText}"); Console.Read(); #endregion } }View Code
運行結果如下:
六、非對稱加密之RSA加密和解密的講解
RSA公鑰加密演算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。RSA是目
前最有影響力的公鑰加密演算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰數據加密標準;RSA演算法基於一個十分簡單的數論事實:
將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰;RSA演算法是第一個能同時用於加密和數字簽
名的演算法,也易於理解和操作。
RSA演算法是被研究得最廣泛的公鑰演算法,從提出到現在已近二十年,經歷了各種攻擊的考驗,逐漸為人們所接受,被普遍認為是目前最優秀的公鑰方案之
一。RSA的安全性依賴於大數的因數分解,但並沒有從理論上證明破譯RSA的難度與大數分解難度等價,即RSA的重大缺陷是無法從理論上把握它的保密性
能如何,而且密碼學界多數人士傾向於因數分解不是NPC問題。
RSA的缺點主要有:
1)產生密鑰很麻煩,受到素數產生技術的限制,因而難以做到一次一密。
2)分組長度太大,為保證安全性,n至少也要600bits以上,導致運算代價很高,尤其是速度較慢(較對稱密碼演算法慢幾個數量級),且隨著大數分解技術
的發展,這個長度還在增加,不利於數據格式的標準化。目前,SET(Secure Electronic Transaction)協議中要求CA採用2048bits長的密鑰,其它實體使用
1024比特的密鑰。
3)RSA密鑰長度隨著保密級別提高,增加很快。
下表列出了對同一安全級別所對應的密鑰長度:
保密級別 |
對稱密鑰長度(bit) |
RSA密鑰長度(bit) |
ECC密鑰長度(bit) |
保密年限 |
80 |
80 |
1024 |
160 |
2010 |
112 |
112 |
2048 |
224 |
2030 |
128 |
128 |
3072 |
256 |
2040 |
192 |
192 |
7680 |
384 |
2080 |
256 |
256 |
15360 |
512 |
2120 |
RSA演算法是一種非對稱密碼演算法,所謂非對稱,就是指該演算法需要一對密鑰,使用其中一個加密,則需要用另一個才能解密。
RSA的演算法涉及三個參數n、e1、e2:
1)n是兩個大質數p、q的積,n的二進位表示時所占用的位數,就是所謂的密鑰長度。
2)e1和e2是一對相關的值,e1可以任意取,但要求e1與(p-1)*(q-1)互質,再選擇e2,要求(e2*e1)mod((p-1)*(q-1))=1。
3)(n及e1)、(n及e2)就是密鑰對。
RSA加解密的演算法完全相同,設A為明文,B為密文,則:A=B^e1 mod n;B=A^e2 mod n;
e1和e2可以互換使用,即:A=B^e2 mod n;B=A^e1 mod n;
6.1生成一對公鑰和密鑰
/// <summary> /// 加密解密幫助類 /// </summary> public static class CryptoHelper { /// <summary> /// 非對稱加密之RSA產生公鑰密鑰 /// </summary> public static void RSACreateKey() { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); //公鑰 using (StreamWriter writer = new StreamWriter(@"..\..\PublicKey.xml")) { writer.WriteLine(rsa.ToXmlString(false)); } //密鑰(請註意保密) using (StreamWriter writer = new StreamWriter(@"..\..\PrivateKey.xml")) { writer.WriteLine(rsa.ToXmlString(true)); } } }View Code
6.2加密操作
/// <summary> /// 加密解密幫助類 /// </summary> public static class CryptoHelper { /// <summary> /// 非對稱加密之RSA加密 /// </summary> /// <param name="publickey">公鑰</param> /// <param name="plainText">明文字元串</param> /// <returns>加密字元串</returns> public static string RSAEncrypt(string publickey, string plainText) { StreamReader reader = new StreamReader(@"..\..\PublicKey.xml", Encoding.UTF8); publickey = reader.ReadToEnd(); reader.Close(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(publickey); byte[] cipherBytes = rsa.Encrypt(Encoding.UTF8.GetBytes(plainText), false); return Convert.ToBase64String(cipherBytes); } }View Code
6.3解密操作
/// <summary> /// 加密解密幫助類 /// </summary> public static class CryptoHelper { /// <summary> /// 非對稱加密之RSA解密 /// </summary> /// <param name="privatekey">密鑰</param> /// <param name="encryptText">加密字元串</param> /// <returns>解密字元串</returns> public static string RSADecrypt(string privatekey, string encryptText) { StreamReader reader = new StreamReader(@"..\..\PrivateKey.xml", Encoding.UTF8); privatekey = reader.ReadToEnd(); reader.Close(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(privatekey); byte[] cipherBytes = rsa.Decrypt(Convert.FromBase64String(encryptText), false); return Encoding.UTF8.GetString(cipherBytes); } }View Code
6.4示例
class Program { static void Main(string[] args) { #region 非對稱加密之RSA加密與解密 //明文數據 string plainText = "人生如戲,全靠演技。"; //生成公鑰和密鑰 CryptoHelper.RSACreateKey(); //加密 string encryptText = CryptoHelper.RSAEncrypt("", plainText); //解密 string decryptText = CryptoHelper.RSADecrypt("", encryptText); Console.WriteLine($"明文數據:{plainText}\n"); Console.WriteLine($"加密後數據:{encryptText}\n"); Console.WriteLine($"解密後數據:{decryptText}"); Console.Read(); #endregion } }View Code
運行結果如下: