使用 Python 加密或解密 PDF 文档

0 阅读8分钟

合同、财务报表和人事档案等 PDF 文件通常包含敏感信息。如果需要通过邮件或网盘分享,最好先为文档设置密码和访问权限,避免未经授权的人员查看或修改内容。

使用 Spire.PDF for Python,可以通过安全策略为 PDF 设置密码和权限限制。例如,为文档设置打开密码,限制打印、复制或修改等操作。本文将介绍 PDF 加密中两种密码的区别,并通过具体代码演示如何加密、检测和解密 PDF 文档。

为什么要加密 PDF?

PDF 加密主要用于保护文档内容,并控制其他人可以执行的操作。常见用途包括:

  • 限制文档访问: 设置打开密码后,用户需要输入正确的密码才能查看文档内容。
  • 控制文档操作: 可以设置打印、复制、修改内容和填写表单等权限,限制用户打开文档后的操作。
  • 保护敏感信息: 对包含合同、财务数据或个人信息的 PDF 进行加密,降低文件在传输和共享过程中泄露的风险。
  • 满足文档管理要求: 在企业文档归档和自动化处理流程中,通过密码和权限设置加强文件管理。

需要注意,PDF 加密并不是简单地隐藏文件内容,而是通过密码和权限策略控制文档的访问与使用。

环境准备

本文使用 Spire.PDF for Python 实现 PDF 加密和权限管理,无需依赖 Adobe Acrobat 等外部软件。

首先,打开终端或命令提示符,执行以下命令安装:

pip install Spire.PDF

安装完成后,在 Python 脚本中导入相关模块:

from spire.pdf.common import *
from spire.pdf import *

理解 PDF 加密中的两种密码

PDF 密码保护主要涉及两种密码:用户密码和所有者密码。它们的作用不同,设置时需要根据实际的安全需求进行选择。

  • 用户密码(User Password,也称打开密码): 用于控制文档能否打开。设置后,用户必须输入正确的密码才能查看 PDF 内容。
  • 所有者密码(Owner Password,也称权限密码): 用于控制文档的权限设置。知道该密码的用户可以修改权限限制或解除加密保护。

两种密码可以设置为相同的值,也可以分别设置。常见的配置方式有两种:

  1. 同时设置用户密码和所有者密码: 用户需要输入打开密码才能查看文档,而所有者密码用于修改权限设置或解除保护。
  2. 只设置所有者密码: 用户密码留空,文档无需输入密码即可打开,但仍会受到设定的权限限制。知道所有者密码的用户才能修改这些限制。

下面分别介绍这两种加密方式。

方法一:使用打开密码加密 PDF(RC4_128)

如果希望限制其他人直接打开 PDF,可以同时设置用户密码和所有者密码。下面的示例使用 PdfPasswordSecurityPolicy 创建安全策略,将用户密码设置为 open,所有者密码设置为 test,并使用 RC4 128 位算法加密文档。

from spire.pdf.common import *
from spire.pdf import *

inputFile = "SampleB_1.pdf"
outputFile = "Encryption.pdf"

doc = PdfDocument()
doc.LoadFromFile(inputFile)

# 设置用户密码和所有者密码
securityPolicy = PdfPasswordSecurityPolicy("open", "test")

# 设置 RC4 128 位加密算法
securityPolicy.EncryptionAlgorithm = PdfEncryptionAlgorithm.RC4_128

# 设置文档权限
dp = PdfDocumentPrivilege.ForbidAll()
dp.AllowPrint = True
dp.AllowFillFormFields = True
securityPolicy.DocumentPrivilege = dp

# 应用安全策略并保存文档
doc.Encrypt(securityPolicy)
doc.SaveToFile(outputFile)
doc.Close()

为 PDF 设置打开密码.png

这里的 PdfPasswordSecurityPolicy("open", "test") 用于创建密码安全策略,其中第一个参数是用户密码,第二个参数是所有者密码。

接下来,通过 PdfDocumentPrivilege.ForbidAll() 禁止所有文档操作,再根据需要开放打印和填写表单的权限。这样,用户输入正确的打开密码后,仍然只能执行允许的操作。

最后,调用 doc.Encrypt(securityPolicy) 应用加密策略,并通过 SaveToFile() 将加密后的文档保存到指定路径。需要注意,加密设置只有在保存文件后才会写入输出文档。

方法二:使用 AES_256 加密并设置精细权限

对于安全要求更高的文档,可以使用 AES 256 位加密算法,并根据实际需求设置文档权限。

下面的示例不设置用户密码,只设置所有者密码 test,同时允许低分辨率打印和填写表单:

from spire.pdf.common import *
from spire.pdf import *

inputFile = "SampleB_1.pdf"
outputFile = "ChangeSecurityPermission.pdf"

doc = PdfDocument()
doc.LoadFromFile(inputFile)

# 用户密码留空,只设置所有者密码
securityPolicy = PdfPasswordSecurityPolicy("", "test")

# 使用 AES 256 位加密算法
securityPolicy.EncryptionAlgorithm = PdfEncryptionAlgorithm.AES_256

# 设置允许的文档操作
dp = PdfDocumentPrivilege.ForbidAll()
dp.AllowDegradedPrinting = True
dp.AllowFillFormFields = True
securityPolicy.DocumentPrivilege = dp

doc.Encrypt(securityPolicy)
doc.SaveToFile(outputFile)
doc.Close()

为 PDF 设置权限密码.png

与方法一不同,这里将用户密码设置为空字符串,意味着打开文档时不需要输入密码,但文档仍然会受到所有者密码和权限策略的保护。

例如,按照上述设置,用户可以打开 PDF、填写表单,也可以进行低分辨率打印,但其他未开放的操作会受到限制。

在加密算法方面,AES_256 通常比 RC4_128 更适合对安全性要求较高的场景。如果需要兼顾安全性和旧版软件的兼容性,也可以根据实际环境考虑 AES_128 等算法。

需要注意,PDF 阅读器对权限限制的执行情况可能有所不同。对于特别敏感的文档,不应仅依赖 PDF 权限设置来防止内容被复制或传播。

先检测再加密:避免重复处理

在批量处理 PDF 文件时,文件夹中可能同时存在已加密和未加密的文档。如果不做判断就直接执行加密操作,可能造成不必要的处理或引发异常。

Spire.PDF 提供了 IsPasswordProtected 静态方法,可以根据文件路径判断 PDF 是否受到密码保护。

from spire.pdf import *

inputFile = "CheckPasswordProtection.pdf"

# 判断 PDF 是否受密码保护
isProtected = PdfDocument.IsPasswordProtected(inputFile)

if isProtected:
    print("该 PDF 已加密,无需重复处理。")
else:
    print("该 PDF 未加密,可以进行加密。")

PdfDocument.IsPasswordProtected() 返回布尔值,可以通过 if 语句判断文件的加密状态。

在批量处理任务中,可以先执行这一步检测,再根据结果决定是否加密文档。这样能够避免对已经受密码保护的文件重复处理,也便于筛选出需要加密的 PDF。

解密 PDF:移除密码保护

除了加密,实际工作中也可能需要解除 PDF 的密码保护。例如,合同归档后需要进行二次处理,或者文档需要在内部系统中统一转换格式。

解密前,需要提供能够访问文档的有效密码。下面的示例使用所有者密码 test 加载已加密的 PDF,然后调用 Decrypt() 移除加密保护。

from spire.pdf import *

inputFile = "CheckPasswordProtection.pdf"
outputFile = "Decryption.pdf"

doc = PdfDocument()

# 使用密码加载已加密的 PDF
doc.LoadFromFile(inputFile, "test")

# 移除文档的加密保护
doc.Decrypt()

doc.SaveToFile(outputFile)
doc.Close()

这里通过 LoadFromFile(inputFile, "test") 使用密码加载文档。成功加载后,调用 doc.Decrypt() 移除加密保护,再通过 SaveToFile() 将解密后的文件保存到指定位置。

需要注意,解密操作应在拥有相应权限的前提下进行。与加密一样,解密后的结果也需要保存到文件中才会生效。建议另存为新文件,避免覆盖原始文档。

实用技巧与注意事项

使用 Python 加密 PDF 时,还需要注意以下几点:

  • 根据安全需求设置密码。 如果需要限制未经授权的人员打开文档,应设置非空用户密码;如果只想限制打开后的操作,可以留空用户密码,只设置所有者密码。两种密码最好分别设置,并妥善保管。
  • 空用户密码不代表没有加密。 即使用户无需输入密码就能打开文档,只要设置了所有者密码和文档权限,PDF 仍然可以处于加密状态。
  • 合理设置文档权限。 除了示例中使用的 AllowPrint、AllowFillFormFields 和 AllowDegradedPrinting,还可以根据需求设置复制内容、修改文档等权限。具体可用属性应以当前 Spire.PDF 版本的 API 文档为准。
  • 留意免费版限制。 Spire.PDF 免费版对单个文档的处理页数和功能存在一定限制。处理较长的 PDF 前,建议先确认当前版本的许可范围。
  • 加密前备份原始文件。 加密和解密都会改变文档的安全设置。建议将处理结果另存为新文件,以便后续检查、审计或重新处理。
  • 批量处理前先检查文件状态。 可以将密码保护检测放在批量处理流程的前面,只对符合条件的文件执行加密操作。

总结

使用 Spire.PDF for Python 可以根据文档的安全需求灵活设置密码和访问权限。如果需要防止未经授权的人员打开 PDF,可以设置用户密码;如果希望文档能够直接打开,但限制打印、复制或修改等操作,则可以只设置所有者密码并配置相应权限。此外,在批量处理文件时,还可以先检查文档是否已经加密,再决定是否执行加密操作;对于需要解除保护的文件,也可以在提供有效密码后进行解密。将这些操作结合起来,就能更方便地在 PDF 自动化处理流程中完成文档加密、权限管理和解密。