生成的签名 PDF 使 Adobe Reader 崩溃,但没有其他 PDF reader
Generated signed PDF crashes Adobe Reader but no other PDF reader
我们有修改 PDF 的代码,然后对修改后的 PDF 进行数字签名。我们使用 iTextSharp 库 (4.1.6) 的 LGPL 版本对 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, '[=12=]', 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 最初将打开,但随后冻结且不可导航。无论您是否安装了我们的证书来验证此签名,问题似乎都会发生。
这个问题似乎并没有经常发生,而且这个问题只存在于 Adobe Reader 中。浏览器 PDF 查看器和 Foxit Reader(进行签名验证)处理得很好。有时会在一段时间后出现一个错误框,上面写着 "There was an error opening the stream."
另外有趣的是,对于经过相同数字签名过程的 PDF,我们在外观完整性报告中观察到以下内容
目前我们不确定这些是否与问题有关。我提到它们是因为它们可能相关。
那么,问题是为什么这个经过数字签名的 PDF 会导致 Adobe Reader 崩溃,我们该如何补救?
您的 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 位),同时为空(Length 0)。如果遇到此类缺失数据,PDF 查看器可能会失败(尽管令人印象深刻的是 Adobe Reader 锁定了一段时间...)。
请检查源 PDF 中的流是否已损坏。
顺便提一期:
pdfReader.Close();
signatureStamper.Close();
您在关闭压模之前关闭 reader。由于压模可能需要在关闭过程中访问 reader,这是一个坏主意。只需切换 Close
调用的顺序。
顺便说一下,您的代码会生成一个 adbe.pkcs7.sha1 签名。这在安全方面是个坏主意,因为无论您在签名中使用哪种安全算法,此机制都将 SHA1 用于第一个文档哈希,否则 SHA1 通常不再被认为是安全的。
我们有修改 PDF 的代码,然后对修改后的 PDF 进行数字签名。我们使用 iTextSharp 库 (4.1.6) 的 LGPL 版本对 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, '[=12=]', 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 最初将打开,但随后冻结且不可导航。无论您是否安装了我们的证书来验证此签名,问题似乎都会发生。
这个问题似乎并没有经常发生,而且这个问题只存在于 Adobe Reader 中。浏览器 PDF 查看器和 Foxit Reader(进行签名验证)处理得很好。有时会在一段时间后出现一个错误框,上面写着 "There was an error opening the stream."
另外有趣的是,对于经过相同数字签名过程的 PDF,我们在外观完整性报告中观察到以下内容
目前我们不确定这些是否与问题有关。我提到它们是因为它们可能相关。
那么,问题是为什么这个经过数字签名的 PDF 会导致 Adobe Reader 崩溃,我们该如何补救?
您的 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 位),同时为空(Length 0)。如果遇到此类缺失数据,PDF 查看器可能会失败(尽管令人印象深刻的是 Adobe Reader 锁定了一段时间...)。
请检查源 PDF 中的流是否已损坏。
顺便提一期:
pdfReader.Close();
signatureStamper.Close();
您在关闭压模之前关闭 reader。由于压模可能需要在关闭过程中访问 reader,这是一个坏主意。只需切换 Close
调用的顺序。
顺便说一下,您的代码会生成一个 adbe.pkcs7.sha1 签名。这在安全方面是个坏主意,因为无论您在签名中使用哪种安全算法,此机制都将 SHA1 用于第一个文档哈希,否则 SHA1 通常不再被认为是安全的。