当前位置: 首页 > 知识库问答 >
问题:

使用iText 7创建的可见签名在chrome中未显示

陈阳舒
2023-03-14

我正在使用iText 7签署pdf文档。这工作没有问题,签名显示为有效。

除了数字签名,我想在PDF上显示一个可视化的表示。这在数字签名手册第2.4章创建不同的签名外观中进行了描述。

第一个图像是使用word和另存为pdf功能创建的pdf。第二张图片是我刚刚随机下载的演示pdf。

    null
    null

下面的代码示例将使用本地证书对pdf文档进行签名,并将一些文本放入Chrome中未显示的SignatureAppeance中。

using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using System.IO;
using System.Security.Cryptography.X509Certificates;

namespace PdfSigning.Lib.Helpers
{
    public class SignPdfTest
    {
        public static byte[] SingPdfUsingCertificate(X509Certificate2 cert2, byte[] pdfToSign)
        {
            var apk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(cert2.PrivateKey).Private;

            IExternalSignature pks = new PrivateKeySignature(apk, DigestAlgorithms.SHA512);

            var cp = new Org.BouncyCastle.X509.X509CertificateParser();
            var chain = new[] { cp.ReadCertificate(cert2.RawData) };

            using (PdfReader reader = new PdfReader(new MemoryStream(pdfToSign)))
            {
                using (MemoryStream fout = new MemoryStream())
                {
                    StampingProperties sp = new StampingProperties();
                    sp.UseAppendMode();

                    PdfSigner signer = new PdfSigner(reader, fout, sp);
                    PdfSignatureAppearance appearance = signer.GetSignatureAppearance();

                    appearance.SetPageNumber(1);
                    appearance.SetLayer2Text("Hello world");
                    appearance.SetLayer2FontSize(8);

                    Rectangle pr = new Rectangle(10, 10, 200, 100);
                    appearance.SetPageRect(pr);

                    appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
                    appearance.SetPageRect(pr);

                    signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
                    return fout.ToArray();
                }
            }
        }
    }
}



    private static void SignDocumentUsingCertificateConfiguration()
    {
        try
        {
            var certificateSignatureConfiguration = new CertificateSignatureConfiguration();
            var cert2 = new X509Certificate2(@"C:\temp\MyCertificate.pfx", "mypassword", X509KeyStorageFlags.Exportable);
            CertificatePdfSigner certPdfSigner = new CertificatePdfSigner(certificateSignatureConfiguration);

            byte[] signedPdf = PdfSigning.Lib.Helpers.SignPdfTest.SingPdfUsingCertificate(cert2, File.ReadAllBytes(@"C:\temp\WordSaveAsPdf.pdf"));

            File.WriteAllBytes(@"C:\temp\WordSaveAsPdf_Signed.pdf", signedPdf);
            Console.WriteLine("Done");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

共有1个答案

楚承天
2023-03-14

Chrome似乎不读取混合引用PDF的对象流,特别是在签名创建期间添加的增量更新中。

而iText则将签名期间的几乎所有更改放入对象流中。

因此,Chrome不知道添加的签名及其外观。

MS Word以这种混合风格创建PDF,实际上是唯一一个这样做的软件。

iText在新的增量更新中将几乎所有的更改都放入对象流中。

显然,Chrome并不完全支持对象和交叉引用流,特别是如果与进一步的增量更新结合在一起的话。

public class PdfSignerNoObjectStream : PdfSigner
{
    public PdfSignerNoObjectStream(PdfReader reader, Stream outputStream, StampingProperties properties) : base(reader, outputStream, properties)
    {
    }

    protected override PdfDocument InitDocument(PdfReader reader, PdfWriter writer, StampingProperties properties)
    {
        try
        {
            return base.InitDocument(reader, writer, properties);
        }
        finally
        {
            FieldInfo propertiesField = typeof(PdfWriter).GetField("properties", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            WriterProperties writerProperties = (WriterProperties) propertiesField.GetValue(writer);
            writerProperties.SetFullCompressionMode(false);
        }
    }
}

不过,请注意,像这样调整iText功能并不能保证跨版本工作。我针对最近的IText-7.1.7-快照开发状态对其进行了测试;我希望它也适用于以前的7.1.x版本。

很可能两者兼而有之。

一方面,Chrome PDF查看器似乎与混合参考PDF有问题。考虑到它们作为PDF格式的一部分已经有多长时间了,这有点令人失望。

(ISO 32000-1,第7.5.8.4节与不支持压缩参考流的应用程序的兼容性)

在目前的情况下,一个(更新的)页面对象在对象流中,即对不支持交叉引用和对象流的查看者隐藏。

当前,如果基础的PDFReader具有任何交叉引用流(hasxrefstm),iText 7PDFDocument尝试在PDFWriters上强制执行FullCompress:

writer.properties.isFullCompression = reader.HasXrefStm();

(pdfdocument方法open)

如果pdfreader也被标识为混合引用流(hashybridxref),那么可能不应该强制执行。

 类似资料:
  • 带文本和背景图像的数字文本我正在尝试用Java中的PDFBox对pdf文件进行数字签名,在页面上显示可见的文本,类似于在Acrobat中手动创建时所创建的文本。如图像所示(一个只有快照我正在寻找,另一个也有数字签名的详细信息),这个示例显示了使用图像文件进行签名。怎么做?

  • 我有一个私人钥匙在档案里。“privatekey.pem”并且不知道如何创建谁能帮助我吗?我正在尝试使用IText7签名pdf。

  • 我有一个场景,我需要用iText7库从pdf中获取签名信息。签名可能存在,也可能不存在。当我为没有任何数字签名的PDF实例化一个新的对象时,会出现异常 “没有相关的PdfWriter用于进行间接操作。” .如果有签名,就很好用。我不确定如何纠正这个异常。 更新为包含代码示例

  • 是否可以用开放源码软件库pdfbox提取已签名PDF的可见签名(图像)? 工作流: null 像下面这样的oop风格的东西会很棒: 找到了类PDSignature和如何签署一个PDF,但没有解决方案提取一个可见的签名作为图像。

  • 我需要将一个使用iText5进行PDF签名验证/创建的Java程序移植到iText7。 旧代码显然不能按原样工作,因为iText的大部分内容都经过了重组。 我找到的所有关于如何做到这一点的例子和教程都是针对iText5的。(非常好的)白皮书也是如此。它们依赖于通过方法返回的列表,在该方法上执行所有与签名相关的操作。 在iText7中,不再具有该方法。 有人知道iText7的例子/文档吗?

  • 我正在使用这个图书馆https://github.com/vbuch/node-signpdf签署pdf文档。在我签署文档后,当我使用Foxit reader打开pdf时,我可以看到签名,但当我使用Adobe reader DC打开pdf时,我看不到签名。我也尝试过Adobe Reader席,但我也看不到。在pdf xchange viewer中打开文档时,出现以下错误: