python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python PDF数字签名

使用 Python 对 PDF 文档进行数字签名的方法

作者:用户835629078051

本文将介绍用Python为PDF添加可见签名、隐藏签名和带时间戳的签名,并对已签名文档进行验证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在合同、发票、报告等文件的流转过程中,如何确认文档确实由某个签署人发出,并且在签署之后没有被篡改,是一个经常遇到的问题。数字签名正是为此设计的机制:它基于 PKI(公钥基础设施)技术,把签署人的身份与文档内容绑定在一起,一旦文档被修改,签名的校验就会失败。

相比手动在 Adobe Acrobat 等工具里逐份签署,用程序批量处理签名更适合需要自动化的场景,例如系统自动生成的合同、每日结算单、审批通过后自动盖章的流程文件等。本文将介绍如何用 Python 为 PDF 添加可见签名、隐藏签名和带时间戳的签名,并对已签名文档进行验证。

数字签名解决的问题

用程序处理数字签名,通常出于以下几方面的考虑:

环境准备

处理 PDF 签名可以使用 Spire.PDF for Python,通过 pip 安装:

pip install Spire.Pdf

除了库本身,还需要一个用于签署的数字证书文件,通常是 .pfx(或 .p12)格式,并配有对应的密码。证书可以由 CA 机构签发,也可以在测试阶段使用自签名证书。

添加可见的数字签名

可见签名会在页面上绘制一个签名框,显示签署人、原因、位置等信息,适合需要让阅读者直观看到"已签署"状态的场景。

核心是 PdfOrdinarySignatureMaker 对象:它接收 PDF 文档、证书文件路径和证书密码,负责完成签署运算。签名的外观则通过 PdfSignatureAppearance 单独配置。

from spire.pdf import *

# 加载 PDF 文档
doc = PdfDocument()
doc.LoadFromFile("SampleB_1.pdf")

# 使用证书文件和密码创建签名生成器
signatureMaker = PdfOrdinarySignatureMaker(doc, "Jerry.pfx", "e-iceblue")

# 配置签名的元数据
signature = signatureMaker.Signature
signature.Name = "Jerry"
signature.ContactInfo = "028-12345678"
signature.Location = "Chengdu"
signature.Reason = "文档负责人签署"

# 配置签名外观
appearance = PdfSignatureAppearance(signature)
appearance.NameLabel = "签署人: "
appearance.ContactInfoLabel = "联系方式: "
appearance.LocationLabel = "地点: "
appearance.ReasonLabel = "原因: "
appearance.SignatureImage = PdfImage.FromFile("logo.png")
appearance.GraphicMode = GraphicMode.SignImageAndSignDetail

# 在第一页指定位置绘制签名框:x, y, 宽, 高
signatureMaker.MakeSignature("Signer:", doc.Pages.get_Item(0), 90.0, 550.0, 270.0, 90.0, appearance)

doc.SaveToFile("DigitalSignature.pdf")
doc.Dispose()

这里有几个关键点值得说明:

添加隐藏签名

有些场景并不希望在页面上出现签名框,只需要在文档层面完成签署以保证完整性即可。这时可以创建不带外观参数的隐藏签名。

from spire.pdf import *

doc = PdfDocument()
doc.LoadFromFile("SampleB_1.pdf")

# 创建签名生成器
signatureMaker = PdfOrdinarySignatureMaker(doc, "Jerry.pfx", "e-iceblue")

# 只传签名字段名称,不设置外观,即为隐藏签名
signatureMaker.MakeSignature("signName")

doc.SaveToFile("AddInvisibleSignature.pdf")
doc.Dispose()

隐藏签名同样具备防篡改能力,阅读器仍能在签名面板中检测到它,只是页面上不显示任何可见标记。

添加带时间戳的签名

数字证书都有有效期。如果需要证明"签署行为发生在证书仍然有效的时间点",就要引入可信时间戳服务(TSA)。Security_PdfSignature 提供了 ConfigureTimestamp 方法来指定 TSA 服务地址。

from spire.pdf import *

doc = PdfDocument()
doc.LoadFromFile("SampleB_1.pdf")

# 创建带页面引用的签名对象
signature = Security_PdfSignature(doc, doc.Pages.get_Item(0), "Jerry.pfx", "e-iceblue", "signature")

# 设置签名框的位置和大小
signature.Bounds = RectangleF(PointF(90.0, 550.0), SizeF(180.0, 90.0))
signature.NameLabel = "Digitally signed by: Jerry"
signature.Reason = "确保文档真实性"

# 限制签署后允许的操作:仅允许填写表单,禁止其他修改
signature.DocumentPermissions = PdfCertificationFlags.AllowFormFill.value | PdfCertificationFlags.ForbidChanges.value

# 配置可信时间戳服务
signature.ConfigureTimestamp("https://freetsa.org/tsr")

doc.SaveToFile("SignedByTimestamp.pdf")
doc.Dispose()

DocumentPermissions 是这里的一个实用属性,它以证书化签名的方式限定签署后允许的操作。示例中的组合表示"允许继续填写表单字段,但禁止其他任何改动",适合审批完成后仍需收集信息、又要防止内容被篡改的表单类文档。

验证已签名的文档

拿到一份签名文档后,可以遍历其表单中的签名字段,逐个校验签名是否有效。

from spire.pdf import *

doc = PdfDocument()
doc.LoadFromFile("SignedDocument.pdf")

# 访问文档表单
formWidget = PdfFormWidget(doc.Form)

if formWidget.FieldsWidget.Count > 0:
    for i in range(formWidget.FieldsWidget.Count):
        field = formWidget.FieldsWidget.get_Item(i)
        if isinstance(field, PdfField):
            signatureField = PdfSignatureFieldWidget(field)
            # 用字段全名验证对应签名
            valid = doc.VerifySignature(signatureField.FullName)
            print("签名有效" if valid else "签名无效")

doc.Dispose()

VerifySignature 会重新计算文档内容的摘要并与签名中记录的值比对:如果文档在签署之后被改动,返回结果就是无效。这一步是数字签名"防篡改"承诺的最终落地。

实用建议

总结

本文围绕 PDF 数字签名的常见需求,介绍了可见签名、隐藏签名、带时间戳签名以及签名验证四种操作。它们的核心都建立在证书文件与文档内容的绑定之上:PdfOrdinarySignatureMaker 负责普通签署,Security_PdfSignature 在此基础上补充了时间戳和权限控制,而 VerifySignature 则完成校验闭环。

在此基础上,可以进一步结合表单字段、文档权限和长期验证(LTV)等能力,构建出适合合同管理、审批流转等场景的自动化签署方案。

到此这篇关于使用 Python 对 PDF 文档进行数字签名的方法的文章就介绍到这了,更多相关Python PDF数字签名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文