我目前正在使用此方法来加密我的 pdf 数据。它可以很好地使 pdf 成为只读文件,并且还表示它允许数字签名。然而,当我尝试签名时,我得到了 这个错误绝对有道理。
当前文档中不允许创建新签名。原因:
PDF权限字典不允许修改或创建 交互式表单字段,包括文档提交时的签名字段 以用户访问权限打开!
我的问题是是否可以创建一个不可编辑的 pdf,以便我可以将其提供给我的客户,但他们将能够在线对其进行数字签名而无需更改其内容。
private byte[] EncryptPdfData(byte[] pdfData)
{
// Create a memory stream to work with the PDF data
using (MemoryStream ms = new MemoryStream())
{
// Create a PdfReader to read the existing PDF data
using (PdfReader reader = new PdfReader(pdfData))
{
// Create a PdfStamper to modify the PDF
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
// Set encryption options
stamper.SetEncryption(null, // User password (empty means no password)
null, // Owner password (empty means no password)
PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_MODIFY_ANNOTATIONS, // Permissions (allow printing and modify annotations)
PdfWriter.ENCRYPTION_AES_128); // Encryption strength
// Ensure the changes are applied
stamper.Close();
}
}
// Return the encrypted PDF data
return ms.ToArray();
}
}
我认为OP正在谈论PDF权限,它在PDFSpec中定义为“用户访问权限”。当然,通过使用忽略这些(或任何其他黑客)的工具,可以编辑文件。但这不是问题。
源代码很明显:
// Set encryption options
stamper.SetEncryption(null, // User password (empty means no password)
null, // Owner password (empty means no password)
PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_MODIFY_ANNOTATIONS, // Permissions (allow printing and modify annotations)
PdfWriter.ENCRYPTION_AES_128); // Encryption strength
我认为您需要更改权限
ALLOW_MODIFY_ANNOTATIONS -> PdfWriter.ALLOW_FILL_IN
stamper.SetEncryption(null, // User password (empty means no password)
null, // Owner password (empty means no password)
PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_FILL_IN, // Permissions (allow printing and allow signing)
PdfWriter.ENCRYPTION_AES_128); // Encryption strength
当然还有其他可能性,例如将所有非签名表单字段设置为只读或拼合除签名字段之外的整个 PDF。这取决于您对“只读”的确切定义。这是否意味着“无法修改其内容”或“无法填写表单或添加新的表单字段”等
补充一点: 您没有设置任何密码。因此,“空意味着没有密码”对于用户密码是正确的,但对于所有者密码则不正确。对于这一点,稍后将使用一些随机值(createDocumentID 方法的哈希和)值。所以总有一个密码只是您不知道而已。但如果您不需要它也没关系。
if (ownerPassword == null || ownerPassword.length == 0)
ownerPassword = md5.digest(createDocumentId());