RSA&MD5实现电子签章  
   
  本人目前在做一个关于“数字签名”的项目,在网上查资料,感觉这方面的都非常的少,一般都是讲RSA的算法,或者“数字签名”的原理,完全是浪费时间。我经过摸索,小有进展,初步实现功能。今天写出来,希望能给以后的做这个的朋友提供个方便。还有一件事,在我查资料的时候也遇见很多朋友在做这个项目,但是我感觉他们都在进入了几个误区。我先把这几个误区说说,以免大家以后走错方向。说得不对的地方希望大家能批评指正,毕竟本人能力有限(但是不要骂我)   ^_^    
   
  误区一:大家对公钥私钥区分得太.......(我还找不到形容来形容了....   ),就太死板了吧。其实当你把公钥保密不公开的时候,公钥就是私钥了;当你把私钥公开的时候,私钥也是公钥了。没必要记得这么死的(个人意见)。  
  误区二:对RSA算法的原理理解不够,实际上所谓的公钥和私钥只是RSA算法(说穿了RSA就是个数学方程式)的参数(未知数),比如   X+Y+M=Z,X就可以说是私钥,Y就可以说是公钥,M就是需要加密的内容,Z就是加密后的密文,当然RSA中不可能只有X和Y两个未知数的,所以就经常有朋友问,到底X是私钥还是Y是私钥(嘻嘻...   我也问过)。其实这个就要取决于你用在时候,什么地方了。  
  误区三:对Security.Cryptography命名空间不熟悉。“数字签名”一般的做法是:A先计算出文件M的HASH码,再对HASH码进行加密(这个步骤就是签名),再把M(文件M不要加密,第三方可以查阅)和加密后的HASH码传送给B,B再用A的公钥来解密刚才得到的加密HASH码,如果能解密,那就说明这个文件是A发的,具有法律效应。再计算出得到的文件M的HASH码,再和刚才解密出来的HASH码比较(这个步骤叫验证签名),如果一致就说明文件M在传输过程中没有被修改。但是在C#中需要解密RSA,就必须提供公钥和私钥,当然这和我们的现实不符,因为A不可能把他的私钥给B。许多人就是在这里难住了。其实在C#的Security.Cryptography命名空间中有RSAPKCS1SignatureFormatter   和RSAPKCS1SignatureDeformatter   两个方法或者说是对象。前者用来对HASH进行加密(签名),后者用来验证签名,用这个验证就只需要A的公钥就行了。在C#中,签名就是这个两个专用的方法,不是用RSA普通的加密解密。  
   
  下面我就贴出我的代码,我的公钥和私钥就是从两个文件PublicKey.xml、PrivateKey.xml中读取出来,相当于是现实中的指定公钥和私钥;再验证时我为了方便直接验证的A计算出的HASH码,现实中应该是由B重新计算出文件M的HASH码(这个大家明白就行了^_^)。  
   

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   
  ///   <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);   
        }   
      }   
    }   
  }