签名后如何锁定PDF文档? [英] How can I lock a PDF document after signing it?

查看:1248
本文介绍了签名后如何锁定PDF文档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Adob​​e Acrobat可以选择在签名后锁定PDF文档。这会更改文档权限,以便Acrobat不再提供对文档的签名或修改注释或表单。在签署文件供多个实体审核并最终由负责人发布之后,这似乎是一个合理的行动。

Adobe Acrobat has the option to lock the PDF document after signing it. This changes the document permissions so that Acrobat does not offer signing the document again or modifying annotations or forms. This seems like a reasonable action to do after a document has been signed for review by multiple entities and finally for release by someone responsible.

iTextSharp也可以签署文件,它还可以为已签名的文档添加更多签名。 iTextSharp基本上也可以设置文档的权限,但不知何故我不能让它设置与Acrobat X Pro相同的权限。我设置了以下权限:

iTextSharp can also sign documents, and it can also add further signatures to an already signed document. iTextSharp basically also can set the document's permissions, but somehow I can't get it to set the same permissions as Acrobat X Pro does. I set the following permissions:


  • PdfWriter.ALLOW_COPY

  • PdfWriter.ALLOW_DEGRADED_PRINTING

  • PdfWriter.ALLOW_PRINTING

  • PdfWriter.ALLOW_SCREENREADERS

  • PdfWriter.ALLOW_COPY
  • PdfWriter.ALLOW_DEGRADED_PRINTING
  • PdfWriter.ALLOW_PRINTING
  • PdfWriter.ALLOW_SCREENREADERS

我没有设置以下权限(应该是其他所有权限):

I do not set the following permissions (which should be all else):


  • PdfWriter.ALLOW_ASSEMBLY

  • PdfWriter.ALLOW_FILL_IN

  • PdfWriter.ALLOW_MODIFY_ANNOTATIONS

  • PdfWriter.ALLOW_MODIFY_CONTENTS

  • PdfWriter.ALLOW_ASSEMBLY
  • PdfWriter.ALLOW_FILL_IN
  • PdfWriter.ALLOW_MODIFY_ANNOTATIONS
  • PdfWriter.ALLOW_MODIFY_CONTENTS

无论如何,在保存这样的文档后,我在Acrobat X Pro中看到以下权限:

Anyway, after saving a document like that, I see the following permissions in Acrobat X Pro:


  • 打印:允许(确定)

  • 修改文件:不允许(确定)

  • 装配:不允许(确定)

  • 复制内容:允许(好)

  • 屏幕阅读器:允许(确定)

  • 删除页面:允许(不行)

  • 注释:允许(不正常)

  • 填写表格:允许(不正常)

  • 签名:允许(不行)

  • 创建模板:允许(未知)

  • Printing: Allowed (OK)
  • Modifying document: Not allowed (OK)
  • Assembly: Not allowed (OK)
  • Copy contents: Allowed (OK)
  • Screen reader: Allowed (OK)
  • Remove pages: Allowed (NOT OK)
  • Annotate: Allowed (NOT OK)
  • Fill in forms: Allowed (NOT OK)
  • Sign: Allowed (NOT OK)
  • Create templates: Allowed (unknown)

我不是使用加密因为只有在放置第一个签名之前才可以使用加密。另外,我真的不想使用它,因为a)没有查看器密码,它基本上没用,b)签名后锁定文件时Acrobat不会这样做。

I'm not using encryption because that is only possible before putting the first signature. Also, I don't really want to use it because a) it's basically useless without a viewer password and b) Acrobat doesn't do it either when locking a document after signing.

我的代码基于iSafePDF项目(Codeplex上的开源),它在现有文档上以某种方式使用PdfStamper。

My code is based on the iSafePDF project (open-source on Codeplex) which is using PdfStamper in some way on an existing document.

我的iTextSharp版本是5.2 0.1。最新版本的API更改不兼容,我还没有解决。

My iTextSharp version is 5.2.1. The latest version has incompatible API changes that I didn't resolve yet.

那么我怎样才能获得与Acrobat相同的结果?

So how can I achieve the same result as with Acrobat?

(我知道我的应用程序仍然可以签署文档,因为它不关心现有权限。但至少其他Acrobat用户应该正确地看到预期权限。)

(I'm aware that my application will still be able to sign the document because it doesn't care for the existing permissions. But at least other Acrobat users should see the "intended permissions" correctly.)

更新:

我已经进一步调查了这个问题,它似乎来了从这里:权限只能通过PdfStamper.SetEncryption方法设置,作为其第4个参数。但是,在附加签名的同时调用此方法会导致以下DocumentException:追加模式不支持更改加密状态。我没有看到设置权限但不加密的方法。这是问题吗? iTextSharp是否根本不支持实际可能的内容?

I have further investigated the issue and it seems to come from here: The permissions can only be set through the PdfStamper.SetEncryption method, as its 4th parameter. But calling this method together with appending a signature leads to the following DocumentException: "Append mode does not support changing the encryption status." I haven't seen a method that sets permissions but not encryption. Is this the problem? Does iTextSharp simply not support what's actually possible?

推荐答案

如果您的用例仅需要签署未签名的PDF,则锁定很容易:您只需为您的 PdfSignatureAppearance 对象设置 CertificationLevel = CERTIFIED_NO_CHANGES_ALLOWED 。但是,因为您的用例是

If your use case only required signing unsigned PDFs, locking would be easy: You simply would have set CertificationLevel = CERTIFIED_NO_CHANGES_ALLOWED for your PdfSignatureAppearance object. But as your use case is to


在新签名字段中添加新签名到现有PDF,可以签名,也可以不签名,

add a new signature in a new signature field to an existing PDF which may or may not be signed,

解决方案有点困难:取代 DocMDP转换方法(用于认证)<必须使用strong> FieldMDP转换方法。有关详细信息,请参阅 ISO 32000-1 ,特别是第12.8节。

the solution is somewhat more difficult: Instead of the DocMDP transform method (used for certification) the FieldMDP transform method has to be used. For details read ISO 32000-1, especially section 12.8.

我试图一步完成这一步但不幸的是,iText在当前状态(版本5.4.4)中只能正确支持锁定字典已经存在的字段。

I tried to do this in one step but, unfortunately, iText in its current state (version 5.4.4) only properly supports lock dictionaries in already existing fields.

@Bruno在签名时为运行时创建的字段添加锁字典支持也不会太困难。

@Bruno It should not be too difficult to add a lock dictionary support for fields created on the run while signing, too.

因此,这里有一个两步解决方案,首先添加一个带有锁定信息的空签名字段,然后对该字段进行签名。我是用Java做的(我更喜欢在那里)但这不应该太难以移植到C#。

Thus, here a two-step solution first adding an empty signature field with locking information and then signing this field. I did it in Java (I'm more at home there) but this should not be too difficult to port to C#.

// STEP 1 --- prepare a signature field with locking information
//
// Creating the reader and the stamper for adding the field
PdfReader reader = new PdfReader(SRC);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, baos, (char)0, true);

// adding the empty signature field
PdfFormField field = PdfFormField.createSignature(stamper.getWriter());
field.setFieldName("Signature");
field.put(PdfName.LOCK, stamper.getWriter().addToBody(new PdfSigLockDictionary(LockPermissions.NO_CHANGES_ALLOWED)).getIndirectReference());
field.setFlags(PdfAnnotation.FLAGS_PRINT);
field.setPage(1);
field.setWidget(new Rectangle(150, 250, 300, 401), PdfAnnotation.HIGHLIGHT_INVERT);
stamper.addAnnotation(field, 1);

// finishing the intermediate PDF
stamper.close();
reader.close();

// STEP 2 --- sign the prepared signature field, nothing special
//
// Creating the reader and the stamper for signing
reader = new PdfReader(baos.toByteArray());
FileOutputStream os = new FileOutputStream("target/test-outputs/test_signed-with-lock-field-2step.pdf");
stamper = PdfStamper.createSignature(reader, os, '\0', null, true);

// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason("reason");
appearance.setLocation("location");
appearance.setVisibleSignature("Signature");

// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, CryptoStandard.CMS);

如您所见,签署准备好的空签名字段时,在第二步中没有什么特别的事可做,iText在引擎盖下应用锁。

As you see, there is nothing special to do in the second step when signing the prepared empty signature field, iText applies the lock under the hood.

此功能仅在iText 5.3.2之后才可用,我还没有检查它何时被完全移植到iTextSharp。

This feature, though, has only been available since iText 5.3.2, and I have not checked when it was completely ported to iTextSharp.

对于测试运行(使用自签名测试证书,因此警告)我得到了:

For a test run (using self-signed test certificates, thus the warnings) I got:

输入文件签名一次:

输出文件签名两次并锁定:

The output file signed twice and locked:

这篇关于签名后如何锁定PDF文档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆