会员
周边
众包
新闻
博问
闪存
赞助商
Chat2DB
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
lkcn
专注.NET开发, 移动平台
Powered by
博客园
博客园
|
首页
|
新随笔
|
联系
|
订阅
|
管理
CSDN关于数字签名的问题
摘自CSDN------------------
别人写的,而且还不能满足你的要求 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 //-------------------------------------- 回复人: 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); } } } } ----------------------------------------------------------------- 在现实中解密方B的公钥是从CA服务器(证书服务器)发放的证书中得到的。欲知这里怎么操作,请听下回分解 ^_^ 吃饭去拉~~!!! 2004年9月4日,钟书林,深圳
发表于
2004-10-19 10:46
做想做的人,做想做的事
阅读(
1199
) 评论(
0
)
编辑
收藏
举报
刷新页面
返回顶部