Aspose.PDF For NET 如何对一个PDF文件中的多个页面进行数字签名?

你好:
我想对一个PDF文件中的多个页面进行数字签名,比如前三页。
我查看了实例代码发现并没有相关的例子
另外我也搜索了论坛中相关的帖子,发现回复的一些方法都是“过时的”
因此,请问应该如何对一个PDF文件中的多个页面进行数字签名呢?
谢谢!

@howze

为了对多页进行签名,您必须保存第一页,然后再次加载并签名第二页。 请尝试使用以下示例代码。

    public static void SignTest()
    {
        String sourceFile = path + "Test PDF.pdf";
        String signatureImageFile = path + "test_signature.png";
        String pfx = path + "test.pkcs12";
        String pfxPassword = "password";
        String outputFile = path + "aspose_sign2.pdf";

        try
        {

            // Create PdfFileSignature object and bind input PDF files
            PdfFileSignature pdfSign = new PdfFileSignature();
            pdfSign.BindPdf(sourceFile);

            // create a rectangle for signature location
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100, 100, 200, 100);

            // Set signature appearance
            pdfSign.SignatureAppearance=signatureImageFile;

            // Create signature
            PKCS7 signature = new PKCS7(pfx, pfxPassword); // PKCS#7 or

            signature.ShowProperties=false;
            pdfSign.Sign(1, "", "", "", true, rect, signature);

            // save output PDF file
            pdfSign.Save(outputFile);

            pdfSign.BindPdf(outputFile);


            pdfSign.Sign(2, "", "", "", true, rect, signature);

            // save output PDF file
            pdfSign.Save(outputFile);

            Console.WriteLine("Signed file saved at " + outputFile);
        }
        catch (Exception e)
        {
            String s=e.StackTrace;
        }
    }

非常感谢你的答复,我测试你的代码可用,但有两个问题:

1、似乎使用pdfSign.Save()方法的时候只能直接输出文件,而不能输出到memorystream中,我的代码如下:

            // Create PdfFileSignature object and bind input PDF files
            PdfFileSignature pdfSign = new PdfFileSignature();

            // Set signature appearance
            pdfSign.SignatureAppearance = signatureImageFile;

            // Create signature
            PKCS7 signature = new PKCS7(pfx, pfxPassword); // PKCS#7 or

            signature.ShowProperties = false;

            // create a rectangle for signature location
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(10, 10, 100, 100);
            pdfSign.BindPdf(sourceFile);

            MemoryStream stream = new MemoryStream();

            for (int i = 1; i <= 3; i++)
            {
                pdfSign.Sign(i, "resion", "contact", "location", true, rect, signature);

                // save output PDF file
                pdfSign.Save(stream);

                pdfSign.BindPdf(stream);

            }

            Document pdfdocument = new Document(stream);

            pdfdocument.Save(outputFile);

这样运行会报错,但如果不使用memorystrea,直接输出文件则没有问题。

2、在PdfFileSignature类下面以及在pdfSign.Sign()方法中,似乎没有设置“Creator”的属性,这导致在PDF阅读器中查看签名信息的时候,Creator没有显示,如何才能设置这个"Creator"属性呢。
QQ截图20210421135046.png (123.9 KB)

@mudassir.fayyaz
另外,在使用pdfSign.Sign()方法时,似乎无法加入“SigName”,我一旦使用 Sign(int page, string SigName, string SigReason, string SigContact, string SigLocation, bool visible, System.Drawing.Rectangle annotRect, Signature sig);
会提示“Form field not found : ”

@howze

您会在输出中注意到,没有Creator字段是证书特定的属性。因此,如果它使用的证书具有创建者属性,那么它将显示在签名中。如果证书中仍然存在创建者但没有出现在PDF中的问题,请与示例PDF文档一起共享示例证书(.pfx)文件。这将帮助我们在环境中测试场景并相应地解决它。

如果要使用此方法,则“签名名称”应该是放置在PDF页面上的签名字段的名称。如果PDF中没有表单字段,则API将引发异常。此特定的重载用于将签名添加到PDF中的特定SignatureField(表单字段)。

@mudassir.fayyaz
非常感谢你的答复,可能我之前的表达不是很正确。

1、具体来说,那个字段应该不叫“Creator”,应该叫Created By,这个属性和证书本身没有关系,是可以自己去定义的,我使用其他工具进行了测试,可以对这个属性进行设置,只是不知道在Aspose中该如何实现。

2、对于“签名名称”,我指的是Field的名称,Aspose默认签名后,签名名称会显示为“Signature1”,我希望能对这个名称进行修改,同样的,我使用别的工具进行了测试,可以对其修改。

以上的问题我附加了签名后的PDF文件和截图,请查看,谢谢!
signed-Aspose.pdf (826.1 KB)
signed-other.pdf (638.6 KB)
pic-aspose.png (571.8 KB)
pic-other.png (555.3 KB)

感谢您的分享。 但是,为了调查此问题,我仍将要求您与我们共享.pfx文件和源文件,以便我们最终可以用来验证问题。 还请共享您共享的其他工具名称以进行比较。

如果您未在PDF中添加签名字段并直接对其进行签名,则API首先会添加一个带有默认名称即签名1的签名字段,然后将签名放在其上。 为了方便起见,我们尝试使用API来实现此目的。

Document doc = new Document();
            doc.Pages.Add();
            SignatureField field = new SignatureField(doc.Pages[1], new Rectangle(10, 800, 100, 700));
            field.PartialName = "MySignField";
            field.Border = new Border(field);
            field.Contents = "Signature Field for John Doe";
            field.Border.Width = 5;
            doc.Form.Add(field);
            doc.Save(dataDir + "SignatureField_out.pdf");

            string file = dataDir + "SignatureField_out.pdf";

        Document pdfDocument = new Document(file);

        var pkcs7 = new Aspose.Pdf.Forms.PKCS7(dataDir + "mykey2.pfx", "aa");
        pkcs7.ShowProperties = true;
        using(var signature = new Facades.PdfFileSignature(pdfDocument))
        {
            signature.Sign("MySignField", "MyReason", "SigContact", "SigLocation", pkcs7);
            //signature.Sign(1, true, new System.Drawing.Rectangle(300, 100, 400, 200), pkcs7);
            signature.Save(dataDir + "1stoutput.pdf");
        }

@mudassir.fayyaz
1、我上传了原始PDF文件和证书,请查看,签名后的文件在之前回复的附件中有。

2、根据你的代码需要首先添加签名字段(field),然后再进行签名,才可以自定义签名字段的名字,如果我要同时对多页进行签名,那首先要有一个循环给每一页添加签名字段,然后再来一个循环对每一页进行签名,不能直接在循环里通过一个方法完成这两步吗?
test.zip (593.3 KB)

@howze

实际上,您的要求是设置签名的名称。 该名称实际上是完成签名的字段的名称。 默认值为API签名。 但是,按照我的解释进行操作时,它将选择字段名称作为签名名称。 这就是在API中完成实现的方式。

为了增加创建者的准备,已创建了ID为PDFNET-49803的票证以提供支持。 该线程已与问题联系在一起,因此一旦获得支持,便会通知您。