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