【问题标题】:Generated signed PDF crashes Adobe Reader but no other PDF reader生成的签名 PDF 会导致 Adob​​e Reader 崩溃,但其他 PDF 阅读器不会崩溃
【发布时间】:2017-12-14 10:01:11
【问题描述】:

我们有修改 PDF 的代码,然后对修改后的 PDF 进行数字签名。我们使用 LGPL 版本的 iTextSharp 库 (4.1.6) 对 PDF 进行数字签名。

public static Stream DigitallyCertifyPdfStream(Stream uncertifiedFileStream, CertificationBundle certificationBundle)
{
    using (var memoryStream = new MemoryStream())
    {
        var pdfReader = new PdfReader(uncertifiedFileStream);
        var signatureStamper = PdfStamper.CreateSignature(pdfReader, memoryStream, '\0', null);
        signatureStamper.SetEncryption(null, Encoding.UTF8.GetBytes(certificationBundle.Password), PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_MODIFY_ANNOTATIONS, PdfWriter.STANDARD_ENCRYPTION_128);

        var signatureAppearance = signatureStamper.SignatureAppearance;
        signatureAppearance.Reason = "Approval of design";
        signatureAppearance.Location = "";

        var privateKey = certificationBundle.PrivateKey;
        var signingCertificates = new[] { certificationBundle.Certificate };
        signatureAppearance.SetCrypto(privateKey, signingCertificates, null, PdfSignatureAppearance.WINCER_SIGNED);

        pdfReader.Close();
        signatureStamper.Close();

        return new MemoryStream(memoryStream.ToArray());
    }
}

这是一个示例 PDF,它显示了该问题。 PDF 最初会打开,但随后会冻结且无法导航。无论您是否拥有我们的证书来验证已安装此签名,问题似乎都会发生。

此问题似乎并非始终如一地发生,并且该问题仅存在于 Adob​​e Reader 中。浏览器 PDF 查看器和 Foxit Reader(进行签名验证)处理得很好。有时会在一段时间后出现一个错误框,上面写着“打开流时出错”。

另外有趣的是,对于经过相同数字签名过程的 PDF,我们在外观完整性报告中观察到以下内容

目前我们不确定这些是否与问题有关。我提到它们是因为它们可能是相关的。

那么,问题是,为什么这个数字签名的 PDF 会导致 Adob​​e Reader 崩溃,我们该如何补救?

【问题讨论】:

  • 我希望您的签名应用程序的用户知道您正在创建的签名已被弃用(在 PDF 2.0 中不再有效)并且不安全。您创建不安全签名的用例是什么?
  • 欲了解更多信息:itextpdf.com/blog/are-pdf-signatures-shattered(您使用的是 SHA-1)。任何具有一定处理能力的人都可以在不破坏签名的情况下更改您的 PDF。
  • @BrunoLowagie 那么 iTextSharp 的 LGPL 版本无法创建安全签名是真的吗?我看到的加密算法选项是PdfWriter.STANDARD_ENCRYPTION_128PdfWriter.ENCRYPTION_AES_128PdfWriter.STANDARD_ENCRYPTION_40。当前的 iTextSharp 发行版使用什么加密算法?
  • 您使用的是早于 PAdES 标准(2009 年发布)的 iTextSharp 版本,因此这个旧版本不支持所有 PAdES 功能是正常的。您的问题表明缺乏数字签名知识。您的签名的主要问题不在于加密算法。事实上,您使用的是损坏的散列算法和已弃用的安全处理程序。最新版本的 iText 符合 PAdES。
  • 另外:在您的评论中,您提到了加密(使用公钥),而我说的是签名(需要使用私钥加密)。有很大的不同!如果您的问题真的是关于加密(而不是签名),您应该知道所有加密算法在 PDF 2.0 中都已弃用,AES 256 除外。 iText 5 或更早版本不支持 AES 256;仅在 iText 7 中。

标签: pdf itext pdf-generation adobe


【解决方案1】:

您的 PDF 包含损坏的图像:

16 0 obj
<</Type/XObject/BitsPerComponent 8/Interpolate true/Width 736/ColorSpace/DeviceRGB/Filter/DCTDecode/Length 0/Height 1242/Subtype/Image>>stream

endstream
endobj 

此 Image XObject 声称包含 RGB 位图图像(736x1242,24 位),同时为空(长度 0)。如果遇到此类丢失的数据,PDF 查看器可能会失败(尽管 Adob​​e Reader 锁定了一段时间令人印象深刻......)。

请检查源 PDF 中的流是否已损坏。


顺便提一个问题:

    pdfReader.Close();
    signatureStamper.Close();

在关闭压模之前关闭阅读器。由于压模可能需要在关闭过程中访问阅读器,这是一个坏主意。只需切换Close 调用的顺序即可。


顺便说一句,您的代码会生成 adbe.pkcs7.sha1 签名。这在安全方面是一个坏主意,因为无论您在签名中使用哪种安全算法,此机制都使用 SHA1 作为第一个文档哈希,并且 SHA1 通常不再被认为是安全的。

【讨论】:

  • 所以......对此还有一些注意事项。 @mkl ...对于您提到的 XObject 的价值,实际上它的长度为零。流是空的,但正如你所见,它有一个宽度和一个高度等。这很糟糕。我认为这是损坏的签名的外观,这就是悬挂 Adob​​e 查看器的原因。 Foxit 在尝试进行验证时实际上忽略外观......虽然打开文档可能是所需的行为,但这并不好。基于浏览器的查看器只是显示外观......这也不好。
  • 是的,同时是空的并包含一张大图... ;)
  • touché - 我想我爱你。
  • “签名的外观” - 实际上没有。至少不仅如此。据我记得,当我检查 PDF 时,我发现 XObject 作为页面资源实际上是从页面内容流中引用的。我认为 Foxit 只是在这里进行了额外的健全性检查。可能这不是导致 Adob​​e 锁定的实际问题,也许我忽略了 PDF 中的其他问题。
  • Good ol' Acrobat 9.5 在打开 PDF 时警告说没有足够的数据用于图像。看起来当前版本已经取消了一些检查。
猜你喜欢
  • 1970-01-01
  • 2015-04-17
  • 2012-02-13
  • 2018-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 2018-01-09
相关资源
最近更新 更多