v0.0.2 - Add random mnemonic startup flow and multi-instance random socket naming
This commit is contained in:
66
README.md
66
README.md
@@ -70,13 +70,15 @@ This reduces deployment variability and shrinks the runtime trust surface.
|
||||
|
||||
When started, `n_signer` immediately enters terminal input mode:
|
||||
|
||||
1. Prompt for mnemonic (terminal echo disabled).
|
||||
2. Parse and validate mnemonic.
|
||||
3. Build in-memory role/selector state.
|
||||
4. Initialize transport endpoints.
|
||||
5. Switch to running status display.
|
||||
1. Choose mnemonic source: `[E]nter existing mnemonic` (default) or `[G]enerate new mnemonic`.
|
||||
- On `E`: prompt for mnemonic with terminal echo disabled, then validate.
|
||||
- On `G`: generate a fresh 12-word BIP-39 mnemonic from `getrandom(2)`, display it numbered with a "WRITE THIS DOWN — IT WILL NOT BE SHOWN AGAIN" warning, then continue. There is no confirmation step.
|
||||
2. Build in-memory role/selector state from the mnemonic.
|
||||
3. Pick the abstract socket name (random BIP-39 pair, or `--socket-name` override).
|
||||
4. Initialize transport endpoints and bind the socket.
|
||||
5. Switch to running status display, with the signer name and socket address shown in the banner.
|
||||
|
||||
No startup files are read or written.
|
||||
No startup files are read or written. The mnemonic — typed or generated — lives only in `mlock`'d memory and is zeroized on shutdown or crash.
|
||||
|
||||
### 3.2 Running phase (status display + signer)
|
||||
|
||||
@@ -207,7 +209,9 @@ This prevents cross-protocol misuse inside one mnemonic-rooted signer process.
|
||||
|
||||
### 7.1 Linux desktop: abstract namespace Unix socket
|
||||
|
||||
Primary local transport is AF_UNIX abstract namespace (for example `@nsigner`).
|
||||
Primary local transport is AF_UNIX abstract namespace.
|
||||
|
||||
Each running `nsigner` process binds to a unique abstract name of the form `@nsigner_<word1>_<word2>`, where the two words are picked at random from the BIP-39 English wordlist at startup (e.g. `@nsigner_hairy_dog`). This lets multiple signers coexist on one host.
|
||||
|
||||
Properties:
|
||||
|
||||
@@ -215,6 +219,17 @@ Properties:
|
||||
- endpoint lifetime bound to process/kernel namespace
|
||||
- no stale socket files
|
||||
- caller identity via peer credentials (`SO_PEERCRED`)
|
||||
- per-launch random name avoids collisions between concurrent instances and leaks no seed-derived identifier
|
||||
|
||||
Naming rules:
|
||||
|
||||
- Default: random pick at startup, displayed in the TUI banner.
|
||||
- Override: `--socket-name <name>` forces a specific name (useful for scripts and tests).
|
||||
- Collision: if the chosen random name is already bound by another process, `nsigner` retries with a fresh pair up to 8 times before erroring out with a hint to use `--socket-name`.
|
||||
|
||||
Discovery:
|
||||
|
||||
- `nsigner list` enumerates currently bound `nsigner_*` abstract sockets by reading `/proc/net/unix`.
|
||||
|
||||
### 7.2 ESP32 MCU: USB-CDC serial
|
||||
|
||||
@@ -258,23 +273,44 @@ Qubes deployment runs `n_signer` in a dedicated signer qube as a foreground proc
|
||||
nsigner
|
||||
```
|
||||
|
||||
Program starts in attached foreground mode and prompts for mnemonic.
|
||||
Program starts in attached foreground mode and prompts for mnemonic. After mnemonic acceptance, the TUI banner shows the randomly assigned signer name and its abstract socket address.
|
||||
|
||||
To force a specific socket name (e.g. for scripted clients):
|
||||
|
||||
```bash
|
||||
nsigner --socket-name my_test_signer
|
||||
```
|
||||
|
||||
### 9.2 Send a request (client mode)
|
||||
|
||||
From another terminal:
|
||||
From another terminal, target the signer by its socket name:
|
||||
|
||||
```bash
|
||||
nsigner client '{"id":"1","method":"get_public_key","params":[]}'
|
||||
nsigner client --socket-name nsigner_hairy_dog '{"id":"1","method":"get_public_key","params":[]}'
|
||||
```
|
||||
|
||||
If only one signer is running you can omit the override and the client will use the default discovery rule.
|
||||
|
||||
Example signing request:
|
||||
|
||||
```bash
|
||||
nsigner client '{"id":"2","method":"sign_event","params":["<event_json>",{"role":"main"}]}'
|
||||
nsigner client --socket-name nsigner_hairy_dog '{"id":"2","method":"sign_event","params":["<event_json>",{"role":"main"}]}'
|
||||
```
|
||||
|
||||
### 9.3 Example session
|
||||
### 9.3 List running signers
|
||||
|
||||
```bash
|
||||
nsigner list
|
||||
```
|
||||
|
||||
Prints the abstract socket names of any currently running `nsigner` instances, e.g.:
|
||||
|
||||
```text
|
||||
@nsigner_hairy_dog
|
||||
@nsigner_brave_canyon
|
||||
```
|
||||
|
||||
### 9.4 Example session
|
||||
|
||||
Terminal A:
|
||||
|
||||
@@ -282,14 +318,16 @@ Terminal A:
|
||||
$ nsigner
|
||||
[unlock] enter mnemonic:
|
||||
[ok] session unlocked
|
||||
[listen] unix-abstract:@nsigner
|
||||
signer name : hairy dog
|
||||
socket : @nsigner_hairy_dog
|
||||
[listen] unix-abstract:@nsigner_hairy_dog
|
||||
[prompt] caller=uid:1000 method=sign_event role=main -> allow? (y/n)
|
||||
```
|
||||
|
||||
Terminal B:
|
||||
|
||||
```text
|
||||
$ nsigner client '{"id":"2","method":"sign_event","params":["<event_json>",{"role":"main"}]}'
|
||||
$ nsigner client --socket-name nsigner_hairy_dog '{"id":"2","method":"sign_event","params":["<event_json>",{"role":"main"}]}'
|
||||
{"id":"2","result":"<signed_event_json>"}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user