签名后如何锁定 PDF 文档?

2023-12-08

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

iTextSharp 还可以签署文档,并且还可以向已签名的文档添加进一步的签名。 iTextSharp 基本上也可以设置文档的权限,但不知何故我无法让它设置与 Acrobat X Pro 相同的权限。我设置了以下权限:

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

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

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

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

  • 打印:允许(OK)
  • 修改文档:不允许(OK)
  • 组装:不允许(OK)
  • 复制内容:允许(确定)
  • 屏幕阅读器:允许(确定)
  • 删除页面:允许(不行)
  • 注释:允许(不行)
  • 填写表格:允许(不行)
  • 签名:允许(不行)
  • 创建模板:允许(未知)

我没有使用加密,因为这只有在放置第一个签名之前才有可能。另外,我真的不想使用它,因为 a) 如果没有查看者密码,它基本上毫无用处;b) 在签名后锁定文档时,Acrobat 也不会执行此操作。

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

我的 iTextSharp 版本是 5.2.1。最新版本有不兼容的 API 更改,我尚未解决。

那么如何才能达到与 Acrobat 相同的结果呢?

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

Update:

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


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

在新签名字段中将新签名添加到可能已签名或未签名的现有 PDF,

解决方案有点困难:而不是DocMDP变换方法(用于认证)FieldMDP变换方法必须使用。欲了解详细信息,请阅读ISO 32000-1,特别是第 12.8 节。

我尝试一步完成此操作,但不幸的是,当前状态(版本 5.4.4)的 iText 仅正确支持已存在字段中的锁定字典。

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

因此,这里有一个两步解决方案,首先添加一个带有锁定信息的空签名字段,然后对该字段进行签名。我是用 Java 完成的(我在那里更熟悉),但是移植到 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 在幕后应用了锁。

不过这个功能是从 iText 5.3.2 开始才可用的,我也没有查过它是什么时候完全移植到 iTextSharp 上的。

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

输入文件签名一次:

enter image description here

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

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

签名后如何锁定 PDF 文档? 的相关文章

随机推荐

  • 如何编码 WAV 以使用 SIPp 播放

    通过观察另一个SIPp相关问题我了解到现在可以使用rtp stream action 我尝试了几个不同的 WAV 文件 但没有成功 我听到的只是一些噪音 而不是预期的声音 在上述问题的一条评论中 有一条简单的指令将 WAV 文件转换为兼容格
  • SQL Server表默认是排序的

    我有一个简单的 SSIS 包 可以将平面文件中的数据导入到 SQL Server 表 SQL Server 005 中 文件包含 70k 行 表没有主键 导入成功 但是当我打开 SQL Server 表时 行的顺序与文件的顺序不同 仔细观察
  • SwiftUI TabView 在添加/删除 CoreData 元素期间给出错误消息

    我目前正在尝试将 TabView 与 CoreData 一起用于轮播视图 PageTabViewStyle 当我按如下顺序添加新页面时 不会发生错误 age name 3 page name 4 page name 5 但是 如果我将数字放
  • 如何从 Swift 中的时间服务器获取当前时区的当前日期?

    我正在开发应用程序 我想根据用户当前时区获取当前日期 即使用户从设备设置菜单更改日期后也是如此 获取我使用的当前时区 let timeZone TimeZone current print timeZone 例如 这里我得到 亚洲 加尔各答
  • 在 Java 中连接 WAV 文件

    这是我的代码 它连接四个 wav 文件并生成 wavAppend wav 这个串联的文件可以在 Windows Media Player 中很好地播放 但通过PlaySound类 只能听到one wav 有人可以帮忙吗 class Play
  • JSON Scraping - 通过 Javascript 将军事时间转换为标准时间

    我正在从 url 中抓取 JSON 数据 时间是军用时间 我想知道在客户端检索后是否有办法将其转换为标准时间 这是 JSON SaturdayClose 21 00 SaturdayOpen 10 00 SundayClose 12 00
  • 如何向直方图添加边缘颜色

    在使用 seaborn 和 Jupyter 笔记本做一些练习问题时 我意识到 distplot 图表在各个 bin 上没有文档中所有示例图表所具有的较暗轮廓 我尝试使用 Pycharm 创建图表并注意到同样的事情 我认为这是一个seabor
  • gvim 病原体问题

    我从github下载了pathogen vim并将其放在 vim下的 autoload 目录中 然而现在当我启动 gvim 并执行 helptags 时 它说 需要参数 我的 vimrc 文件的内容是 call pathogen runti
  • 命中测试 SVG 形状?

    已经实现了 SVG 规范部分内容的浏览器 Firefox 等 免费为我们进行命中测试 如果我在 SVG 对象上附加 mousedown 侦听器 则每当单击该形状时我都会收到通知 这是令人惊奇的 特别是对于复杂的多边形形状 我想知道是否有一种
  • AvalonDock 停靠一个窗口

    我正在尝试将 WPF 中的应用程序转换为可以使用AvalonDock 我有几个窗口 大约 10 个 和主窗体DockingManager 我想把那些窗户放在里面DockingManager 我试过这个
  • 无法在 Kotlin 中替换字符串内的字符串

    我正在尝试替换字符串中的一些子字符串 但我的代码似乎不起作用 val listOfMaleWords listOf him he his val listOfFemaleWords listOf her she her fun modify
  • 如何从Python扩展模块的C代码调用内置函数(或方法)?

    我目前想要完成的是调整Pythonitertools模块功能combinations对通过的进行排序iterable在创建组合之前 目的是对返回的组合进行排序 我是第一次开发 Python 扩展模块 到目前为止我唯一的经验是编写和编译一个像
  • 许多二进制文件同步

    我的办公服务器上有大约 100 000 个文件 图像 pdf 等 文件数量每天都会增加大约 100 500 个项目 并且大约有 20 50 个旧文件发生更改 将 Web 服务器与这些文件同步的最佳方法是什么 像 Mercurial GIT
  • 自定义类型编码后无法操作? Spark数据集

    假设你有这个 编码自定义类型的解决方案来自这个线程 assume we handle custom type class MyObj val i Int val j String implicit val myObjEncoder org
  • 如何为 future 配置微调线程池?

    Scala 的 future 线程池有多大 我的 Scala 应用程序赚了数百万美元future 我想知道是否可以通过配置线程池来优化它们 谢谢 这个答案来自 Monkjack 是对已接受答案的评论 然而 人们可能会错过这个很好的答案 所以
  • 组织内存缓存键

    我试图找到一种好方法来处理内存缓存键 以便以更文明的方式在缓存层中存储 检索和更新数据 发现了这个模式 看起来很棒 但是如何将它变成 PHP 应用程序的功能部分呢 身份映射模式 http martinfowler com eaaCatalo
  • Python:为什么 np.where 不适用于两个条件?

    我有以下数据框 gt gt gt import pandas as pd gt gt gt import numpy as np gt gt gt df test pd DataFrame id 100 101 102 103 104 dr
  • 如何在WordPress主题中包含styles.css?

    我正在尝试将 styles css 样式表包含在我正在尝试开发的 WordPress 主题中 我的第一个主题 问题 如何将其纳入其中 我知道将以下代码放入 header php 文件中可以正常工作 但是我宁愿通过functions php
  • 从产品类别和自定义元键对 WooCommerce 产品进行排序

    我使用自定义插件 和meta key 成功地按喜欢 计数 过滤了我的所有WordPress帖子 这也让我可以过滤类别中最喜欢的帖子 我在自定义页面模板中显示 查询 结果 一切正常 Like 功能也适用于 WooCommerce 产品 但到目
  • 签名后如何锁定 PDF 文档?

    Adobe Acrobat 可以选择在签名后锁定 PDF 文档 这会更改文档权限 以便 Acrobat 不再提供对文档进行再次签名或修改注释或表单的功能 在文件被多个实体签署供审查并最终由负责人发布后 这似乎是一个合理的行动 iTextSh