|
2 | 2 |
|
3 | 3 | A lightweight, modern PDF signing utility written in Rust. It creates an Adobe-compatible detached OpenPGP (GPG) signature and appends it to the PDF, making it easy to sign and verify documents without dragging in heavyweight PDF signing stacks. |
4 | 4 |
|
| 5 | +In practical security terms: many “enterprise PDF signing” solutions pull in a full **CMS/PKCS#7** / **X.509 PKI** toolchain (certificate chains, policy constraints, CRL/OCSP revocation logic, time-stamping/TSAs) plus PDF-form and incremental-update machinery to produce standards like **PAdES**. Those stacks are powerful, but they’re also complex to configure, audit, and automate. |
| 6 | + |
| 7 | +`pdf-sign` intentionally stays on the minimalist end of that spectrum: it produces a detached OpenPGP signature over the PDF bytes and appends it, while delegating all private-key operations to `gpg-agent`. |
| 8 | + |
5 | 9 | It’s designed to be a practical alternative to “traditional” PDF signing workflows: minimal setup, scriptable CLI, and it delegates cryptography to your existing `gpg-agent` (including smartcards/YubiKey). |
6 | 10 |
|
7 | 11 | The signed output stays minimal: the original PDF content is preserved and the signature is appended, keeping the file compliant so it still opens normally in standard PDF viewers. |
8 | 12 |
|
9 | 13 | ## Features |
10 | 14 |
|
11 | 15 | * **Simple CLI**: `sign` and `verify` commands that compose well in pipelines. |
12 | | -* **Works with your existing GPG setup**: Uses `gpg-agent` and your keyring (respects `GNUPGHOME`). |
| 16 | +* **Works with your existing GPG setup**: Uses `gpg-agent` (smartcards/YubiKey supported) and reads your local keybox (`pubring.kbx`) for public key lookups. |
13 | 17 | * **Hardware-friendly**: Private keys can stay on a smartcard/YubiKey. |
14 | 18 | * **Lightweight distribution**: Single-file script you can run directly (see Quickstart). |
15 | 19 |
|
16 | 20 | ## Security model |
17 | 21 |
|
18 | 22 | * **No private keys in the tool**: All signing operations are performed by `gpg-agent`. |
19 | 23 | * **Reduced key exposure**: Private keys never need to be loaded into this process. |
20 | | -* **Explicit verification**: Verifies the appended signature against a provided certificate. |
| 24 | +* **Explicit verification**: Verifies using your local keybox by default (no `gpg` subprocess), or a provided certificate via `--cert`. |
| 25 | +* **Privacy by default**: Signer UIDs (name/email) are not embedded in the signature unless enabled. |
21 | 26 |
|
22 | 27 | ## Quickstart |
23 | 28 |
|
@@ -60,25 +65,34 @@ chmod +x pdf-sign.rs |
60 | 65 |
|
61 | 66 | ### Sign |
62 | 67 |
|
63 | | -Signs a PDF. Requires a key specification (File, Key ID, Fingerprint, or Email). |
| 68 | +Signs a PDF. Requires a key specification (File path, Key ID, Fingerprint, or Email). |
| 69 | + |
| 70 | +If the input PDF already has appended OpenPGP signatures, `sign` preserves them and appends an additional signature (multi-signer workflow). |
64 | 71 |
|
65 | 72 | ```bash |
66 | 73 | ./pdf-sign.rs sign contract.pdf --key 0xF1171FAAAA237211 |
67 | 74 | ``` |
68 | 75 |
|
69 | 76 | * **--output, -o**: Specify output path (Default: `input_signed.pdf`). |
70 | | -* **--key**: Key identifier. If a file path is not found, it queries `gpg --export`. |
| 77 | +* **--key**: Key spec. If a file path is not found, it falls back to your local keybox (`pubring.kbx`). |
| 78 | +* **--embed-uid**: Embed the signer UID into the OpenPGP signature as notation (adds identity metadata). |
| 79 | +* **--json**: Output a single JSON object to stdout (useful for scripting). |
71 | 80 |
|
72 | 81 | ### Verify |
73 | 82 |
|
74 | | -Verifies the appended signature against a provided public certificate. |
| 83 | +Verifies the appended signature. If `--cert` is omitted, it will look up the signer key in your local keybox (`pubring.kbx`). |
| 84 | + |
| 85 | +If multiple signatures are appended, `verify` checks **all** of them and prints each signer’s details. |
75 | 86 |
|
76 | 87 | ```bash |
77 | | -./pdf-sign.rs verify contract_signed.pdf --cert signing-key.asc |
| 88 | +./pdf-sign.rs verify contract_signed.pdf |
78 | 89 | ``` |
79 | 90 |
|
| 91 | +* **--cert, -c**: Optional. Can be provided multiple times. Public certificate file path, fingerprint, key ID, or email. |
| 92 | +* **--json**: Output a single JSON object to stdout (useful for scripting). |
| 93 | + |
80 | 94 | ## Environment |
81 | 95 |
|
82 | | -* `GNUPGHOME`: Respected for keyring lookups. |
| 96 | +* `GNUPGHOME`: Respected for keybox lookups (defaults to `~/.gnupg`). |
83 | 97 | * `stderr`: Used for all progress, status, and error reporting. |
84 | 98 | * `stdout`: Outputs the resulting file path (signing) or "OK" (verification) for pipeline composition. |
0 commit comments