.NET中的密碼學--對稱加密

iDotNetSpace發表於2009-02-02

 using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Security.Cryptography;
using System.IO;


namespace WindowsApplication5
{
   /// 


   /// Form1 的摘要說明。
   /// 

   public class Form1 : System.Windows.Forms.Form.
   {
      private System.Windows.Forms.Button button1;
      private System.Windows.Forms.TextBox txtData;
      /// 
      /// 必需的設計器變數。
      /// 

      private System.ComponentModel.Container components = null;

      public Form1()
      {
         //
         // Windows 窗體設計器支援所必需的
         //
         InitializeComponent();

         //
         // TODO: 在 InitializeComponent 呼叫後新增任何建構函式程式碼
         //
      }

      /// 
      /// 清理所有正在使用的資源。
      /// 

      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if (components != null) 
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }

      #region Windows 窗體設計器生成的程式碼
      /// 
      /// 設計器支援所需的方法 - 不要使用程式碼編輯器修改
      /// 此方法的內容。
      /// 

      private void InitializeComponent()
      {
         this.button1 = new System.Windows.Forms.Button();
         this.txtData = new System.Windows.Forms.TextBox();
         this.SuspendLayout();
         // 
         // button1
         // 
         this.button1.Location = new System.Drawing.Point(64, 168);
         this.button1.Name = "button1";
         this.button1.Size = new System.Drawing.Size(80, 48);
         this.button1.TabIndex = 0;
         this.button1.Text = "button1";
         this.button1.Click += new System.EventHandler(this.button1_Click);
         // 
         // txtData
         // 
         this.txtData.Location = new System.Drawing.Point(56, 64);
         this.txtData.Name = "txtData";
         this.txtData.TabIndex = 1;
         this.txtData.Text = "";
         // 
         // Form1
         // 
         this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
         this.ClientSize = new System.Drawing.Size(292, 273);
         this.Controls.Add(this.txtData);
         this.Controls.Add(this.button1);
         this.Name = "Form1";
         this.Text = "Form1";
         this.ResumeLayout(false);

      }
      #endregion

      /// 
      /// 應用程式的主入口點。
      /// 

      [STAThread]
      static void Main() 
      {
         Application.Run(new Form1());
      }

      private void button1_Click(object sender, System.EventArgs e)
      {
          
         SymmetricAlgorithm mCryptProv;
            
         MemoryStream mMemStr;
            
         // 加密txtData中的資料,然後將加密結果用MessageBox顯示並且回寫到TextBox中
            
         // 這裡你可以配置任何.NET支援的類
            
          mCryptProv = SymmetricAlgorithm.Create("Rijndael");
            
         // 加密資料將要以流的形式儲存在記憶體中因此我們需要記憶體Stream物件

         mMemStr = new MemoryStream();

         //建立ICryptToransform物件.(在這裡我們使用預設的金鑰和初始向量).

         ICryptoTransform mTransform = mCryptProv.CreateEncryptor();

         CryptoStream mCSWriter = new CryptoStream(mMemStr,mTransform,CryptoStreamMode.Write);

         StreamWriter mSWriter = new StreamWriter(mCSWriter);

         mSWriter.Write(this.txtData.Text);

         mSWriter.Flush();

         mCSWriter.FlushFinalBlock();

         //   有一件事情在這裡需要注意我們沒有在程式碼的任何地方使用IV和金鑰。事實上,在我們在程式碼裡面沒有指定他們的時候.NET Framework將為我們自動產生。但是本文包含的例子程式碼使用的是使用者指定的金鑰和IV。我們將加密以後的資料使用MemoryStream寫到記憶體中。現在讓我們從記憶體中得到資料的程式碼。

         //資料已經寫入記憶體但是我們需要回顯它到TextBox和MessageBox中,因此要做下面的工作。

         //為接受資料建立位元組陣列。

         byte[] mBytes = new byte[mMemStr.Length - 1];

         mMemStr.Position = 0;

         mMemStr.Read(mBytes,0,mBytes.Length);

         String mEncData = System.Text.Encoding.UTF8.GetString(mBytes);

         MessageBox.Show("加密資料為:\n"+mEncData);

         this.txtData.Text = mEncData;

//         從位元組轉換為字串必須要編碼。在這裡我使用了UTF8Encoding。最後,讓我們將解密後的資料再次顯示在MessageBox和TextBox中。
//
//         現在讓我們從記憶體中得到解密後的資料
//
//         因為我們的資料在記憶體中,所以我們需要重新使用MemoryStream物件。
//
//         將記憶體點置0

         mMemStr.Position = 0;

         mTransform = mCryptProv.CreateDecryptor();

         CryptoStream mCSReader = new CryptoStream(mMemStr,mTransform,CryptoStreamMode.Read);

         StreamReader mStrReader = new StreamReader(mCSReader);

         String mDecData = mStrReader.ReadToEnd();

         MessageBox.Show("解密資料為:\n"+mDecData);

         this.txtData.Text = mDecData;


      }
   }
}

 

 

 

程式碼例子
      現在我們有足夠關於SymmetricAlgorithm資訊。最後,讓我們看看將要編碼和解碼的程式碼片斷。我假設你擁有一個包含txtData和命令按鈕控制元件的窗體。在命令按鈕的程式碼事件裡寫如下程式碼。這個程式碼將要加密TextBox裡面的文字並用MessageBox顯示,在將加密結果寫回到TextBox中。
SymmetricAlgorithm mCryptProv;
MemoryStream mMemStr;
// 加密txtData中的資料,然後將加密結果用MessageBox顯示並且回寫到TextBox中
// 這裡你可以配置任何.NET支援的類
DES mCryptProv = SymmetricAlgorithm.Create(“Rijndael”);
// 加密資料將要以流的形式儲存在記憶體中因此我們需要記憶體Stream物件
mMemStr = new MemoryStream();
// 建立ICryptTransform物件.(在這裡我們使用預設的金鑰和初始向量).
ICryptTramsform. mTransform. = mCryptProv.CreateEncryptor();
CryptoStream mCSWriter = new CryptoStream(mMemStr,mTransform,CryptoStreamMode.Write);
StreamWriter mSWriter = StreamWriter(mCSWriter);
mSwriter.Writer(this.txtData.Text);
mSWriter.Flush();
mCSWriter.FlushFinalBlock();
      有一件事情在這裡需要注意我們沒有在程式碼的任何地方使用IV和金鑰。事實上,在我們在程式碼裡面沒有指定他們的時候.NET Framework將為我們自動產生。但是本文包含的例子程式碼使用的是使用者指定的金鑰和IV。我們將加密以後的資料使用MemoryStream寫到記憶體中。現在讓我們從記憶體中得到資料的程式碼。
// 資料已經寫入記憶體但是我們需要回顯它到TextBox和MessageBox中,因此要做下面的工作。
// 為接受資料建立位元組陣列。
byte[] mBytes = new byte[mMemStr.Length - 1];
mMemStr.Position = 0;
mMemStr.Read(mBytes,0,mMemStr.Length);
Text.UTF8Encoding mEnc = new Text.UTF8Encoding();
String mEncData = mEnc.GetString(mBytes);
MessageBox.Show(“加密資料為:\n”+mEncData);
This.txtData.Text = mEncData;
從位元組轉換為字串必須要編碼。在這裡我使用了UTF8Encoding。最後,讓我們將解密後的資料再次顯示在MessageBox和TextBox中。
// 現在讓我們從記憶體中得到解密後的資料
// 因為我們的資料在記憶體中,所以我們需要重新使用MemoryStream物件。
// 將記憶體點置0
mMemStr.Position = 0;
mTransform. = mCryptProv.CreateDecryptor();
CryptoStream mCSReader = new CryptoStream(mMemStr,mTransform,CryptoStreamMode.Read);
StreamReader mStrReader = new StreamReader(mCSReader);
String mDecData = mStrReader.ReadToEnd();
MessageBox(“解密資料為:\n”+mDecData);
This.txtData.Text = mDecData;
      這是所有的工作。解密那些資料我們使用了相同的記憶體流。為了能從流的其實部分讀資料我們首先將它置為開始。然後我們用SymmetricAlgorithm物件的CreateDecryptor方法建立IcryptoTransform物件。我們在上面的程式碼中為了解密重複使用了物件(mMemStr)。你可以建立新的物件(使用新的變數)。然後我們為了從記憶體中讀取資料需要StreamReader物件。While reading that it will also decrypt that data since we passed CryptoStream object during the creation of StreamReader object.
最後的話
      .NET為我們提供了一個非常好的託管途徑保護我們的資料。我們可以使用.NET內建的一組類來加密我們的資料。雖然很多的類後臺依然使用Crypto APIs技術,我們使用老的Crypto APIs沒有任何問題。但是我們可以不用擔心那些類的具體實現來安全的使用這些類。在後面的文章我將描述非對稱加密演算法的神話和用途。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-545021/,如需轉載,請註明出處,否則將追究法律責任。

相關文章