国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

用C#實現(xiàn)pdf文件的完整性驗證

2019-11-18 16:36:17
字體:
來源:轉載
供稿:網友
    現(xiàn)在對文件的完整性驗證,防止文件被篡改的技術已經比較成熟,一般使用數字簽名,數字水印等,最近我在一個項目中也遇到了防篡改的需求。該項目要求用戶將原始發(fā)票用專門的掃描程序掃描成pdf文件,然后將該pdf文件傳到服務器上,在上傳的同時必須要驗證這個pdf是沒有被手工修改過的。我剛一接觸到這個需求想到的就是使用數字水印,要不然就直接使用PDF的數字簽名功能,不過這些方法都感覺比較比較復雜,一大堆的英文文檔也沒有心思去研究,于是琢磨了半天,寫了一個簡化版的數字水印程序,實現(xiàn)了pdf文件完整性驗證。
    驗證的基本思路是:
    對文件全部內容計算其md5值,這樣無論用戶修改了文件的任何一個地方,那么生成的MD5的是完全不一樣的,我們可以將這個MD5寫到文件的一個隱藏區(qū),一般二進制文件格式都有文件頭和文件體部分,而文件頭是用戶看不到的,一般也會預留一部分字節(jié)用于以后擴展,或可以在文件頭寫入特殊標記的數據。于是研究了一下pdf文件的格式,試著往其第10個字節(jié)插入了MD5值,結果文件雖然可以使用,但是每次打開的時候都會提示“文件修復”。原來是寫在頭上面的內容將pdf文件的字節(jié)數和文件中對象的地址改變了,導致了文件錯誤,原因找到了那么解決辦法也就有了,為了不改變pdf文件中對象的地址,那么我們將這個md5寫在文件尾不就可以了嘛!于是在客戶端(掃描程序)將掃描出的pdf文件流計算MD5值,然后將該文件流和MD5值一起寫到硬盤上,形成一個添加了MD5值的pdf文件。文件可以正常打開和使用,而且用戶也不會看到我們添加的這個MD5值。
    在服務器端,我們將上傳上來的文件流除了最后32個字節(jié)以為的部分計算MD5值(這兒取32個字節(jié)是因為最后這32字節(jié)是我們寫的MD5),將前面部分算出的MD5和最后32個字節(jié)的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中的字節(jié)內容算MD5
19               result = MD5String(result +key);//這兒點的key相當于一個密鑰,這樣一般人就是知道使用MD5算法,但是若不知道這個字符串還是無法計算出正確的MD5
20
21               byte[] md5 = System.Text.Encoding.ASCII.GetBytes(result);//將字符串轉換成字節(jié)數組以便寫人到文件中
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位以外的字節(jié)計算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文件,對于其他一些格式也可以用,這主要是取決于文件的格式規(guī)范。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 长海县| 原阳县| 乡宁县| 赤峰市| 航空| 泽普县| 东台市| 灯塔市| 清镇市| 开鲁县| 灌南县| 伽师县| 绥中县| 铜陵市| 黄龙县| 乐亭县| 波密县| 封丘县| 兰溪市| 韩城市| 孟津县| 嵊州市| 蒙城县| 宁陕县| 英山县| 承德市| 宜州市| 沙田区| 新泰市| 澄迈县| 香格里拉县| 鹿邑县| 凤阳县| 旺苍县| 施秉县| 无锡市| 江川县| 讷河市| 佳木斯市| 望城县| 贺州市|