加密解密算法以及對應.Net實現

引言

最近在倒弄數據存儲傳輸過程當中的加密解密方法,本文不是筆者親身研究所得,而是對幾篇博客中的知識點的學習摘抄記錄,以做總結。

加密解密

說到加密,可能你們最熟悉的就是MD5了,它的用戶密碼就是採用的MD5進行加密。MD5實際上只是一種散列運算,或者能夠稱爲單向的加密,
便是說沒法根據密文(加密後的數據),推導出明文(原數據)。那麼加密是什麼呢?加密是經過對消息進行編碼,創建一種安全的交流方式,
使得只有你和你所指望的接收者可以理解。那麼怎麼樣才能叫安全呢?消息在接收方和發送方進行安全傳遞,通常要知足下面三個要點:
  1. 消息的發送方可以肯定消息只有預期的接收方能夠解密(不保證第三方沒法得到,但保證第三方沒法解密)。
  2. 消息的接收方能夠肯定消息是由誰發送的(消息的接收方能夠肯定消息的發送方)。
  3. 消息的接收方能夠肯定消息在途中沒有被篡改過(必須確認消息的完整性)。
加密一般分爲兩種方式:對稱加密和非對稱加密,接下來咱們先看看對稱加密。

對稱加密

對稱加密的思路很是簡單,就是含有一個稱爲密鑰的東西,在消息發送前使用密鑰對消息進行加密,在對方收到消息以後,使用相同的密鑰進行
解密。根據密鑰來產生加密後的消息(密文)的這一加工過程,由加密算法來完成,加密算法一般是公開的。它的流程以下:
  1. 發送方使用密鑰對消息進行加密。
  2. 接收方使用一樣的密鑰對消息進行解密。
可使用下面一副圖來表示:
對稱加密
對稱加密存在這樣兩個問題:
  1. 雖然能夠經過密鑰來保證消息安全地進行傳遞,可是如何確保密鑰安全地進行傳遞?由於發送者和接收者總有一次初始的通訊,用來傳遞密鑰,此時的安全如何保證?
  2. 接收者雖然能夠根據密鑰來解密消息,但由於存在上面的問題,消息有多是由第三方(非法得到密鑰)發來的,而接收方沒法辨別。
爲了解決上面兩個問題,就須要介紹一下非對稱加密。

非對稱加密

非對稱加密的接收者和發送者都持有兩個密鑰,一個是對外公開的,稱爲公鑰,一個是自行保管的,稱爲私鑰。非對稱加密的規則是由某人A的公鑰加密的消息,只能由A的私鑰進行解密;由A的私鑰加密的消息只能由A的公鑰解密。此時咱們能夠得出接收方、發送方有兩個公鑰兩個私鑰一共四個密鑰,咱們先看看兩種簡單的方式,這兩種方式都是隻使用兩個密鑰。
第一種模式只使用接收方的公鑰和私鑰,稱爲加密模式。
在加密模式中,由消息的接收方發佈公鑰,持有私鑰。好比發送方要發送消息「hello,jimmy」到接收方,它的步驟是:
  1. 發送方使用接收者的公鑰進行加密消息,而後發送。
  2. 接收方使用本身的私鑰對消息進行解密。
可使用下面一幅圖來描述:
非對稱加密
在這種模式下,若是第三方截獲了發送者發出的消息,由於他沒有接收者的私鑰,因此這個消息對他來講毫無心義。可見,它可以知足本文最開始提出的消息安全傳遞的要點一:消息的發送方可以肯定消息只有預期的接收方能夠解密(不保證第三方沒法得到,但保證第三方沒法解密)。
除此之外,由於接收方的公鑰是公開的,任何人均可以使用這個公鑰來加密消息併發往接收者,而接收者沒法對消息進行判別,沒法知道是由誰發送來的。因此,它不知足咱們開始提出的消息安全傳遞的要點二:消息的接收方能夠肯定消息是由誰發送的(消息的接收方能夠肯定消息的發送方)。
這個問題能夠在下面的認證模式中獲得解決。
第二種模式只使用發送方的公鑰和私鑰,稱爲認證模式。
在認證模式中,由消息的發送方發佈公鑰,持有私鑰。好比發送者要發送消息「Welcome to Tracefact.net」到接收者,它的步驟是:
  1. 發送者使用本身的私鑰對消息進行加密,而後發送。
  2. 接收者使用發送者的公鑰對消息進行解密。
能夠用下面一副圖來表述:
認證模式
在這種模式下,假如發送方叫作Ken,接收方叫作Matthew,由於Matthew只能使用Ken的公鑰對消息進行解密,而沒法使用Molly、Sandy或者任何其餘人公鑰對消息進行解密,因此他必定可以肯定消息是由Ken發送來的。所以,這個模式知足了前面提出的消息安全傳遞的要點二。
與此同時,由於Ken的公鑰是公開的,任何截獲了該消息的第三方都可以使用Ken的公鑰來對消息進行解密,換言之,消息如今是不安全的。所以,與加密模式正好相反,它沒法知足前面提出的消息安全傳遞的要點一。
而無論是採用加密模式仍是認證模式,都沒有解決加密解密中的要點三:接收方必須可以確認消息沒有被改動過。爲了解決這個問題,又引入了數字簽名。

數字簽名

數字簽名實際上就是上面非對稱加密時的認證模式,只不過作了一點點的改進,加入了散列算法。你們比較熟悉的散列算法可能就是MD5了,不少開源論壇都採用了這個算法。散列算法有三個特色:一是不可逆的,由結果沒法推算出原數據;二是原數據哪怕是一丁點兒的變化,都會使散列值產生巨大的變化;三是不論多麼大或者多麼少的數據,總會產生固定長度的散列值(常見的爲32位64位)。產生的散列值一般稱爲消息的摘要(digest)。
那麼如何經過引入散列函數來保證數據的完整性呢?也就是接收方可以確認消息確實是由發送方發來的,而沒有在中途被修改過。具體的過程以下:
  1. 發送方將想要進行傳遞的消息進行一個散列運算,獲得消息摘要。
  2. 發送方使用本身的私鑰對摘要進行加密,將消息和加密後的摘要發送給接收方。
  3. 接收方使用發送方的公鑰對消息和消息摘要進行解密(確認了發送方)。
  4. 接收方對收到的消息進行散列運算,獲得一個消息摘要。
  5. 接收方將上一步得到的消息摘要與發送方發來的消息摘要進行對比。若是相同,說明消息沒有被改動過;若是不一樣,說明消息已經被篡改。
這個過程能夠用下面的一副圖來表述:
數字簽名
咱們能夠看出,數字簽名經過引入散列算法,將非對稱加密的認證模式又增強了一步,確保了消息的完整性。除此之外,注意到上面的非對稱加密算法,只是對消息摘要進行了加密,而沒有對消息自己進行加密。非對稱加密是一個很是耗時的操做,因爲只對消息摘要加密,使得運算量大幅減小,因此這樣可以顯著地提升程序的執行速度。同時,它依然沒有確保消息不被第三方截獲到,不只如此,由於此時消息是以明文進行傳遞,第三方甚至不須要發送方的公鑰,就能夠直接查看消息。
爲了解決這樣的問題,只須要將非對稱加密的認證模式、加密模式以及消息摘要進行一個結合就能夠了,這也就是下面的高級模式。

高級實現

因爲這個過程比上面稍微複雜了一些,咱們將其分爲發送方和接收方兩部分來看。先看看發送方須要執行的步驟:
  1. 將消息進行散列運算,獲得消息摘要。
  2. 使用本身的私鑰對消息摘要加密(認證模式:確保了接收方可以確認本身)。
  3. 使用接收方的公鑰對消息進行加密(加密模式:確保了消息只能由指望的接收方解密)。
  4. 發送消息和消息摘要。
接下來咱們看一下接收方所執行的步驟:
  1. 使用發送方的公鑰對消息摘要進行解密(確認了消息是由誰發送的)。
  2. 使用本身的私鑰對消息進行解密(安全地得到了實際應得到的信息)。
  3. 將消息進行散列運算,得到消息摘要。
  4. 將上一步得到的消息摘要 和 第一步解密的消息摘要進行對比(確認了消息是否被篡改)。
能夠看到,經過上面這種方式,使用了接收方、發送方所有的四個密鑰,再配合使用消息摘要,使得前面提出的安全傳遞的全部三個條件全都知足了。那麼是否是這種方法就是最好的呢?不是的,由於咱們已經說過了,非對稱加密是一種很耗時的操做,因此這個方案是很低效的。實際上,咱們能夠經過它來解決對稱加密中的密鑰傳遞問題,若是你已經忘記了能夠翻到前面再看一看,也就是說,咱們可使用這裏的高級實現方式來進行對稱加密中密鑰的傳遞,對於以後實際的數據傳遞,採用對稱加密方式來完成,由於此時已是安全的了。

證書機制

與數字簽名相關的一個概念就是證書機制了,證書是用來作什麼呢?在上面的各類模式中,咱們一直使用了這樣一個假設,就是接收方或者發送方所持有的、對方的公鑰老是正確的(確實是對方公佈的)。而實際上除非對方手把手將公鑰交給咱們,不然若是不採起措施,雙方在網絡中傳遞公鑰時,同樣有可能被篡改。那麼怎樣解決這個問題呢?這時就須要證書機制了:能夠引入一個公正的第三方,當某一方想要發佈公鑰時,它將自身的身份信息及公鑰提交給這個第三方,第三方對其身份進行證明,若是沒有問題,則將其信息和公鑰打包成爲證書(Certificate)。而這個公正的第三方,就是常說的證書頒發機構(Certificate Authority)。當咱們須要獲取公鑰時,只須要得到其證書,而後從中提取出公鑰就能夠了。

常見的加密解密方法

加密解密方法不少,經過對字節流的操做,也很容易的實現自定義的加密解密方法。常見的加密解密方法大體以下:

一、經常使用密鑰算法

密鑰算法用來對敏感數據、摘要、簽名等信息進行加密,經常使用的密鑰算法包括:
DES(Data Encryption Standard):數據加密標準,速度較快,適用於加密大量數據的場合; 
3DES(Triple DES):是基於DES,對一塊數據用三個不一樣的密鑰進行三次加密,強度更高; 
RC2和 RC4:用變長密鑰對大量數據進行加密,比 DES 快; 
IDEA(International Data Encryption Algorithm)國際數據加密算法,使用 128 位密鑰提供很是強的安全性; 
RSA:由 RSA 公司發明,是一個支持變長密鑰的公共密鑰算法,須要加密的文件快的長度也是可變的;
DSA(Digital Signature Algorithm):數字簽名算法,是一種標準的 DSS(數字簽名標準); 
AES(Advanced Encryption Standard):高級加密標準,是下一代的加密算法標準,速度快,安全級別高,目前 AES 標準的一個實現是 Rijndael 算法; 
BLOWFISH,它使用變長的密鑰,長度可達448位,運行速度很快; 
其它算法,如ElGamal、Deffie-Hellman、新型橢圓曲線算法ECC等。

二、單向散列算法

單向散列函數通常用於產生消息摘要,密鑰加密等,常見的有:
MD5(Message Digest Algorithm 5):是RSA數據安全公司開發的一種單向散列算法,MD5被普遍使用,能夠用來把不一樣長度的數據塊進行暗碼運算成一個128位的數值; 
SHA(Secure Hash Algorithm)這是一種較新的散列算法,能夠對任意長度的數據運算生成一個160位的數值; 
MAC(Message Authentication Code):消息認證代碼,是一種使用密鑰的單向函數,能夠用它們在系統上或用戶之間認證文件或消息。HMAC(用於消息認證的密鑰散列法)就是這種函數的一個例子。 
CRC(Cyclic Redundancy Check):循環冗餘校驗碼,CRC校驗因爲實現簡單,檢錯能力強,被普遍使用在各類數據校驗應用中。佔用系統資源少,用軟硬件均能實現,是進行數據傳輸差錯檢測地一種很好的手段(CRC 並非嚴格意義上的散列算法,但它的做用與散列算法大體相同,因此歸於此類)。

三、其它數據算法

其它數據算法包括一些經常使用編碼算法及其與明文(ASCII、Unicode 等)轉換等,如 Base 6四、Quoted Printable、EBCDIC 等。

.Net中加密解密的支持

常見的加密和編碼算法都已經在 .NET Framework中獲得了實現,爲編碼人員提供了極大的便利性,實現這些算法的名稱空間是:System.Security.Cryptography。System.Security.Cryptography 命名空間提供加密服務,包括安全的數據編碼和解碼,以及許多其餘操做,例如散列法、隨機數字生成和消息身份驗證,按照對稱與非對稱的分類方式,大體以下圖所示:
.Net加密
上面的類按照名稱還能夠分爲兩組,一組後綴爲「CryptoServiceProvider」的,是對於底層Windows API的包裝類,一組後綴爲「Managed」,是在.NET中全新編寫的類。下面咱們對.Net中支持的加密方式作進一步介紹。

一、私鑰加密

私鑰加密又稱爲對稱加密,由於同一密鑰既用於加密又用於解密。私鑰加密算法很是快(與公鑰算法相比),特別適用於對較大的數據流執行加密轉換。.NET Framework 提供如下實現私鑰加密算法的類:
DES:DESCryptoServiceProvider 
RC2:RC2CryptoServiceProvider 
Rijndael(AES):RijndaelManaged 
3DES:TripleDESCryptoServiceProvider

二、公鑰加密和數字簽名

公鑰加密使用一個必須對未經受權的用戶保密的私鑰和一個能夠對任何人公開的公鑰。用公鑰加密的數據只能用私鑰解密,而用私鑰簽名的數據只能用公鑰驗證。公鑰能夠被任何人使用;該密鑰用於加密要發送到私鑰持有者的數據。兩個密鑰對於通訊會話都是惟一的。公鑰加密算法也稱爲不對稱算法,緣由是須要用一個密鑰加密數據而須要用另外一個密鑰來解密數據。.NET Framework 提供如下實現公鑰加密算法的類: 
DSA:DSACryptoServiceProvider 
RSA:RSACryptoServiceProvider 

三、哈希(Hash)值

哈希算法將任意長度的二進制值映射爲固定長度的較小二進制值,這個小的二進制值稱爲哈希值。哈希值是一段數據惟一且極其緊湊的數值表示形式。若是散列一段明文並且哪怕只更改該段落的一個字母,隨後的哈希都將產生不一樣的值。要找到散列爲同一個值的兩個不一樣的輸入,在計算上是不可能的,因此數據的哈希值能夠檢驗數據的完整性。.NET Framework 提供如下實現數字簽名算法的類: 
HMAC:HMACSHA1 (HMAC 爲一種使用密鑰的 Hash 算法) 
MAC:MACTripleDES 
MD5:MD5CryptoServiceProvider 
SHA1:SHA1Managed、SHA256Managed、SHA384Managed、SH7747.net12Managed

四、隨機數生成

加密密鑰須要儘量地隨機,以便使生成的密鑰很難再現,因此隨機數生成是許多加密操做不可分割的組成部分。在 .NET Framework 中,RNGCryptoServiceProvider 是隨機數生成器算法的實現,對於數據算法,.NET Framework 則在其它命名空間中實現,如 Convert 類實現 Base 64 編碼,System.Text 來實現編碼方式的轉換等。

從以上來看,.NET Framework 對於數據加密/編碼仍是支持比較好,大大地方便了開發人員,但美中不足的是,.NET Framework 中的數據加密算法仍然不夠徹底,如 IDEA、BLOWFISH、其它算法,如ElGamal、Deffie-Hellman、ECC 等,對於一些其它的數據校驗算法支持也不夠,如 CRC、SFV 等,開發人員只能去從早期代碼作移植或者尋找第三方廠商的實現。

.Net加密示例

爲了更好的理解.Net中的加密解密方法的運用,咱們經過代碼示例來了解。

MD5加密

MD5全稱是message-digest algorithm 5,簡單的說就是單向的加密,便是說沒法根據密文推導出明文。MD5主要用途:
  1. 對一段信息生成信息摘要,該摘要對該信息具備惟一性,能夠做爲數字簽名。
  2. 用於驗證文件的有效性(是否有丟失或損壞的數據),
  3. 對用戶密碼的加密,
  4. 在哈希函數中計算散列值
從上邊的主要用途中咱們看到,因爲算法的某些不可逆特徵,在加密應用上有較好的安全性。經過使用MD5加密算法,咱們輸入一個任意長度的字節串,都會生成一個128位的整數。因此根據這一點MD5被普遍的用做密碼加密。

示例:html

        public string GetMD5_32(string s, string _input_charset)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(Encoding.GetEncoding(_input_charset).GetBytes(s));
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
            {
                sb.Append(t[i].ToString("x").PadLeft(2, '0'));//ToString("x")爲十六進制表示,詳細參考:https://msdn.microsoft.com/zh-cn/library/dwhawy9k
            }
            return sb.ToString();
        }
        public string GetMD5_16(string ConvertString)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);
            t2 = t2.Replace("-", "");
            return t2;
        }


SHA1加密

安全哈希算法(Secure Hash Algorithm)主要適用於數字簽名標準(Digital Signature Standard DSS)裏面定義的數字簽名算法(Digital Signature Algorithm DSA)。對於長度小於2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要能夠用來驗證數據的完整性。在傳輸的過程當中,數據極可能會發生變化,那麼這時候就會產生不一樣的消息摘要。
示例:
        /// <summary>
        /// use sha1 to encrypt string
        /// </summary>
        public string SHA1_Encrypt(string Source_String)
        {
            byte[] StrRes = Encoding.Default.GetBytes(Source_String);
            HashAlgorithm iSHA = new SHA1CryptoServiceProvider();
            StrRes = iSHA.ComputeHash(StrRes);
            StringBuilder EnText = new StringBuilder();
            foreach (byte iByte in StrRes)
            {
                EnText.AppendFormat("{0:x2}", iByte);
            }
            return EnText.ToString();
        }

DES加密、解密

DES加密是對稱加密,它使用一個 56 位的密鑰以及附加的 8 位奇偶校驗位,產生最大 64 位的分組大小。這是一個迭代的分組密碼,使用稱爲 Feistel 的技術,其中將加密的文本塊分紅兩半。使用子密鑰對其中一半應用循環功能,而後將輸出與另外一半進行「異或」運算;接着交換這兩半,這一過程會繼續下去,但最後一個循環不交換。DES 使用 16 個循環,使用異或,置換,代換,移位操做四種基本運算。
示例:
        /// <summary>
        /// DES加密方法
        /// </summary>
        /// <param name="strPlain">明文</param>
        /// <param name="strDESKey">密鑰</param>
        /// <param name="strDESIV">向量</param>
        /// <returns>密文</returns>
        public string DESEncrypt(string strPlain, string strDESKey, string strDESIV)
        {
            //把密鑰轉換成字節數組
            byte[] bytesDESKey = ASCIIEncoding.ASCII.GetBytes(strDESKey);
            //把向量轉換成字節數組
            byte[] bytesDESIV = ASCIIEncoding.ASCII.GetBytes(strDESIV);
            //聲明1個新的DES對象
            DESCryptoServiceProvider desEncrypt = new DESCryptoServiceProvider();
            //開闢一塊內存流
            MemoryStream msEncrypt = new MemoryStream();
            //把內存流對象包裝成加密流對象
            CryptoStream csEncrypt = new CryptoStream(msEncrypt, desEncrypt.CreateEncryptor(bytesDESKey, bytesDESIV), CryptoStreamMode.Write);
            //把加密流對象包裝成寫入流對象
            StreamWriter swEncrypt = new StreamWriter(csEncrypt);
            //寫入流對象寫入明文
            swEncrypt.WriteLine(strPlain);
            //寫入流關閉
            swEncrypt.Close();
            //加密流關閉
            csEncrypt.Close();
            //把內存流轉換成字節數組,內存流如今已是密文了
            byte[] bytesCipher = msEncrypt.ToArray();
            //內存流關閉
            msEncrypt.Close();
            //把密文字節數組轉換爲字符串,並返回
            return UnicodeEncoding.Unicode.GetString(bytesCipher);
        }

        /// <summary>
        /// DES解密方法
        /// </summary>
        /// <param name="strCipher">密文</param>
        /// <param name="strDESKey">密鑰</param>
        /// <param name="strDESIV">向量</param>
        /// <returns>明文</returns>
        public string DESDecrypt(string strCipher, string strDESKey, string strDESIV)
        {
            //把密鑰轉換成字節數組
            byte[] bytesDESKey = ASCIIEncoding.ASCII.GetBytes(strDESKey);
            //把向量轉換成字節數組
            byte[] bytesDESIV = ASCIIEncoding.ASCII.GetBytes(strDESIV);
            //把密文轉換成字節數組
            byte[] bytesCipher = UnicodeEncoding.Unicode.GetBytes(strCipher);
            //聲明1個新的DES對象
            DESCryptoServiceProvider desDecrypt = new DESCryptoServiceProvider();
            //開闢一塊內存流,並存放密文字節數組
            MemoryStream msDecrypt = new MemoryStream(bytesCipher);
            //把內存流對象包裝成解密流對象
            CryptoStream csDecrypt = new CryptoStream(msDecrypt, desDecrypt.CreateDecryptor(bytesDESKey, bytesDESIV), CryptoStreamMode.Read);
            //把解密流對象包裝成讀出流對象
            StreamReader srDecrypt = new StreamReader(csDecrypt);
            //明文=讀出流的讀出內容
            string strPlainText = srDecrypt.ReadLine();
            //讀出流關閉
            srDecrypt.Close();
            //解密流關閉
            csDecrypt.Close();
            //內存流關閉
            msDecrypt.Close();
            //返回明文
            return strPlainText;
        } 

RSA加密解密


RSA加密算法是一種非對稱加密算法。在公鑰加密標準和電子商業中RSA被普遍使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一塊兒提出的。當時他們三人都在麻省理工學院工做。RSA就是他們三人姓氏開頭字母拼在一塊兒組成的。
  RSA算法的可靠性基於分解極大的整數是很困難的。假若有人找到一種很快的分解因子的算法的話,那麼用RSA加密的信息的可靠性就確定會極度降低。但找到這樣的算法的可能性是很是小的。今天只有短的RSA鑰匙纔可能被強力方式解破。到2008年爲止,世界上尚未任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息其實是不能被解破的。
示例(來自MSDN):
using System;
using System.Security.Cryptography;
using System.IO; 
using System.Text;

namespace Microsoft.Samples.Security.PublicKey
{
  class App
  {
    // Main entry point
    static void Main(string[] args)
    {
      // Instantiate 3 People for example. See the Person class below
      Person alice = new Person("Alice");
      Person bob = new Person("Bob");
      Person steve = new Person("Steve");

      // Messages that will exchanged. See CipherMessage class below
      CipherMessage aliceMessage;
      CipherMessage bobMessage;
      CipherMessage steveMessage;

      // Example of encrypting/decrypting your own message
      Console.WriteLine("Encrypting/Decrypting Your Own Message");
      Console.WriteLine("-----------------------------------------");

      // Alice encrypts a message using her own public key
      aliceMessage = alice.EncryptMessage("Alice wrote this message");
      // then using her private key can decrypt the message
      alice.DecryptMessage(aliceMessage);
      // Example of Exchanging Keys and Messages
      Console.WriteLine();
      Console.WriteLine("Exchanging Keys and Messages");
      Console.WriteLine("-----------------------------------------");

      // Alice Sends a copy of her public key to Bob and Steve
      bob.GetPublicKey(alice);
      steve.GetPublicKey(alice);

      // Bob and Steve both encrypt messages to send to Alice
      bobMessage = bob.EncryptMessage("Hi Alice! - Bob.");
      steveMessage = steve.EncryptMessage("How are you? - Steve");

      // Alice can decrypt and read both messages
      alice.DecryptMessage(bobMessage);
      alice.DecryptMessage(steveMessage);

      Console.WriteLine();
      Console.WriteLine("Private Key required to read the messages");
      Console.WriteLine("-----------------------------------------");

      // Steve cannot read the message that Bob encrypted
      steve.DecryptMessage(bobMessage);
      // Not even Bob can use the Message he encrypted for Alice.
      // The RSA private key is required to decrypt the RS2 key used
      // in the decryption.
      bob.DecryptMessage(bobMessage);

    } // method Main
  } // class App

  class CipherMessage
  {
    public byte[] cipherBytes;  // RC2 encrypted message text
    public byte[] rc2Key;       // RSA encrypted rc2 key
    public byte[] rc2IV;        // RC2 initialization vector
  }

  class Person
  {
    private RSACryptoServiceProvider rsa;
    private RC2CryptoServiceProvider rc2;
    private string name;

    // Maximum key size for the RC2 algorithm
    const int keySize = 128;

    // Person constructor
    public Person(string p_Name)
    {
      rsa = new RSACryptoServiceProvider();
      rc2 = new RC2CryptoServiceProvider();
      rc2.KeySize = keySize;
      name = p_Name;
    }

    // Used to send the rsa public key parameters
    public RSAParameters SendPublicKey() 
    {
      RSAParameters result = new RSAParameters();
      try 
      {
        result = rsa.ExportParameters(false);
      }
      catch (CryptographicException e)
      {
        Console.WriteLine(e.Message);
      }
      return result;
    }

    // Used to import the rsa public key parameters
    public void GetPublicKey(Person receiver)
    {
      try 
      {
        rsa.ImportParameters(receiver.SendPublicKey()); 
      }
      catch (CryptographicException e)
      {
        Console.WriteLine(e.Message);
      }
    }

    public CipherMessage EncryptMessage(string text)
    {
      // Convert string to a byte array
      CipherMessage message = new CipherMessage();
      byte[] plainBytes = Encoding.Unicode.GetBytes(text.ToCharArray());

      // A new key and iv are generated for every message
      rc2.GenerateKey();
      rc2.GenerateIV();

      // The rc2 initialization doesnt need to be encrypted, but will
      // be used in conjunction with the key to decrypt the message.
      message.rc2IV = rc2.IV;
      try 
      {
        // Encrypt the RC2 key using RSA encryption
        message.rc2Key = rsa.Encrypt(rc2.Key, false);
      }
      catch (CryptographicException e)
      {
        // The High Encryption Pack is required to run this  sample
        // because we are using a 128-bit key. See the readme for
        // additional information.
        Console.WriteLine("Encryption Failed. Ensure that the" + 
          " High Encryption Pack is installed.");
        Console.WriteLine("Error Message: " + e.Message);
        Environment.Exit(0);
      }
      // Encrypt the Text Message using RC2 (Symmetric algorithm)
      ICryptoTransform sse = rc2.CreateEncryptor();
      MemoryStream ms = new MemoryStream();
      CryptoStream cs = new CryptoStream(ms, sse, CryptoStreamMode.Write);
      try
      {
          cs.Write(plainBytes, 0, plainBytes.Length);
          cs.FlushFinalBlock();
          message.cipherBytes = ms.ToArray();
      }
      catch (Exception e)
      {
          Console.WriteLine(e.Message);
      }     
      finally
      {
        ms.Close();
        cs.Close();
      }
      return message;
    } // method EncryptMessage


    public void DecryptMessage(CipherMessage message)
    {
      // Get the RC2 Key and Initialization Vector
      rc2.IV = message.rc2IV;
      try 
      {
        // Try decrypting the rc2 key
        rc2.Key = rsa.Decrypt(message.rc2Key, false);
      }
      catch (CryptographicException e)
      {
        Console.WriteLine("Decryption Failed: " + e.Message);
        return;
      }
      
      ICryptoTransform ssd = rc2.CreateDecryptor();
      // Put the encrypted message in a memorystream
      MemoryStream ms = new MemoryStream(message.cipherBytes);
      // the CryptoStream will read cipher text from the MemoryStream
      CryptoStream cs = new CryptoStream(ms, ssd, CryptoStreamMode.Read);
      byte[] initialText = new Byte[message.cipherBytes.Length];

      try
      {
          // Decrypt the message and store in byte array
          cs.Read(initialText, 0, initialText.Length);
      }
      catch (Exception e)
      {
          Console.WriteLine(e.Message);
      }      
      finally 
      {
        ms.Close();
        cs.Close();
      }

      // Display the message received
      Console.WriteLine(name + " received the following message:");
      Console.WriteLine("  " + Encoding.Unicode.GetString(initialText));
    } // method DecryptMessage
  } // class Person
} // namespace PublicKey


此外還有AES加密算法,可是AES加密是一個新的能夠用於保護電子數據的加密算法。其產生的密碼是迭代對稱的分組密碼,代加密使用一個循環結構,在該循環中重複置換和替換輸入數據。這種加密方法用的不是不少。

參考博客:
That's All.
相關文章
相關標籤/搜索