跳到主要内容
ecdsa.com

PDF 签名验证工具

大多数在线 PDF 签名检测工具都要求把文档传到它们的服务器上。这个工具在你的浏览器中读取文档:已签名的字节范围、CMS 签名、签名者的证书链、内嵌的时间戳和长期验证数据都在你的设备上验证,PDF 不会离开你的设备。

你的 PDF 在此浏览器标签页中读取和验证。它不会被上传,页面发出的任何请求都不会携带它。

已签名的 PDF

将文件拖放到此处,或

不限大小;大文件会在后台检查,页面不会卡住。

信任锚(可选)

只有当签名者的证书链能追溯到你信任的根证书时,签名才能证明是谁签的名。Adobe Acrobat 使用 Adobe Approved Trust List 和欧盟可信列表;在这里,你需要自己添加根证书——你所在组织的 CA,或合格信任服务的根证书。只能粘贴证书;私钥会被拒绝。

在下一次检查时生效

示例

测试文档来自本站的测试套件(tools/pdf-signature-verifier/fixtures)。PDF 由测试套件的生成器脚本编写;签名、RFC 3161 时间戳令牌、OCSP 响应和 CRL 由 OpenSSL 3.6.5 基于一套测试 PKI 生成,该 PKI 的根证书为“ecdsa.com Test Root CA”。需要该根证书的示例会把它加载为信任锚。

Your PDF never leaves the browser

Online PDF signature checkers usually ask you to upload the document, which is a strange request for a contract, an invoice or a medical report. This verifier is a page that does the work itself. The file you drop is read with the browser's File API and handed to a Web Worker of this page, a background thread inside the same tab. The PDF parser, the CMS and X.509 code and every hash run there. There is no upload endpoint to send the file to: the page makes no request carrying it, and once the page has loaded the check works offline. The SHA-256 shown under Document is computed in that worker too, so you can match it against the file you meant to check.

Three separate questions

A PDF signature is a CMS (PKCS #7, RFC 5652) signature stored in the /Contents entry of a signature dictionary (ISO 32000-2, §12.8). Its /ByteRange lists the bytes it covers: the whole file as it was at signing time, except the hole that holds /Contents itself. A verdict answers three questions, and the verifier reports each one:

  • Integrity. Do the signed bytes still hash to the digest in the signature, and does the signature over the signed attributes verify with the signer's public key? RSA PKCS #1 v1.5 and PSS, ECDSA on the NIST and Brainpool curves, Ed25519 and Ed448 are checked.
  • Coverage. Is the gap in /ByteRange exactly the /Contents value, and does the signed range end where a PDF revision ends? The bar under each signature shows the signed bytes, the signature value and what the signature does not cover.
  • Trust. Does the signer's certificate chain to a root that you trust? The chain is built from the certificates in the signature and in the document's validation data, then checked for signatures, validity at the signing time, CA flags, key usage and path length.

"Valid but not trusted"

Acrobat's yellow question mark usually means the first two answers are yes and the third is unknown: the bytes are intact, but the signer's root is not in the reader's trust list. Readers ship their own lists — the Adobe Approved Trust List and the EU Trusted Lists of qualified trust services under eIDAS. This page ships none, so a correct signature from an unknown CA is reported as intact, but not trusted rather than as valid. Paste the root you rely on under Trust anchors — your company CA, or the root certificate of a qualified trust service provider — and the same signature becomes valid when its chain reaches it. Whether a signature is a qualified electronic signature in the eIDAS sense is a legal status that also depends on the trusted list at signing time; the verifier does not decide it.

Changes after signing

Signing appends an incremental update instead of rewriting the file, and later updates can follow: another signature, form data, comments, validation data. The verifier lists every object written after each signature and compares it with the version the signature covered. New annotations, signature fields and a Document Security Store are expected; a replaced page content stream, font or image is flagged because it changes what the document shows. A certifying signature with DocMDP level 1 forbids any change, and a later change is reported as a failure. Bytes after the last %%EOF that are not a PDF revision are reported as uncovered data.

PAdES, time-stamps and LTV

PAdES (ETSI EN 319 142-1) profiles PDF signatures in levels. B-B requires the signing-certificate attribute that binds the signer's certificate into the signed data; the verifier checks that it is present and matches. B-T adds an RFC 3161 time-stamp over the signature value, which proves the signature existed at that time (RFC 3161); the token's imprint, its TSA signature and the TSA certificate rules are verified, and the chain is evaluated at the time-stamped time rather than at the signer's own claim in /M. B-LT embeds validation data — certificates, OCSP responses and CRLs — in the Document Security Store, so the signature can be checked after the CA is gone: each OCSP response and CRL is decoded, its signature verified and matched against the certificates of the chain. B-LTA adds a document time-stamp (ETSI.RFC3161) over everything before it; the verifier checks those like any other signature.

Legacy sub-filters are still read: adbe.pkcs7.sha1, which signs a SHA-1 digest of the byte ranges, and adbe.x509.rsa_sha1, a bare RSA signature. Both are reported with a weak-hash warning.

What it does not do

  • It does not fetch anything: OCSP responders and CRL distribution points are not queried, so revocation is judged from the data embedded in the document only.
  • It does not render pages or compare signature appearances; a visible signature image proves nothing on its own.
  • It does not decide qualified status or apply a national trust list; you choose the trust anchors.

For the full background — how the ByteRange is laid out, what each PAdES level adds and how pyHanko and OpenSSL check the same files — read PDF signatures explained. An embedded time-stamp token can be taken apart field by field in the time-stamp inspector, and a signer certificate in the certificate decoder.