返回PDF页面的SHA256哈希值

时间:2014-10-08 21:41:17

标签: c# wpf pdf hash pdfsharp

我正在编写一个C#WPF应用程序,我在其中插入一个“标题”页面作为一批PDF文档的第一页。标题页取自批次中第一个pdf的第一页。

用户将启动此过程,但我想确保以后用户无法再次运行此过程,这将导致插入另一个标头。

所以我的计划是获取头页面的SHA256哈希值,并将其与其他pdf的第一页的哈希值进行比较。如果它们匹配,则第一页与标题页相同,否则我们插入标题。

我敲了下面的代码来测试获取pdf中第一页的哈希值,但每次运行时哈希值都不同。

为什么每次都不一样?

由于

using System.IO;
using System.Text;
using System.Security.Cryptography;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;

namespace Syncada
{
    public class PDFDoc
    {

        private PdfDocument pdfDoc;

        public PDFDoc(string path)
        {
            pdfDoc = PdfReader.Open(path,PdfDocumentOpenMode.Import);
        }

        public string GetPageOneHash()
        {

            byte[] hash;

            PdfPage page = pdfDoc.Pages[0];
            using (MemoryStream stream = new MemoryStream())
            {
                PdfDocument doc = new PdfDocument();
                doc.AddPage(page);
                doc.Save(stream,false);

                SHA256 sha256 = SHA256.Create();
                hash = sha256.ComputeHash(stream);
            }

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            return sb.ToString();
        }
    }
}

4 个答案:

答案 0 :(得分:3)

  

我敲了下面的代码来测试获取pdf中第一页的哈希值,但每次运行时哈希值都不同。

     

为什么每次都不一样?

您不计算页面的哈希,而是计算您添加页面的新PDF文档的哈希。不幸的是,PDF文档包含创建日期,最后修改日期和唯一ID等信息。由于每次计算哈希值时这些信息都不同,因此您将永远不会获得相同的哈希值(除非您发生冲突)。

答案 1 :(得分:1)

首先检查流保存后是否正在重绕流。如果没有,那么你实际上并没有阅读任何内容,因为doc.Save(stream, false)会在流的末尾离开你。

要使用stream.Seek(0, SeekOrigin.Begin);来回放信息流。

如果没有解决问题,请检查.Save生成的文档在程序运行期间是否相同。每次生成文档时,文档中可能存在某些内容(可能是时间戳)。

答案 2 :(得分:1)

正如mkl已经写过的那样,您每次都在创建一个新的PDF文档,因此创建日期/时间和修改日期/时间会有所不同。

此外,随机值也用于PDF中包含的字体,因此每次运行程序时这些字体也会有所不同。

使用PDFsharp的DEBUG版本时,PDF文件将包含许多注释。您可以使用任何DIFF程序来查看不同的内容。

由于PDF页面可以引用PDF文件中的许多其他对象,因此计算可靠的哈希值并不是一件容易的事。

另一种方法:使用像GhostScript这样的库来创建第一页的图像并计算它的哈希值。如果页面看起来相同,您将获得相同的哈希值。

答案 3 :(得分:0)

您还可以在页面字典中插入自定义键,并在重新加载文件时检查密钥是否存在。