用C#实现pdf文件的完整性验证

现在对文件的完整性验证,防止文件被篡改的技术已经比较成熟,一般使用数字签名,数字水印等,最近我在一个项目中也遇到了防篡改的需求。该项目要求用户将原始发票用专门的扫描程序扫描成pdf文件,然后将该pdf文件传到服务器上,在上传的同时必须要验证这个pdf是没有被手工修改过的。我刚一接触到这个需求想到的就是使用数字水印,要不然就直接使用PDF的数字签名功能,不过这些方法都感觉比较比较复杂,一大堆的英文文档也没有心思去研究,于是琢磨了半天,写了一个简化版的数字水印程序,实现了pdf文件完整性验证。

验证的基本思路是:

对文件全部内容计算其MD5值,这样无论用户修改了文件的任何一个地方,那么生成的MD5的是完全不一样的,我们可以将这个MD5写到文件的一个隐藏区,一般二进制文件格式都有文件头和文件体部分,而文件头是用户看不到的,一般也会预留一部分字节用于以后扩展,或可以在文件头写入特殊标记的数据。于是研究了一下pdf文件的格式,试着往其第10个字节插入了MD5值,结果文件虽然可以使用,但是每次打开的时候都会提示“文件修复”。原来是写在头上面的内容将pdf文件的字节数和文件中对象的地址改变了,导致了文件错误,原因找到了那么解决办法也就有了,为了不改变pdf文件中对象的地址,那么我们将这个md5写在文件尾不就可以了嘛!于是在客户端(扫描程序)将扫描出的pdf文件流计算MD5值,然后将该文件流和MD5值一起写到硬盘上,形成一个添加了MD5值的pdf文件。文件可以正常打开和使用,而且用户也不会看到我们添加的这个MD5值。

在服务器端,我们将上传上来的文件流除了最后32个字节以为的部分计算MD5值(这儿取32个字节是因为最后这32字节是我们写的MD5),将前面部分算出的MD5和最后32个字节的MD5进行比较,如果一样那么说明这个文件从扫描程序生成以后没有被人为篡改过,否则说明该文件要么不是用我们这个扫描程序生成的要么就是被篡改了。这样验证通过以后我们才将该文件流写到服务器硬盘上。

相关程序代码

1 public class MD5

2  {
3    /**//// <summary>
4    /// 对给定文件路径的文件加上标签
5    /// </summary>
6    /// <param name="path">要加密的文件的路径</param>
7    /// <returns>标签的值</returns>
8    public static string MD5pdf(string path,string key)
9    {
10
11      try
12      {
13        FileStream get_file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
14        byte[] pdfFile = new byte[get_file.Length];
15        get_file.Read(pdfFile, 0, (int)get_file.Length);//将文件流读取到Buffer中
16        get_file.Close();
17
18        string result = MD5Buffer(pdfFile, 0, pdfFile.Length );//对Buffer中的字节内容算MD5
19        result = MD5String(result +key);//这儿点的key相当于一个密钥,这样一般人就是知道使用MD5算法,但是若不知道这个字符串还是无法计算出正确的MD5
20
21        byte[] md5 = System.Text.Encoding.ASCII.GetBytes(result);//将字符串转换成字节数组以便写人到文件中
22
23        FileStream fsWrite = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
24        fsWrite.Write(pdfFile, 0, pdfFile.Length);//将pdf文件,MD5值 重新写入到文件中。
25        fsWrite.Write(md5, 0, md5.Length);
26        //fsWrite.Write(pdfFile, 10, pdfFile.Length - 10);
27        fsWrite.Close();
28
29        return result;
30      }
31      catch (Exception e)
32      {
33        return e.ToString();
34      }
35    }
36    /**//// <summary>
37    /// 对给定路径的文件进行验证
38    /// </summary>
39    /// <param name="path"></param>
40    /// <returns>是否加了标签或是否标签值与内容值一致</returns>
41    public static bool Check(string path,string key)
42    {
43      try
44      {
45        FileStream get_file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
46
47       
48        byte[] pdfFile = new byte[get_file.Length];
49        get_file.Read(pdfFile, 0, (int)get_file.Length);
50        get_file.Close();
51        string result = MD5Buffer(pdfFile, 0, pdfFile.Length - 32);//对pdf文件除最后32位以外的字节计算MD5,这个32是因为标签位为32位。
52        result = MD5String(result + key);
53
54        string md5 = System.Text.Encoding.ASCII.GetString(pdfFile, pdfFile.Length - 32, 32);//读取pdf文件最后32位,其中保存的就是MD5值
55        return result == md5;
56      }
57      catch
58      {
59
60        return false;
61
62      }
63    }
64    private static string MD5Buffer(byte[] pdfFile, int index, int count)
65    {
66      System.Security.Cryptography.MD5CryptoServiceProvider get_md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
67      byte[] hash_byte = get_md5.ComputeHash(pdfFile, index, count);
68
69      string result = System.BitConverter.ToString(hash_byte);
70      result = result.Replace("-", "");
71      return result;
72    }
73    private static string MD5String(string str)
74    {
75      byte[] MD5Source = System.Text.Encoding.ASCII.GetBytes(str);
76      return MD5Buffer(MD5Source, 0, MD5Source.Length);
77
78    }
79  }

以上代码不仅仅只适用于PDF文件,对于其他一些格式也可以用,这主要是取决于文件的格式规范。

时间: 2024-10-02 04:24:11

用C#实现pdf文件的完整性验证的相关文章

办公一族小心:打开PDF文件可致电脑被远程控制

Adobe 官方发布安全警告称,在Adobe Reader 和Acrobat 9.4.6中发现新的安全漏洞(CVE- 2011 -2462).因漏洞等级较高,Adobe将于下周发布更新.12月8日,金山毒霸安全中心报告已有攻击代码被公开,经验证,安装了金山毒霸的电脑可以成功防御此漏洞攻击. PDF是电子文档应用最普遍的格式,Adobe Reader和Acrobat在办公电脑中安装量很高,而许多人并不重视Adobe Reader和Acrobat的版本更新,存在安全漏洞的软件没有得到及时修补.幸运的

Win8系统查看PDF文件的方法

  大家都知道,PDF文档是我们日常工作.学习中经常会遇到的一种文字表现格式,这个文字格式不可修改,只可以通过一些相应的软件来打开,所以很多人都是使用的第三方软件开打开win8中的一些PDF文件,其实win8系统中应用商店的一些软件也可以打开PDF文件,但是如果没有微软账户的话也是不可以的.今天小编就来教大家win8系统如何查看PDF格式,学会了这种方法就可以不借助第三方软件的作用了,赶紧学起来吧! PDF是电子文档是一种不可修改的文件格式,通常用于电子书,手册,合同等方面,其实我们按win8系

PDF文件怎么打开?PDF阅读器下载推荐

PDF是一种由Adobe公司开发的电子文件格式,在日常办公中,很多电子书.产品说明.公司文档都内容都会被制作成PDF文件.由于我们的操作系统默认是不支持打开PDF文件的,所以PDF文件怎么打开就成了很多用户的疑问.其实只要在我们的电脑中安装一款好用的PDF阅读器,就可以轻松阅读PDF文件中的内容了.另外,现在手机和平板电脑的用途越来越广泛,也有不少用户会在手机或平板电脑上浏览PDF文件,那么,在移动设备上又该如何选择PDF阅读器呢? PDF文件怎么打开?PDF阅读器下载推荐 电脑PDF阅读器下载

java web-javaweb jsp显示pdf文件,ie显示导致pdf显示最上层

问题描述 javaweb jsp显示pdf文件,ie显示导致pdf显示最上层 问题是这样的,我最近做了一个阅读pdf文件的页面,不能用后台输出来显示,只能页面读取文件显示.试过用object.embed.iframe等标签,在别的浏览器都可以,但是在ie内核的浏览器显示的时候pdf就显示最上层.由于页面有个验证层的缘故,在显示的时候pdf必须在这验证层的后面,可ie就是恶心,pdf显示在最上层,也不给调样式.求大神们帮忙. 更多0

(在线等!)在网页中有什么好的控件怎么打开pdf文件?

问题描述 各位大神是这样,撸主想实现:在gridview中单击某个超链,通过调用控件来开打对应的PDF文件.因为要求说不能下载或者保存,所以想请问有什么好的PDF控件可以借鉴,或者我的思路是不是有什么问题还有更好的办法!谢谢!在线等! 解决方案 本帖最后由 u012150329 于 2014-01-26 09:36:41 编辑解决方案二: 解决方案三: 解决方案四:引用1楼liuchaolin的回复:转换成swf?还是会被下载.我可能理解的不对,请详细一点,谢谢!解决方案五:引用2楼wg5945

Windows Azure网站服务新功能预览: 生成PDF文件

在 http://www.aliyun.com/zixun/aggregation/13357.html">Azure 网站服务上,我们致力确保它与开发环境中.一般的 IIS 平台有一致的环境,这样一来,开发人员便能够让应用程序在既有机房与云端之间 无缝切换执行. 不过身为一个多租户服务(multi-tenant service),Azure 网站服务设计了一些确保安全的游戏规则,这可能会让一些既 有的应用程序发生一些兼容性问题. 所以今天我们宣布 Azure 网站服务将新增两个功能让使用

Win7系统打开PDF文件出现关联错误怎么办

  Win7系统打开PDF文件出现关联错误怎么办?win7系统每个软件都有对应的打开方式,它们都是相互关联的,如果选择错了,会出现打不开现象. 解决方法: 1.单击开始菜单-运行,并在运行一栏中输入"regedit"按下回车; 2.进入注册表编辑器,按序点击打开:"HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerFileExts.pdf ; 3.把"OpenWithList"注册

在C++中用ActiveX控件显示PDF文件

PDF介绍 PDF是"Portable Document Format 可移植文档格式"的缩写,它是Adobe公司开发的一种电子文档格式,已经成为国际通用的电子文档交换事实标准.PDF文件可以在各种平台下阅读.编辑.发布.该文件格式支持字体.图像.甚至任何附件的嵌入. Adobe公司提供了两种软件用于处理PDF文档,分别是Acrobat及Acrobat Reader:前者功能强大,不仅能阅读,还可以创建或编辑PDF文档,但要收费:后者只具备阅读功能,为免费软件. 用ActiveX控件显

pdf-PDFBOX 打印PDF文件出现在异常

问题描述 PDFBOX 打印PDF文件出现在异常 我使用PDFBOX(版本1.8.3)打印PDF文件时老提示:""未发送 StartDocPrinter 调用""C# 测试代码如下:PDDocument pdf = PDDocument.load(strFileName);pdf.print();帮各位大侠帮忙看看pdfbox 的print方法到底要怎么使用.