Skip to content

feat: sign what you write, with your signature, signature blocks and your own certificate - #122

Merged
FPurchess merged 25 commits into
mainfrom
feat/signing
Oct 13, 2026
Merged

FPurchess merged 25 commits into
mainfrom
feat/signing

Conversation

@FPurchess

@FPurchess FPurchess commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Sign what you write in Blank, visibly and with your own certificate. This is the first of three stacked PRs for signing; the PDF tabs (#123) and signing received PDFs (#124) build on it.

What users get

  • Your signature and initials (Settings ▸ Signing, or the commands "Your signature…" / "Your initials…"):
    • Draw them, type them in one of four script fonts (Pinyon Script, Ms Madi, Dancing Script, Caveat), or use a picture, whose background is removed.
    • They're kept in <app config>/signing/.
  • Signature blocks: a new Signing group in the blocks pane.
    • Each block is one signer, with a line, "Name · Role", and "Place, date".
    • Its settings (Role, Name, Place, Date, Width) are in its popover.
    • The block is saved as <!-- blank:signature@1 … -->, and makes the round trip through Word. A Word signature line becomes a block on import.
  • Export signed PDF…:
    • The save dialog comes first, then the Sign dialog: Sign as, the block to sign, initials on every page, place, reason and the passphrase.
    • The PDF stays PDF/A-2u. "No digital signature" writes only the visible signature.
  • Digital signatures:
    • Create a P-256 certificate (rcgen), or import a .p12. You can back up the key and export the certificate.
    • Signing is PAdES: CMS ETSI.CAdES.detached, signed as an incremental update with lopdf.
    • An RFC 3161 timestamp server is optional. When it fails, Blank offers to sign without it.
    • Trusted certificates are kept by their fingerprint.

How it works

  • Engine: Content::Stamp lays out the block. The engine also reports the boxes of the blocks, so the signer knows where they sit. The wasm is rebuilt.
  • Signer (src-tauri/src/signing/): the key, the CMS and the timestamp stay native, and the passphrase crosses IPC once per signing. The signer never rewrites earlier bytes.
  • Rules and docs: .claude/rules/signing.md and docs/guide/signing.md, plus the blocks, settings, configuration and shortcuts pages.

Checked by hand

  • Acrobat Reader: "validity unknown", then valid after adding the certificate to Trusted Identities
  • LibreOffice and Okular list the signature, and EU DSS reports B-B / B-T

… points elsewhere an object it signed, even beside validation data
…sked, keep the old key when saving a new one fails, cap timestamp answers as they arrive, and name the certificate's holder as the signer
…data, and look up a revision's objects by number once
…ked, and count the trailer's /Info among the rest
…ir own, with widths, alignment and captions for pictures
…ent's rendered diagrams, align captions as their pictures, and read picture widths only from Blank's Word files
# Conflicts:
#	.claude/rules/content-blocks.md
#	.claude/rules/state.md
#	CLAUDE.md
#	blank.json
#	docs/guide/blocks.md
#	docs/guide/shortcuts.md
#	public/THIRD-PARTY-NOTICES.txt
#	src-tauri/Cargo.lock
#	src/config.ts
#	src/editor/commands/contentBlocks.test.ts
#	src/editor/commands/contentBlocks.ts
#	src/editor/plugins/keymap.ts
#	src/editor/requests.ts
#	src/engine/engine.ts
#	src/engine/flatten.ts
#	src/engine/incremental.test.ts
#	src/engine/pdf.ts
#	src/engine/wasm/blank_layout_bg.wasm
#	src/exporters/docx/forms.ts
#	src/exporters/docx/index.ts
#	src/importers/docx/cleanup.ts
#	src/importers/docx/prepare.ts
#	src/markdown/schema.ts
#	src/scss/_typography.scss
#	src/scss/main.scss
#	src/state/dialogs.ts
#	src/ui/App.vue
#	src/ui/BlockTile.vue
#	src/ui/BlocksPane.test.ts
#	src/ui/TocPopover.vue
…the shared block settings, widths and picture scale, and the Word import on the shared part reading
…e, so it covers the lines under the signature too
…ir own, with widths, alignment and captions for pictures
…ent's rendered diagrams, align captions as their pictures, and read picture widths only from Blank's Word files
@FPurchess
FPurchess merged commit 9d903bf into main Oct 13, 2026
8 checks passed
@FPurchess
FPurchess deleted the feat/signing branch October 13, 2026 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant