Python给PDF添加可见与隐藏数字签名实战教程
在处理合同、发票或报告时,数字签名能验证文档的完整性与签署人身份。相比手动在Acrobat里逐份签署,用Python批量处理更适合自动化流程。本文基于Spire.PDF for Python,详细介绍如何为PDF添加可见签名、隐藏签名、带时间戳的签名,以及验证签名有效性。环境准备
首先安装依赖库:
pip install Spire.Pdf
还需要一个数字证书文件(.pfx或.p12格式)及对应的密码。测试阶段可使用自签名证书(如通过OpenSSL生成),生产环境应由CA签发。
添加可见的数字签名
可见签名会在PDF页面上绘制一个签名框,显示签署人、原因、位置等信息。核心是PdfOrdinarySignatureMaker对象,它负责加载证书并执行签署运算;签名外观通过PdfSignatureAppearance单独配置。
from spire.pdf import *
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
signatureMaker.MakeSignature("Signer:", doc.Pages.get_Item(0), 90.0, 550.0, 270.0, 90.0, appearance)
doc.SaveToFile("DigitalSignature.pdf")
doc.Dispose()
关键点:
- Name、Reason、Location等信息写入签名对象,PDF阅读器可读取。
- GraphicMode设置签名框显示内容:SignImageAndSignDetail同时显示Logo和文字,也可只选图片或文字。
- MakeSignature坐标参数以点(point)为单位,原点在页面左下角(左下为(0,0)),四个数值依次为左边界、下边界、宽度、高度。
添加隐藏签名
若只需在文档层面完成完整性校验而不显示可见框,可创建不带外观的隐藏签名。同样使用PdfOrdinarySignatureMaker,只传签名字段名称即可。
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()
隐藏签名仍具备防篡改能力,PDF阅读器可在签名面板中检测到它,但页面无任何显示。
添加带时间戳的签名
数字证书有有效期,若需证明签署发生在证书有效期内,需引入可信时间戳服务(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属性以证书化签名方式限定签署后允许的操作。示例组合表示“允许继续填写表单字段,但禁止其他改动”,适合审批后仍需收集信息且防止篡改的表单类文档。
验证已签名的文档
遍历PDF表单中的签名字段,调用VerifySignature方法检查文档完整性。
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会重新计算文档摘要并与签名中的记录比对:若文档被修改,返回无效。
实用建议
- 证书密码不要硬编码:应通过环境变量或密钥管理服务读取。
- 坐标系统:签名框原点在页面左下角,y轴向上为正,与屏幕坐标相反,注意换算。
- 签名顺序:多签名时后续签名会包含先前签名内容,影响验证逻辑。
- 及时释放资源:处理完后调用Dispose(),避免批量任务文件句柄占用。
以上即为Python自动化添加PDF数字签名的完整实现。基于此,可进一步结合表单字段、长期验证(LTV)等构建合同管理、审批流转的自动签署方案。
Re: Python给PDF添加可见与隐藏数字签名实战教程
很实用的教程,最近刚好在找给PDF批量签名的方案。请问自签名证书和CA签发的证书在功能上有哪些区别?除了信任问题外,在代码层面是否需要做不同处理?Re: Python给PDF添加可见与隐藏数字签名实战教程
好实用的教程!Spire.PDF 这个库的可见/隐藏签名、时间戳绑定这些功能都讲得很清楚,坐标原点在左下角这个细节很多人会踩坑,楼主特意标出来太贴心了。要是能补充一下自签名证书用 OpenSSL 生成的具体命令就更完美了,感谢分享!Re: Python给PDF添加可见与隐藏数字签名实战教程
谢谢分享,这篇教程非常实用,把可见签名、隐藏签名和带时间戳的签名的完整流程都讲清楚了,尤其是坐标原点在左下角这个细节,新手很容易忽略。想问下自签名证书用 OpenSSL 生成时,有没有推荐的参数设置,避免在验证时被识别为“不受信任”?另外,文中的时间戳服务 `freetsa.org` 是免费的吧,长期生产环境是否建议用固定的商业 TSA?
页:
[1]