RSA&MD5實現電子簽章 這個例子很經典哈

本人目前在做一個關於“數字簽名”的項目,在網上查資料,感覺這方面的都非常的少,一般都是講RSA的算法,或者“數字簽名”的原理,完全是浪費時間。我經過摸索,小有進展,初步實現功能。今天寫出來,希望能給以後的做這個的朋友提供個方便。還有一件事,在我查資料的時候也遇見很多朋友在做這個項目,但是我感覺他們都在進入了幾個誤區。我先把這幾個誤區說說,以免大家以後走錯方向。說得不對的地方希望大家能批評指正,畢竟本人能力有限(但是不要罵我) ^_^

誤區一:大家對公鑰私鑰區分得太.......(我還找不到形容來形容了.... ),就太死板了吧。其實當你把公鑰保密不公開的時候,公鑰就是私鑰了;當你把私鑰公開的時候,私鑰也是公鑰了。沒必要記得這麼死的(個人意見)。

誤區二:對RSA算法的原理理解不夠,實際上所謂的公鑰和私鑰只是RSA算法(說穿了RSA就是個數學方程式)的參數(未知數),比如 X+Y+M=ZX就可以說是私鑰,Y就可以說是公鑰,M就是需要加密的內容,Z就是加密後的密文,當然RSA中不可能只有XY兩個未知數的,所以就經常有朋友問,到底X是私鑰還是Y是私鑰(嘻嘻... 我也問過)。其實這個就要取決於你用在時候,什麼地方了。

誤區三:對Security.Cryptography命名空間不熟悉。“數字簽名”一般的做法是:A先計算出文件MHASH碼,再對HASH碼進行加密(這個步驟就是簽名),再把M(文件M不要加密,第三方可以查閱)和加密後的HASH碼傳送給BB再用A的公鑰來解密剛纔得到的加密HASH碼,如果能解密,那就說明這個文件是A發的,具有法律效應。再計算出得到的文件MHASH碼,再和剛纔解密出來的HASH碼比較(這個步驟叫驗證簽名),如果一致就說明文件M在傳輸過程中沒有被修改。但是在C#中需要解密RSA,就必須提供公鑰和私鑰,當然這和我們的現實不符,因爲A不可能把他的私鑰給B。許多人就是在這裏難住了。其實在C#Security.Cryptography命名空間中有RSAPKCS1SignatureFormatter RSAPKCS1SignatureDeformatter 兩個方法或者說是對象。前者用來對HASH進行加密(簽名),後者用來驗證簽名,用這個驗證就只需要A的公鑰就行了。在C#中,簽名就是這個兩個專用的方法,不是用RSA普通的加密解密。

下面我就貼出我的代碼,我的公鑰和私鑰就是從兩個文件PublicKey.xmlPrivateKey.xml中讀取出來,相當於是現實中的指定公鑰和私鑰;再驗證時我爲了方便直接驗證的A計算出的HASH碼,現實中應該是由B重新計算出文件MHASH碼(這個大家明白就行了^_^)。

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.IO;

using System.Security.Cryptography;

using System.Xml;

namespace StandSoftRSA

{

 /// <summary>

 /// Form1 的摘要說明。

 /// </summary>

 public class Form1 : System.Windows.Forms.Form

 {

 private System.Windows.Forms.RichTextBox richTextBox1;

 private System.Windows.Forms.Button button1;

 private System.Windows.Forms.Button button2;

 private System.Windows.Forms.RichTextBox richTextBox2;

 private System.Windows.Forms.Button button3;

 private RSACryptoServiceProvider RSA;

 private byte[] Hashbyte;

 private byte[] EncryptedData;

 private RSAParameters PrivateKey;

 private RSAParameters PublicKey;

 private XmlDocument objXml;

 private XmlNodeList objXmlNode;

 

 /// <summary>

 /// 必需的設計器變量。

 /// </summary>

 private System.ComponentModel.Container components = null;

 public Form1()

 {

   //

   // Windows 窗體設計器支持所必需的

   //

   InitializeComponent();

   //

   // TODO: InitializeComponent 調用後添加任何構造函數代碼

   //

 }

 /// <summary>

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

 /// </summary>

 protected override void Dispose( bool disposing )

 {

   if( disposing )

   {

    if (components != null)

    {

     components.Dispose();

    }

   }

   base.Dispose( disposing );

 }

 #region Windows 窗體設計器生成的代碼

 /// <summary>

 /// 設計器支持所需的方法 - 不要使用代碼編輯器修改

 /// 此方法的內容。

 /// </summary>

 private void InitializeComponent()

 {

   this.richTextBox1 = new System.Windows.Forms.RichTextBox();

   this.button1 = new System.Windows.Forms.Button();

   this.button2 = new System.Windows.Forms.Button();

   this.richTextBox2 = new System.Windows.Forms.RichTextBox();

   this.button3 = new System.Windows.Forms.Button();

   this.SuspendLayout();

   //

   // richTextBox1

   //

   this.richTextBox1.BackColor = System.Drawing.Color.Black;

   this.richTextBox1.ForeColor = System.Drawing.Color.LawnGreen;

   this.richTextBox1.Location = new System.Drawing.Point(8, 8);

   this.richTextBox1.Name = "richTextBox1";

   this.richTextBox1.Size = new System.Drawing.Size(384, 80);

   this.richTextBox1.TabIndex = 0;

   this.richTextBox1.Text = "";

   //

   // button1

   //

   this.button1.Location = new System.Drawing.Point(168, 104);

   this.button1.Name = "button1";

   this.button1.Size = new System.Drawing.Size(56, 24);

   this.button1.TabIndex = 1;

   this.button1.Text = "哈稀碼";

   this.button1.Click += new System.EventHandler(this.button1_Click);

   //

   // button2

   //

   this.button2.Location = new System.Drawing.Point(8, 184);

   this.button2.Name = "button2";

   this.button2.Size = new System.Drawing.Size(384, 24);

   this.button2.TabIndex = 3;

   this.button2.Text = "加密";

   this.button2.Click += new System.EventHandler(this.button2_Click);

   //

   // richTextBox2

   //

   this.richTextBox2.BackColor = System.Drawing.Color.Black;

   this.richTextBox2.ForeColor = System.Drawing.Color.LawnGreen;

   this.richTextBox2.Location = new System.Drawing.Point(8, 216);

   this.richTextBox2.Name = "richTextBox2";

   this.richTextBox2.Size = new System.Drawing.Size(384, 80);

   this.richTextBox2.TabIndex = 4;

   this.richTextBox2.Text = "";

   //

   // button3

   //

   this.button3.Location = new System.Drawing.Point(8, 304);

   this.button3.Name = "button3";

   this.button3.Size = new System.Drawing.Size(384, 24);

   this.button3.TabIndex = 5;

   this.button3.Text = "解密";

   this.button3.Click += new System.EventHandler(this.button3_Click);

   //

   // Form1

   //

   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

   this.ClientSize = new System.Drawing.Size(400, 421);

   this.Controls.Add(this.button3);

   this.Controls.Add(this.richTextBox2);

   this.Controls.Add(this.button2);

   this.Controls.Add(this.button1);

   this.Controls.Add(this.richTextBox1);

   this.Name = "Form1";

   this.Text = "RSA&MD5";

   this.ResumeLayout(false);

 }

 #endregion

 

//--------------------------------------

 回覆人: cnming(cnming) ( ) 信譽:100 2004-10-15 09:40:00 得分: 0 

 

 

   /// <summary>

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

 /// </summary>

 [STAThread]

 static void Main()

 {

   Application.Run(new Form1());

 }

 //獲得文件的哈稀碼

 private void GetFileHash()

 {

   FileStream objFile = File.OpenRead("Hash.doc");

   HashAlgorithm MD5 = HashAlgorithm.Create("MD5");

   Hashbyte = MD5.ComputeHash(objFile);

   objFile.Close();

   foreach(byte b in Hashbyte)

   {

    richTextBox1.AppendText(b.ToString()+" ");

   }

 }

   

 private void button1_Click(object sender, System.EventArgs e)

 {

   GetFileHash();

 }

 //設置公鑰和私鑰對(都包含)

 public void SetPrivateKey()

 {

   PrivateKey = new RSAParameters();

   objXml = new XmlDocument();

   objXml.Load("PublicKey.xml");

   //指定RSA參數Exponent的值(公鑰)

   objXmlNode = objXml.SelectNodes("//Exponent");

   PrivateKey.Exponent = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());  

   //指定RSA參數Modulus的值(公鑰)

   objXmlNode = objXml.SelectNodes("//Modulus");

   PrivateKey.Modulus = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   objXml = new XmlDocument();

   objXml.Load("PrivateKey.xml");

   //指定RSA參數D的值(私鑰)

   objXmlNode = objXml.SelectNodes("//D");

   PrivateKey.D = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   //指定RSA參數DP的值(私鑰)

   objXmlNode = objXml.SelectNodes("//DP");

   PrivateKey.DP = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   //指定RSA參數DQ的值(私鑰)

   objXmlNode = objXml.SelectNodes("//DQ");

   PrivateKey.DQ = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   //指定RSA參數InverseQ的值(私鑰)

   objXmlNode = objXml.SelectNodes("//InverseQ");

   PrivateKey.InverseQ = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   //指定RSA參數P的值(私鑰)

   objXmlNode = objXml.SelectNodes("//P");

  PrivateKey.P = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

   //指定RSA參數Q的值(私鑰)

   objXmlNode = objXml.SelectNodes("//Q");

   PrivateKey.Q = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());  

 }

 //執行加密

 private void button2_Click(object sender, System.EventArgs e)

 {

   RSA = new RSACryptoServiceProvider();

   //設置私鑰

   SetPrivateKey();

   //導入加密私鑰

   RSA.ImportParameters(PrivateKey);

   RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(RSA);

   //設置簽名的算法爲MD5

   RSAFormatter.SetHashAlgorithm("MD5");

   //執行簽名

   EncryptedData = RSAFormatter.CreateSignature(Hashbyte);

   string strCode = "";

   //現實加密結果

   for(int i = 0; i < EncryptedData.Length; i++)

   {

    strCode += " " + EncryptedData[i].ToString();

   }

   richTextBox2.AppendText(strCode);

 }

 //設置公鑰

 public void SetPublicKey()

 {

   PublicKey = new RSAParameters();

   objXml = new XmlDocument();

   objXml.Load("PublicKey.xml");

   //指定私鑰Exponent的值

   objXmlNode = objXml.SelectNodes("//Exponent");

   PublicKey.Exponent = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());  

   //指定私鑰Modulus的值

   objXmlNode = objXml.SelectNodes("//Modulus");

   PublicKey.Modulus = Convert.FromBase64String(objXmlNode[0].InnerXml.ToString());

 }

 

 //用公鑰解密

 private void button3_Click(object sender, System.EventArgs e)

 {

   RSA = new RSACryptoServiceProvider();

   //設置公鑰

   SetPublicKey();

   RSA.ImportParameters(PublicKey);

   RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(RSA);

   //指定解密的時候HASH算法爲MD5

   RSADeformatter.SetHashAlgorithm("MD5");

   if(RSADeformatter.VerifySignature(Hashbyte,EncryptedData))

   {

    MessageBox.Show("身份已經確認!","確認身份",MessageBoxButtons.OK,MessageBoxIcon.Information);

   }

   else

   {

    MessageBox.Show("確認身份失敗","確認身份",MessageBoxButtons.OK,MessageBoxIcon.Error);

   }

 }

 }

}

 
發佈了37 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章