2、引言传统的交易行为和政府间的公文传送,必须要用书面的文件来完成,为了保证文件是某个当事人或者机关签发的,并且文件没有被篡改,还必须要有签发人的手写签字或者公章。
网络环境中,文件的传递采取电子的方式,比如E-mail。
这种方式最大的优点就是速度快,文件可以在数秒中到达远在万里之外的客户手中。
在“时间就是金钱、效率就是生命”的生意场上,这种优势无疑成为广大厂商的首选。
电子文件并非只用于合同的签订和政府文件的传递,而是适用于所有信息的传递。
可以理想化地认为,未来的信息传递,可以不借助于任何纸张。
但如何保证一项文件或者一条信息是某个人发出的?某个人发出文件或者信息后,如果发现对自己不利抵赖怎么办?如果文件或者信息在网络传输过程中被他人截取,并被篡改了怎么办?许多人都知道,我们平时发送和接收的电子邮件是不加密的,对于某些人比如网管员来说,看这些文件甚至比看没有封上的书面信件更容易。
3、实例某信息公司要求研发一套办公自动化系统,其中就包括了对电子公文进行电子签章的功能,本人有幸参与并设计了电子签章部份。
目前最成熟的电子签章技术就是“数字签章(Digital Signature)”,它是以公钥及私钥的“非对称型”密码技术制作的电子签章。
使用原理大致为:由计算机程序将密钥和需传送的文件浓缩成信息摘要予以运算,得出数字签章,将数字签章并同原交易信息传送给对方,后者可用公钥来验证该信息确实由前者传送、并可查验文件在传送过程是否遭他人篡改,并防止对方抵赖。
由于数字签章技术采用的是单向不可逆运算方式,要想对其破解,以目前的计算机速度以及技术而言,几乎是不可能的。
文件传输可选择明文或密文进行传输。
因此,从某种意义上讲,使用电子文件和数字签章,甚至比使用经过签字盖章的书面文件安全得多。
设计之初,我就先提出了需要解决的几个问题:如何保证电子文件在传输过程中不被篡改?如何保证电子文件合法性及不可抵赖?一般来说要保证电子文件在传输过程中不被篡改,一是对电子文件进行私钥加密。
在传输方使用私钥对电子文件进行明文加密,接收方再用私钥对传输过来的密文进行解密,以此来达到电子文件不被篡改。
但此方法需要传输方与接收方都拥有私钥而且出现问题后双方都可能指责对方将私钥解密,因此单纯使用此方法,一般都只用于安全性要求不高的应用,不值得推荐。
二是传输方对电子文件创建哈希,将电子文件与哈希一同发给接收方,接收方对接受到的电子文件也创建哈希,然后对比哈希值,以此来达到电子文件不被篡改。
这是本人所选用的方案。
下面是根据本人电子签章设计所写的一个DEMO片段,以供参考。
以下是对电子文件创建哈希的具本实现(使用了MD5加密):1///<summary>2///得到指定电子文件的哈希3///</summary>4///<param name="filePath">电子文件地址</param>5///<returns>哈希值</returns>6public static byte[] GetFileHash(string filePath)7 {8try9 {10 FileStream objFile = File.OpenRead(filePath);11 HashAlgorithm MD5 = HashAlgorithm.Create("MD5");12byte[] Hashbyte = puteHash(objFile);13 objFile.Close();14return Hashbyte;15 }16catch17 {18return null;19 }20 }要实现合法性及不可抵赖就必需使用公钥私钥非对称加密方式并结合哈希加密方式。
公钥及私钥是一对很有意思的组合,它们是成对使用的,一一对应的,使用私钥加密的数据,可以使用公钥来证明是否是由此公钥所对应的私钥所加密的,将电子文件的哈希用私钥加密,接收人就算出电子文件的哈希,然后用公钥来验证电子文件是否是传输者所确认的文件。
生成公钥及私钥:1///<summary>2///得到公钥与私钥3///</summary>4///<param name="ContainerName">私钥容器名</param>5///<param name="privatekey">真为得到私钥,假为得到公钥</param>6///<returns>公钥或私钥</returns>7public static string GetKeyFromContainer(string ContainerName,bool privatekey)8 {9 CspParameters cp = new CspParameters();10 cp.KeyContainerName = ContainerName;11 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);12return rsa.ToXmlString(privatekey);13 }对电子文件的哈希进行数字签名:1///<summary>2///对哈希进行数字签名3///</summary>4///<param name="privateKey">私钥</param>5///<param name="fileHash">电子文件哈希</param>6///<returns></returns>7public static byte[] EncryptHash(string privateKey,byte[] fileHash)8 {9 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();1011 RSA.FromXmlString(privateKey);1213 RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatte r(RSA);1415 RSAFormatter.SetHashAlgorithm("MD5");1617return RSAFormatter.CreateSignature(fileHash);18 }19对数字签名用公钥进行验证1///<summary>2///对数字签名用公钥进行验证3///</summary>4///<param name="publicKey">公钥</param>5///<param name="fileHash">接收到的电子文件的哈希</param>6///<param name="electronicSignature">数字签名</param>7///<returns>数字签名有效为真,数字签名无效为假</returns>8public static bool DecryptHash(string publicKey,byte[] fileHash,byte[] electronicSign ature)9 {10 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();1112 RSA.FromXmlString(publicKey);1314 RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDefo rmatter(RSA);1516 RSADeformatter.SetHashAlgorithm("MD5");1718return RSADeformatter.VerifySignature(fileHash,electronicSignature);19 }主体程序1static void Main()2 {3// 生成电子文件4string filePath = "C:\\公文.txt";5 StreamWriter sw = File.CreateText(filePath);6 sw.Write("测试公文");7 sw.Close();89// 对电子文件进行哈希10byte[] fileHash = GetFileHash(filePath);11// 取得公钥12string publicKey = GetKeyFromContainer("公文",false);13// 取得私钥14string privateKey = GetKeyFromContainer("公文",true);1516 Console.WriteLine("发送方:A");17 Console.WriteLine("电子文件地址:");18 Console.WriteLine(filePath);1920 Console.WriteLine("哈希:");21 Console.WriteLine(ConvertBytesToString(fileHash));2223 Console.WriteLine("使用私钥进行数字签名:");24// 取得电子签名25byte[] ElectronicSignature = EncryptHash(privateKey,fileHash);26 Console.WriteLine(ConvertBytesToString(ElectronicSignature));2728 Console.WriteLine("传送给接收方。
");29 Console.WriteLine("");30string fileCopyPath = "C:\\公文接收.txt";31 File.Copy(filePath,fileCopyPath,true);3233 Console.WriteLine("是否篡改文件?(Y/N)");34string sRe = string.Empty;35do36 {37 sRe = Console.ReadLine();38 }39while(sRe != "Y" && sRe != "N");4041byte[] fileCopyHash;42if(sRe == "N")43 {44 Console.WriteLine("接收方收到电子文件。