一个完整的RSA数字签名的Project

来源:互联网 发布:五笔输入法 for linux 编辑:程序博客网 时间:2024/05/21 09:11

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