Files
n_signer/client/README.md

5.9 KiB

n_signer C Client — migrated to nostr_core_lib

The hand-rolled nsigner_client.{c,h} that previously lived in this directory has been removed. n_signer now uses the shared, transport-pluggable client stack that lives in nostr_core_lib:

This is the single source of truth for the n_signer wire contract. See nostr_core/NSIGNER_INTEGRATION.md for the full integration contract.

What moved where

Old (client/) New (nostr_core_lib)
nsigner_client_t (stack) nsigner_client_t* (heap) or nostr_signer_t*
nsigner_client_init / connect_unix / close nsigner_transport_open_unix + nsigner_client_new / nsigner_client_free
nsigner_client_get_public_key nostr_signer_get_public_key or nsigner_client_call(..., "nostr_get_public_key", ...)
nsigner_client_sign_event nostr_signer_sign_event or nsigner_client_call(..., "nostr_sign_event", ...)
nsigner_client_set_auth nsigner_client_set_auth or nostr_signer_nsigner_set_auth
nsigner_client_request / request_raw nsigner_client_call (returns parsed cJSON result)

Consumers (updated)

The nsigner ... client '<json>' subcommand in src/main.c is unaffected — it has its own raw framing pass-through and never used this directory.

Multi-Algorithm and Post-Quantum Verbs

n_signer supports six algorithms: secp256k1 (Nostr), ed25519 (SSH), x25519 (age/ECDH), ml-dsa-65 (PQ signatures, FIPS 204), slh-dsa-128s (PQ hash-based signatures, FIPS 205), and ml-kem-768 (PQ KEM, FIPS 203).

The API has two verb families (see README.md §4 for the full spec):

Algorithm-based verbs — the caller specifies algorithm and index in the options object. No role table entry is needed.

Verb Algorithms Description
get_public_key all key-deriving algorithms Returns the derived public key (structured)
sign secp256k1, ed25519, ml-dsa-65, slh-dsa-128s Sign arbitrary bytes (hex)
verify secp256k1, ed25519, ml-dsa-65, slh-dsa-128s Verify a signature
encapsulate ml-kem-768 KEM encapsulation with peer's public key
decapsulate ml-kem-768 KEM decapsulation with derived private key
derive_shared_secret x25519 ECDH key agreement
derive secp256k1 HMAC-SHA256(privkey, data) — key-derived MAC for opaque identifiers (index required)
encrypt / decrypt otp One-time pad encrypt/decrypt (algorithm:"otp")

Nostr protocol verbs — select a secp256k1 NIP-06 key via nostr_index (or role/role_path). These are role-based.

Verb Description
nostr_get_public_key Returns the role's secp256k1 public key
nostr_sign_event Sign a Nostr event
nostr_mine_event NIP-13 PoW mining + sign
nostr_nip44_encrypt / nostr_nip44_decrypt NIP-44 encrypt/decrypt
nostr_nip04_encrypt / nostr_nip04_decrypt NIP-04 encrypt/decrypt

Example: nsigner_client_call(client, "sign", "[\"68656c6c6f\",{\"algorithm\":\"ed25519\",\"index\":0}]", &result)

For secp256k1, the optional scheme parameter selects "schnorr" (default) or "ecdsa".

get_public_key response format

The algorithm-based get_public_key always returns a structured JSON string: {"algorithm":"<alg>","public_key":"<hex>","key_id":"<16 hex>"}.

The role-based nostr_get_public_key returns a plain 64-hex-char secp256k1 public key by default, or the structured form with {"format":"structured"}.

Clients should parse the result string with cJSON_Parse to extract the algorithm, public_key, and key_id fields when the result is a JSON object.

Key sizes

Algorithm Pub key Priv key Signature Ciphertext Shared secret
secp256k1 32 B 32 B 64 B
ed25519 32 B 32 B 64 B
x25519 32 B 32 B 32 B
ML-DSA-65 1952 B 4032 B 3309 B
SLH-DSA-128s 32 B 64 B 7856 B
ML-KEM-768 1184 B 2400 B 1088 B 32 B

Example clients

See documents/CLIENT_IMPLEMENTATION.md section 11 for the full multi-algorithm specification, derivation paths, and example request/response transcripts.

Why

Per plans/nsigner_integration_plan.md (Phase 7): retire per-project hand-rolled clients in favor of the shared module in nostr_core_lib, so the wire contract has one implementation and downstream projects get unix/tcp/serial/fds transports for free.