Using a signer

A signing request flows through four layers: client → companion → signer → companion → client. Each step has a clear job and explicit limits.

Step 1 — Client builds the event

The client (a Nostr app, a CLI, a service) builds an event template (kind, content, tags, created_at) and asks for a signature. It never sees the key.

Step 2 — Companion normalizes & routes

The companion:

  1. Validates the request against signing-request-v0 + implementation limits. Oversized, malformed, or unsupported events are rejected before review, signing, or transport.
  2. Normalizes the request to v0 canonical form.
  3. Routes it to the active signer over the right transport: QR (nsealr1), USB serial, smartcard APDU, or NIP-46 bridge.
$ nsealr request --kind 1 --content "hello" > req.json
$ nsealr route --request req.json --signer raspberry-qr

Step 3 — Signer reviews and approves

Where hardware allows, the signer:

  1. Renders the canonical material on a trusted display (the universal event review contract).
  2. Binds the local approval gesture (button press, on-card acknowledgement) to that material through approval_digest. Drift between “what was shown” and “what gets signed” fails closed.
  3. Signs BIP-340 / secp256k1 only after physical approval.

For display-less custody (smartcard), an external review acknowledgement must precede the APDU.

Step 4 — Companion verifies, returns

Every signed response goes through signed-response-verification-v0 before reaching the client:

  • BIP-340 signature math against the canonical bytes.
  • Event id matches the signed payload.
  • approval_digest matches the request the user approved.
$ nsealr verify --request req.json --response resp.json
 event id matches BIP-340 signature
 approval_digest matches reviewed material

If verification fails, the response is rejected even if the signature is mathematically valid.

Where each piece lives

  • The private key lives on the signer (RAM-only for QR vaults, persistent for USB / smartcard / custom HW).
  • The companion holds no secrets and is replaceable.
  • The client never sees keys.
  • The policy is owned by the signer; the companion proposes.

See Transports for the wire-level details and Trust boundaries for what each layer is — and is not — trusted with.

Last updated 2026-05-16