<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      打造屬于你的加密Helper類

      摘要

           

             在我們軟件系統(tǒng)設(shè)計中,數(shù)據(jù)的安全性是我們考慮的重中之重,特別像銀行系統(tǒng)的設(shè)計賬戶和密碼都需進(jìn)行加密處理。這時我們可以使用加密算法對數(shù)據(jù)進(jìn)行加密處理,這就是我們今天要介紹的主題。

             首先讓我們了解加密算法分為:對稱、非對稱加密算法和Hash加密

             對稱加密算法:首先需要發(fā)送方和接收方協(xié)定一個密鑰K。K可以是一個密鑰對,但是必須要求加密密鑰和解密密鑰之間能夠互相推算出來。在最簡單也是最常用的對稱算法中,加密和解密共享一個密鑰。

             非對稱加密算法:首先得有一個密鑰對,這個密鑰對含有兩部分內(nèi)容,分別稱作公鑰(PK)和私鑰(SK),公鑰通常用來加密,私鑰則用來解密。在對稱算法中,也講到了可以有兩個密鑰(分為加密和解密密鑰)。但是,對稱算法中的加解密密鑰可以互相轉(zhuǎn)換,而在非對稱算法中,則不能從公鑰推算出私鑰,所以我們完全可以將公鑰公開到任何地方。

       

      正面

       

      encrpyt

      圖1 .NET中對稱加密算法

       encrypt2

      圖2 .NET中非對稱加密算法

       

              通過上面.NET的對稱和非對稱加密算法類結(jié)構(gòu)圖,我們可以發(fā)現(xiàn)在.NET Framework中通過提供者模式實現(xiàn)加密算法動態(tài)擴(kuò)展,SymmetricAlgorithm和AsymmetricAlgorithm類分別為對稱和非對稱算法的基類,接著通過擴(kuò)展不同的算法類型(如:DES,TripleDES等),來動態(tài)地擴(kuò)展不同類型的算法,最后是每種算法的具體實現(xiàn)Provider(如:DESCryptoServiceProvider,TripleDESCryptoServiceProvider等)。

             現(xiàn)在我們對.NET Framework中的加密算法有了初步了解,接下來讓我們通過打造屬于我們的加密Helper類,來加深加密算法的使用。

       

      對稱加密算法

             首先讓我們實現(xiàn)對稱算法的加密和解密方法,先定義對稱算法加密方法Encypt(),它提供所有對稱算法加密算法的加密實現(xiàn)。

       

      /// <summary>
      /// Encrypts the specified algorithm.
      /// The type of algorithm is SymmetricAlgorithm, so the Encrypt
      /// supports all kind of Symmetric Algorithm (cf: DES, TripleDes etc).
      /// </summary>
      /// 
      /// <param name="algorithm">The algorithm.</param>
      /// <param name="plainText">The plain text.</param>
      /// <param name="key">The key.</param>
      /// <param name="cipherMode">The cipher mode.</param>
      /// <param name="paddingMode">The padding mode.</param>
      /// <returns> The string base on base64. </returns>
      public static string Encrypt(SymmetricAlgorithm algorithm, string plainText, byte[] key,
          CipherMode cipherMode, PaddingMode paddingMode)
      {
          byte[] plainBytes;
          byte[] cipherBytes;
          algorithm.Key = key;
          algorithm.Mode = cipherMode;
          algorithm.Padding = paddingMode;
      
          BinaryFormatter bf = new BinaryFormatter();
      
          using (MemoryStream stream = new MemoryStream())
          {
              bf.Serialize(stream, plainText);
              plainBytes = stream.ToArray();
          }
      
          using (MemoryStream ms = new MemoryStream())
          {
              // Defines a stream for cryptographic transformations
              CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
      
              // Writes a sequence of bytes for encrption
              cs.Write(plainBytes, 0, plainBytes.Length);
      
              // Closes the current stream and releases any resources 
              cs.Close();
              // Save the ciphered message into one byte array
              cipherBytes = ms.ToArray();
              // Closes the memorystream object
              ms.Close();
          }
          string base64Text = Convert.ToBase64String(cipherBytes);
         
          return base64Text;
      }

            

              現(xiàn)在我們完成了對稱加密算法的加密方法Encrypt(),它的簽名包含一個SymmetricAlgorithm類參數(shù),前面提到對稱加密算法都是繼承于SymmetricAlgorithm抽象類,所用我們通過多態(tài)性降低了Encrypt()方法和不同的加密算法類之間的耦合度。

             接著傳遞的參數(shù)是要加密的明文plainText、密鑰key,使用的加密模式cipherMode和加密數(shù)據(jù)的填充方式paddingMode。最后返回一組由base64格式組成的加密數(shù)據(jù)。

             上面我們已經(jīng)完成了對稱加密算法的加密方法Encrypt(),接著讓我們實現(xiàn)對稱算法的解密方法,首先定義對稱算法解密方法Decrypt(),它提供所有對稱算法解密算法的解密實現(xiàn)。

       

      /// <summary>
      /// Decrypts the specified algorithm.
      /// </summary>
      /// <param name="algorithm">The algorithm.</param>
      /// <param name="base64Text">The base64 text.</param>
      /// <param name="key">The key.</param>
      /// <param name="cipherMode">The cipher mode.</param>
      /// <param name="paddingMode">The padding mode.</param>
      /// <returns> The recovered text. </returns>
      public static string Decrypt(SymmetricAlgorithm algorithm, string base64Text, byte[] key,
          CipherMode cipherMode, PaddingMode paddingMode)
      {
          byte[] plainBytes;
      
          //// Convert the base64 string to byte array. 
          byte[] cipherBytes = Convert.FromBase64String(base64Text);
          algorithm.Key = key;
          algorithm.Mode = cipherMode;
          algorithm.Padding = paddingMode;
      
          using (MemoryStream memoryStream = new MemoryStream(cipherBytes))
          {
              using (CryptoStream cs = new CryptoStream(memoryStream,
                  algorithm.CreateDecryptor(), CryptoStreamMode.Read))
              {
                  plainBytes = new byte[cipherBytes.Length];
                  cs.Read(plainBytes, 0, cipherBytes.Length);
              }
          }
      
          string recoveredMessage;
          using (MemoryStream stream = new MemoryStream(plainBytes, false))
          {
              BinaryFormatter bf = new BinaryFormatter();
              recoveredMessage = bf.Deserialize(stream).ToString();
          }
      
          return recoveredMessage;
      
      }

       

             我們已經(jīng)完成了對稱加密算法的解密方法Decrypt(),它的簽名形式和加密方法Encrypt()基本一致,只是我們傳遞要解密的密文進(jìn)行解密就OK了。

             現(xiàn)在讓我們回憶一下對稱加密算法的定義,其中有幾點我們要注意的是,加密和解密密鑰可以相同,或通過一定算法由加密密鑰推演出解密密鑰,所以我們?yōu)榱舜_保數(shù)據(jù)的安全性最好設(shè)置對稱算法初始化向量IV,其目的是在初始加密數(shù)據(jù)頭部添加其他數(shù)據(jù),從而降低密鑰被破譯的幾率。

             初始化向量IV在加密算法中起到的也是增強(qiáng)破解難度的作用。在加密過程中,如果遇到相同的數(shù)據(jù)塊,其加密出來的結(jié)果也一致,相對就會容易破解。加密算法在加密數(shù)據(jù)塊的時候,往往會同時使用密碼和上一個數(shù)據(jù)塊的加密結(jié)果。因為要加密的第一個數(shù)據(jù)塊顯然不存在上一個數(shù)據(jù)塊,所以這個初始化向量就是被設(shè)計用來當(dāng)作初始數(shù)據(jù)塊的加密結(jié)果。

             現(xiàn)在我們已經(jīng)完成了對稱加密算法的加密和解密方法,接下來我們繼續(xù)完成非對稱加密算法的加密和解密方法吧!

       

      非對稱加密算法

            在.NET Framework中提供四種非對稱加密算法(DSAECDiffieHellmanECDsaRSA),它們都繼承于抽象類AsymmetricAlgorithm。但這里我們只提供RSA的加密和解密方法的實現(xiàn)。

             首先我們定義一個方法GenerateRSAKey() 來生成RSA的公鑰和密鑰,它的簽名包含一個RSACryptoServiceProvider類型的參數(shù),細(xì)心的大家肯定會發(fā)現(xiàn)為什么我們沒有把參數(shù)類型定義為AsymmetricAlgorithm,這不是可以充分的利用抽象類的特性嗎?當(dāng)我們查看抽象類AsymmetricAlgorithm發(fā)現(xiàn),它并沒有定義公鑰和密鑰的生成方法——ToXmlString()方法,這個方法是在RSA類中定義的,所以這里使用RSACryptoServiceProvider類型。

       

      /// <summary>
      /// Generates the RSA key.
      /// </summary>
      /// <param name="algorithm">The algorithm.</param>
      /// <returns></returns>
      public static void GenerateRSAKey(RSACryptoServiceProvider algorithm)
      {
          RSAPrivateKey = algorithm.ToXmlString(true);
      
          using (StreamWriter streamWriter = new StreamWriter("PublicPrivateKey.xml"))
          {
              streamWriter.Write(RSAPrivateKey);
          }
      
          RSAPubicKey = algorithm.ToXmlString(false);
          using (StreamWriter streamWriter = new StreamWriter("PublicOnlyKey.xml"))
          {
              streamWriter.Write(RSAPubicKey);
          }
      
      }

             我們通過ToXmlString()方法生成公鑰和密鑰,然后把公鑰和密鑰寫到流文件中,當(dāng)我們要使用公鑰和密鑰時,可以通過讀流文件把公鑰和密鑰讀取出來。

             OK接下來讓我們完成RSA的加密和解密方法吧!

       

      /// <summary>
      /// Encrypts the specified algorithm.
      /// The Asymmetric Algorithm includes DSA,ECDiffieHellman, ECDsa and RSA.
      /// Code Logic:
      /// 1. Input encrypt algorithm and plain text.
      /// 2. Read the public key from stream.
      /// 3. Serialize plian text to byte array.
      /// 4. Encrypt the plian text array by public key.
      /// 5. Return ciphered string.
      /// </summary>
      /// <param name="algorithm">The algorithm.</param>
      /// <param name="plainText">The plain text.</param>
      /// <returns></returns>
      public static string Encrypt(RSACryptoServiceProvider algorithm, string plainText)
      {
          string publicKey;
          List<Byte[]> cipherArray = new List<byte[]>();
          
          //// read the public key.
          using (StreamReader streamReader = new StreamReader("PublicOnlyKey.xml"))
          {
              publicKey = streamReader.ReadToEnd();
          }
          algorithm.FromXmlString(publicKey);
      
          BinaryFormatter binaryFormatter = new BinaryFormatter();
          byte[] plainBytes = null;
      
      
          //// Use BinaryFormatter to serialize plain text.
          using (MemoryStream memoryStream = new MemoryStream())
          {
              binaryFormatter.Serialize(memoryStream, plainText);
              plainBytes = memoryStream.ToArray();
          }
      
          int totLength = 0;
          int index = 0;
      
          //// Encrypt plain text by public key.
          if (plainBytes.Length > 80)
          {
              byte[] partPlainBytes;
              byte[] cipherBytes;
                 myArray = new List<byte[]>();
              while (plainBytes.Length - index > 0)
              {
                  partPlainBytes = plainBytes.Length - index > 80 ? new byte[80] : new byte[plainBytes.Length - index];
      
                  for (int i = 0; i < 80 && (i + index) < plainBytes.Length; i++)
                      partPlainBytes[i] = plainBytes[i + index];
                  myArray.Add(partPlainBytes);
      
                  cipherBytes = algorithm.Encrypt(partPlainBytes, false);
                  totLength += cipherBytes.Length;
                  index += 80;
      
                  cipherArray.Add(cipherBytes);
              }
          }
      
          //// Convert to byte array.
          byte[] cipheredPlaintText = new byte[totLength];
          index = 0;
          foreach (byte[] item in cipherArray)
          {
              for (int i = 0; i < item.Length; i++)
              {
                  cipheredPlaintText[i + index] = item[i];
              }
      
              index += item.Length;
          }
          return Convert.ToBase64String(cipheredPlaintText);
       
      }

       

            上面給出了RSA的加密方法實現(xiàn),首先該方法傳遞一個RSACryptoServiceProvider類型的參數(shù)和明文,然后我們從流中讀取預(yù)先已經(jīng)創(chuàng)建的公鑰,接著把明文序列化為Byte數(shù)組,而且使用公鑰對明文進(jìn)行加密處理,最后把加密的Byte數(shù)組轉(zhuǎn)換為base64格式的字符串返回。

             OK現(xiàn)在讓我們完成RSA的解密方法Decrypt(),其實原理和前面的加密方法基本一致,只是我們要使用密鑰對密文進(jìn)行解密。

       

      /// <summary>
      /// Decrypts the specified algorithm.
      /// </summary>
      /// <param name="algorithm">The algorithm.</param>
      /// <param name="base64Text">The base64 text.</param>
      /// <returns></returns>
      public static string Decrypt(RSACryptoServiceProvider algorithm, string base64Text)
      {
          byte[] cipherBytes = Convert.FromBase64String(base64Text);
          List<byte[]> plainArray = new List<byte[]>();
          string privateKey = string.Empty;
      
          //// Read the private key.
          using (StreamReader streamReader = new StreamReader("PublicPrivateKey.xml"))
          {
              privateKey = streamReader.ReadToEnd();
          }
      
          algorithm.FromXmlString(privateKey);
      
          int index = 0;
          int totLength = 0;
          byte[] partPlainText = null;
          byte[] plainBytes;
          int length = cipherBytes.Length / 2;
          //int j = 0;
          //// Decrypt the ciphered text through private key.
          while (cipherBytes.Length - index > 0)
          {
              partPlainText = cipherBytes.Length - index > 128 ? new byte[128] : new byte[cipherBytes.Length - index];
      
              for (int i = 0; i < 128 && (i + index) < cipherBytes.Length; i++)
                  partPlainText[i] = cipherBytes[i + index];
      
              plainBytes = algorithm.Decrypt(partPlainText, false);
        
                  totLength += plainBytes.Length;
              index += 128;
              plainArray.Add(plainBytes);
      
          }
      
          byte[] recoveredPlaintext = new byte[length];
          List<byte[]> recoveredArray;
           index = 0;
          for (int i = 0; i < plainArray.Count; i++)
          {
              for (int j = 0; j < plainArray[i].Length; j++)
              {
                  recoveredPlaintext[index + j] = plainArray[i][j];
              }
              index += plainArray[i].Length;
          }
      
          BinaryFormatter bf = new BinaryFormatter();
          using (MemoryStream stream = new MemoryStream())
          {
              stream.Write(recoveredPlaintext, 0, recoveredPlaintext.Length);
              stream.Position = 0;
              string msgobj = (string)bf.Deserialize(stream);
              return msgobj;
          }
      
      }

       

            我們很快就實現(xiàn)RSA的解密方法實現(xiàn),代碼邏輯和加密算法基本一致,我們只需注意把明文換成密文,公鑰換成密鑰就基本不會出錯了。

       

      Hash加密

             Hash算法特別的地方在于它是一種單向算法,用戶可以通過Hash算法對目標(biāo)信息生成一段特定長度的唯一的Hash值,卻不能通過這個Hash值重新獲得目標(biāo)信息,因此Hash算法常用在不可還原的密碼存儲、信息完整性校驗等,所用我們代碼邏輯就沒有解密方法,而是判斷加密的密文是否匹配。

       

      /// <summary>
      /// Encrypts the specified hash algorithm.
      /// 1. Generates a cryptographic Hash Key for the provided text data.
      /// </summary>
      /// <param name="hashAlgorithm">The hash algorithm.</param>
      /// <param name="dataToHash">The data to hash.</param>
      /// <returns></returns>
      public static string Encrypt(HashAlgorithm hashAlgorithm, string dataToHash)
      {
      
          string[] tabStringHex = new string[16];
          UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
          byte[] data = UTF8.GetBytes(dataToHash);
          byte[] result = hashAlgorithm.ComputeHash(data);
          StringBuilder hexResult = new StringBuilder(result.Length);
      
          for (int i = 0; i < result.Length; i++)
          {
              //// Convert to hexadecimal
              hexResult.Append(result[i].ToString("X2"));
          }
          return hexResult.ToString();
      }

       

           接著我們定義IsHashMatch()方法判斷加密的密文是否一致。

       

      /// <summary>
      /// Determines whether [is hash match] [the specified hash algorithm].
      /// </summary>
      /// <param name="hashAlgorithm">The hash algorithm.</param>
      /// <param name="hashedText">The hashed text.</param>
      /// <param name="unhashedText">The unhashed text.</param>
      /// <returns>
      ///   <c>true</c> if [is hash match] [the specified hash algorithm]; otherwise, <c>false</c>.
      /// </returns>
      public static bool IsHashMatch(HashAlgorithm hashAlgorithm, string hashedText, string unhashedText)
      {
          string hashedTextToCompare = Encrypt(hashAlgorithm, unhashedText);
          return (String.Compare(hashedText, hashedTextToCompare, false) == 0);
      }

       

             現(xiàn)在我們已經(jīng)實現(xiàn)了屬于我們的加密Helper類了,現(xiàn)在讓我們測試一下自定義Helper類是否好用,我們可以通過Unit Test或一個界面程序來測試我們的Helper類的功能是否完善,這里我們選擇使用一個界面程序來說話。

              首先我們創(chuàng)建一個應(yīng)用程序界面,然后我們添加兩個Tabpage分別對應(yīng)對稱和非對稱加密程序。

       

      encrypt3 

      圖3加密程序界面

       

      encrypt4 

      圖4非對稱加密程序界面

       

      encrypt5 

      圖5對稱加密程序界面

       

         現(xiàn)在我們已經(jīng)把界面設(shè)計好了,接下來讓我們完成界面邏輯的設(shè)計。

       

      /// <summary>
      /// Handles the Click event of the btnEncrypt control.
      /// Encypt plain text by symmetric algorithm.
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
      private void btnEncrypt_Click(object sender, EventArgs e)
      {
      
          if (String.IsNullOrEmpty(txtInputMsg.Text) ||
              String.IsNullOrEmpty(txtRandomInit.Text) ||
              String.IsNullOrEmpty(txtRandomKey.Text))
          {
              MessageBox.Show("Invalid parameters!");
              return;
          }
      
          if (_symmetricAlgorithm != null)
          {
              try
              {
      
                  //// Specified IV.
      
              _symmetricAlgorithm.IV = _initVector;
      
              //// Invoke Cryptography helper.
              /// Get ciphered text.
      
              txtCipherMsg.Text = CryptographyUtils.Encrypt(_symmetricAlgorithm, txtInputMsg.Text.Trim(), _key, _cipherMode, _paddingMode);
      
      
                  //// Convert string to byte array.
      
                  _cipherBytes = Convert.FromBase64String(txtCipherMsg.Text);
      
      
                  //// Initialize text box.
      
                  InitTextBox(_cipherBytes, ref txtCipherByte);
      
      
      
              }
              catch (Exception ex)
              {
      
                  MessageBox.Show(ex.Message);
              }
          }
          
      }

       

             接著我們同樣通過調(diào)用Helper類的Decrypt()方法,使用對稱算法對數(shù)據(jù)進(jìn)行解密處理就OK了。

       

      /// <summary>
      /// Handles the Click event of the btnDecrypt control.
      /// Decrypt plain text by symmetric algorithm
      /// </summary>
      /// <param name="sender">The source of the event.</param>
      /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
      private void btnDecrypt_Click(object sender, EventArgs e)
      {
          if (_symmetricAlgorithm != null)
          {
              try
              {
      
                  //// Specified IV.
                  _symmetricAlgorithm.IV = _initVector;
      
                  //// Decrypt ciphered text.
                  txtOutputMsg.Text = CryptographyUtils.Decrypt(_symmetricAlgorithm, txtCipherMsg.Text.Trim(), _key, _cipherMode, _paddingMode);
      
              }
              catch (Exception ex)
              {
                  MessageBox.Show(ex.Message);
              }
             
          }
      }

       

             接著我們同樣通過調(diào)用Helper類的Decrypt()方法,使用對稱算法對數(shù)據(jù)進(jìn)行解密處理就OK了。

       

      encrypt6

      圖6對稱加密程序效果

       

      encrypt7

      圖7非對稱加密程序效果

       

      總結(jié)

       

             通過本文的介紹相信大家對.NET Framework中提供的加密算法有了初步的了解。

             最后,我們在實際應(yīng)用中對于大量數(shù)據(jù)進(jìn)行加密時應(yīng)該采用對稱加密算法,對稱加密算法的優(yōu)點在于加解密的高速度和使用長密鑰時的難破解性。而非對稱加密的缺點是加解密速度要遠(yuǎn)遠(yuǎn)慢于對稱加密,非對稱加密算法適合于數(shù)據(jù)量少的情況,應(yīng)該始終考慮使用對稱加密的方式進(jìn)行文件的加解密工作。當(dāng)然,如果文件加密后要傳給網(wǎng)絡(luò)中的其它接收者,而接收者始終要對文件進(jìn)行解密的,這意味著密鑰也是始終要傳送給接收者的。這個時候,非對稱加密就可以派上用場了,它可以用于字符串的加解密及安全傳輸場景。

       

      加密Helper源代碼

      posted @ 2011-07-24 21:45  JK_Rush  閱讀(8649)  評論(33)    收藏  舉報
      主站蜘蛛池模板: 免费萌白酱国产一区二区三区| 久久精品国产99国产精品严洲| 天天躁日日摸久久久精品| 亚洲线精品一区二区三八戒 | 久久婷婷五月综合色丁香花| 日本熟妇色xxxxx| 国产午夜精品久久久久免费视| 亚洲国产欧美在线人成| 色综合久久中文字幕综合网| 亚洲有无码中文网| 麻豆国产成人AV在线播放| 激情六月丁香婷婷四房播| 老少配老妇老熟女中文普通话 | 偃师市| 99精品国产一区二区三| 波多结野衣一区二区三区| 精品无码人妻| 亚洲精品一区二区三区大桥未久| 国产高清一区二区三区视频| 亚洲国产成熟视频在线多多| 国产欧美日韩高清在线不卡| 国产91丝袜在线播放动漫| 国产精品美女自慰喷水| 亚洲国产美女精品久久久| 国产mv在线天堂mv免费观看| 欧美亚洲另类 丝袜综合网| 国内精品无码一区二区三区| 实拍女处破www免费看| 国产高清自产拍AV在线| 国产av国片精品一区二区| 國產尤物AV尤物在線觀看| 久久av中文字幕资源网| 激情97综合亚洲色婷婷五| 精品一区二区免费不卡| 久久成人国产精品免费软件| 国产午夜福利视频在线| 免费观看欧美猛交视频黑人| 亚洲中文字幕国产综合| 日日碰狠狠添天天爽不卡| 国产线播放免费人成视频播放 | 国产精品有码在线观看|