Skip to content

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 19:57
· 160 commits to main since this release

Added

  • Signature verification, read-only. PdfDocument.GetSignatures() lists signature fields and document time-stamps with signer name, reason, location, contact, /M, sub-filter, /ByteRange, the CMS bytes, the /DocMDP certification level and the field lock; PdfFormField.GetSignature() returns one field's signature. PdfSignature.Verify and PdfDocument.VerifySignatures check, with the platform's hashes, RSA (PKCS#1 v1.5 and PSS) and ECDSA and its X.509 chain builder (no System.Security.Cryptography.Pkcs):
    • the byte range (starts at 0, leaves out exactly /Contents, no gaps or overlaps, ends at a revision boundary) and which revision it covers;
    • the digest, the signed attributes and the signature, for adbe.pkcs7.detached, ETSI.CAdES.detached (with the signing-certificate attribute), ETSI.RFC3161 document time-stamps, and the legacy adbe.pkcs7.sha1 (flagged weak); adbe.x509.rsa_sha1 is reported as unsupported and weak;
    • an RFC 3161 signature time-stamp, itself verified, and the certificate chain against TrustAnchors (or, if asked, the system store) at a validation time chosen from the time-stamp, the signing time or now, or given explicitly;
    • revocation, which is never fetched: reported as not checked unless a RevocationCheck callback answers from data the caller holds;
    • changes after signing, object by object and classified (form field value, new signature, annotation, page content, validation data, other) against the DocMDP level and FieldMDP locks.
      The result (PdfSignatureVerification) keeps every check separate; IsValid is a convenience. See docs/signatures.md.
  • A signature fuzz target (ASN.1/CMS parsing, certificates, chain building, byte ranges and change analysis; also time-stamp responses).
  • Signing. PdfDocument.Sign writes an incremental update holding an approval or certification signature (PdfCertificationLevel 1 to 3, an optional field /Lock), and PdfDocument.AddDocumentTimestamp adds an ETSI.RFC3161 document time-stamp; both need a document opened with AllowEditing, keep the original bytes as an exact prefix and keep encryption (the /Contents string is never encrypted, ISO 32000-2 7.6.2).
    • Formats: PAdES baseline B-B (ETSI.CAdES.detached with contentType, messageDigest and signingCertificateV2, no signingTime, and the ESIC extensions entry for pre-2.0 files), B-T when PdfSigningOptions.Timestamp is set, or adbe.pkcs7.detached. Digests SHA-256, SHA-384, SHA-512; RSA PKCS#1 or PSS, and ECDSA.
    • Keys: PdfSigningCredential.FromCertificate (a certificate with a private key) or FromExternalSigner, a callback that receives the digest of the signed attributes and returns the signature value, for HSMs and remote signing. Every signature value is checked with the certificate's public key before it is embedded.
    • Time-stamps only through a PdfTimestampCallback that receives the RFC 3161 request and returns a response or token; OnePDF opens no connection. The token's status, imprint and nonce are checked before it is embedded.
    • Visible signatures get an appearance built with the content builder (name, date, reason, location, optional image). Failures throw PdfSigningException with a PdfSigningError reason and write nothing. Our own DER writer builds the CMS; no System.Security.Cryptography.Pkcs.
    • PdfSigningResult reports the reserved and used /Contents size. See docs/signatures.md.

Fixed

  • Signature verification checked too little in several attack cases found by crafting the published PDF signature attacks (see docs/signatures.md, "Known attacks"):
    • Data appended after the last %%EOF (objects with no cross-reference section, or a bare trailer) is now an unsigned change; before, a file whose signature covered its last revision still counted as the whole document.
    • An update whose trailer points /Root at a different catalog is a disallowed change.
    • The certification level is read from the signed revision, not from the newest dictionary.
    • An indirect /ByteRange or /Contents is refused.
    • A signer certificate whose key usage lacks digitalSignature/nonRepudiation, or whose extended key usage is only for other purposes, now fails IsValid (PdfSignatureVerification.KeyUsage; PdfSignatureVerifyOptions.RequireSigningKeyUsage = false allows it). A time-stamp signed by a certificate without the time-stamping purpose is invalid.
  • Signature verification no longer throws on a damaged embedded certificate on macOS, where the platform accepts certificate bytes and fails only when a property is read. Every certificate from the file, the extra certificates and the trust anchors is read once on load; one that fails is left out with a warning (the signer then counts as missing). Signing checks the credential's certificates the same way and reports PdfSigningException instead of a platform exception.