PDF已签名无法编辑解去除签名编辑的解决方法-dsv4p编写

实用技术 Adobe 算法
85 编辑于
  1. 本文档内容仅用于PDF文件格式结构数字签名加密算法的底层技术研究与学习。

  2. 文中涉及的操作流程,严格限定于用户拥有完全著作权的原创文档,或已进入公有领域(Public Domain) 的无版权文件。

  3. 用户若将该技术应用于任何受版权保护、未经授权的商业文档、合同或出版物,由此产生的一切民事纠纷及刑事责任,均由实际操作者自行承担,与本文作者及发布平台无关。

  4. 请用户在阅读完毕后24小时内删除相关测试数据


  5. deepseek-v4-pro编写

这大肥鱼还是有俩下的,搜索引擎搜索一堆收钱网站还有垃圾答案,真的无语了

1数字签名不是独立文件,是挂在 PDF 对象引用链上的一串对象:

/AcroForm /Fields
    └─ 签名字段(/FT /Sig)
          └─ /V 签名值对象
                └─ /Contents  ← PKCS#7 签名数据真正在这
                └─ /ByteRange ← 签名覆盖的字节区间

2.去签名就是“断开引用”:删掉页面 /Annots 里的签名挂件

再删掉 /AcroForm /Fields 里的签名字段

删完之后,/V → /Contents 这一串签名对象就没人引用了,变成孤立对象


3.最后一步最关键:pdf.save() 不是在原文件上打补丁,让 pikepdf(底层是 qpdf)把整个 PDF 重新构建一遍

重新生成对象和交叉引用表

孤立对象不会被写进去,于是那几千字节的 PKCS#7 签名数据就物理消失了

文件会缩小几十 KB,缩掉的基本就是签名数据


外部依赖

pip install pikepdf

核心算法

Python
import pikepdf

SIG = pikepdf.Name("/Sig")
# Enfocus PitStop / QITE 等预检工具留下的非标准扩展数据
JUNK_KEYS = ("/FICL:Enfocus", "/QITE_DocInfo", "/CP2")


def has_signature(pdf):
    """判断文档里是否有签名字段。"""
    acro = pdf.Root.get("/AcroForm")
    if acro is None:
        return False
    fields = acro.get("/Fields")
    if fields is None:
        return False
    return any(f.get("/FT") == SIG for f in fields)


def strip_signatures(pdf):
    """移除签名挂件、签名字段,以及预检残留数据。"""
    root = pdf.Root

    # 1) 删除页面上的签名挂件(widget annotation,/FT = /Sig)
    for page in pdf.pages:
        if "/Annots" not in page:
            continue
        kept = pikepdf.Array()
        for annot in page.Annots:
            if annot.get("/FT") != SIG:
                kept.append(annot)
        page.Annots = kept

    # 2) 删除 AcroForm 里的签名字段;表单空了就整个移除 AcroForm
    if "/AcroForm" in root:
        acro = root.AcroForm
        if "/Fields" in acro:
            kept = pikepdf.Array()
            for field in acro.Fields:
                if field.get("/FT") != SIG:
                    kept.append(field)
            if len(kept) == 0:
                del root["/AcroForm"]
            else:
                acro.Fields = kept
                if "/SigFlags" in acro:
                    del acro["/SigFlags"]

    # 3) 清理预检工具残留
    for key in JUNK_KEYS:
        if key in root:
            del root[key]


def remove_signature(src, dst):
    pdf = pikepdf.open(src)
    try:
        if not has_signature(pdf):
            return "skip"
        strip_signatures(pdf)
        pdf.save(dst)   # 关键:重写整个 PDF
    finally:
        pdf.close()
    return "done"

本文版权遵循 CC BY-NC 协议 本站版权政策

(。>︿<。) 已经一滴回复都不剩了哦~