6.2 KiB
ZKAC CLI Guide
This guide documents the zkac-node CLI and the related zkac-node-i2p-server helper, with practical workflows for creating users, issuing credentials, and authenticating.
Install
From the repository root:
# Build/install the zkac Python extension first.
maturin develop
# Install CLI entrypoints.
pip install -e ./cli
Check installed commands:
zkac-node --help
zkac-node-i2p-server --help
Concepts
useridis your local identity name; each user is stored under~/.zkac/<userid>/.serveris always a network endpoint string inhost:portform.- Most management operations require pinning the server public key first.
- Credentials are granted directly over authenticated P2P delivery (
grant->p2p-listen).
Command Groups
user
Manage local identities.
zkac-node user create <userid>
zkac-node user list
zkac-node user show <userid> [--peer host:port]
creategenerates issuance and transport keypairs.show --peer host:portembeds your receiving endpoint into a shareable contact bundle, used by admins when granting.
serve
Run a ZKAC node server:
zkac-node serve <userid> [--data-dir DIR] [--host HOST] [--port PORT] \
[--max-connections N] [--idle-timeout SECONDS] [--listen-backlog N] \
[--allow-non-loopback]
Defaults: --host 127.0.0.1, --port 9800, data at ~/.zkac/<userid>/server/.
By default non-loopback binds are blocked unless you explicitly pass --allow-non-loopback.
server pin
Pin a server transport public key per user:
zkac-node server pin <userid> <host:port> --key <SERVER_PUBLIC_KEY_HEX>
Pins are exact string matches. If you connect with example.b32.i2p:9800, pin exactly that, not localhost:9800.
registry
Manage registries you own:
zkac-node registry create <userid> <server> --roles role1,role2
zkac-node registry update <userid> <server> --registry <REGISTRY_ID> --add-roles role3,role4
zkac-node registry get <userid> <server> --registry <REGISTRY_ID>
zkac-node registry list <userid>
zkac-node registry revoke <userid> <server> --registry <REGISTRY_ID> --role <ROLE>
zkac-node registry revoke <userid> <server> --registry <REGISTRY_ID> --all
createinitializes a registry and stores local admin metadata.updateadds new roles.revokebumps role epoch(s), invalidating credentials for that role or all roles.
grant
Grant one credential directly to a recipient:
zkac-node grant <admin_userid> --server <host:port> --registry <REGISTRY_ID> \
--role <ROLE> --to "<RECIPIENT_CONTACT_BUNDLE>"
The --to bundle must include both:
- recipient issuance key and transport key
- grant pairing token and
peerendpoint (fromuser show --peer)
p2p-listen
Receive exactly one direct grant and store it locally:
zkac-node p2p-listen <userid> [--host HOST] [--port PORT] [--timeout SECONDS] \
[--allow-non-loopback]
Default bind is 127.0.0.1:9810.
credentials list
Show locally stored credentials:
zkac-node credentials list <userid>
auth
Authenticate using a credential:
zkac-node auth <userid> --registry <REGISTRY_ID> --role <ROLE> [--server host:port]
If --server is omitted, the CLI tries to use server info from local admin metadata for that registry.
net check
Connectivity diagnostics:
zkac-node net check <host:port> [--timeout SECONDS] [--handshake] [--userid <id>] [--key <hex>]
- Without
--handshake, this verifies TCP reachability. - With
--handshake, it additionally verifies anonymous ZKAC handshake. - For handshake mode, provide either
--keyor--userid(not both).
End-to-End Workflow: Create, Grant, Receive, Authenticate
Two users: alice (admin) and bob (recipient), one server on localhost:9800.
- Create users
zkac-node user create alice
zkac-node user create bob
- Start server (Alice host)
zkac-node serve alice --host 127.0.0.1 --port 9800
- Pin server key for both users
zkac-node server pin alice localhost:9800 --key <SERVER_PK_HEX>
zkac-node server pin bob localhost:9800 --key <SERVER_PK_HEX>
- Bob shares contact bundle with peer endpoint
zkac-node user show bob --peer 127.0.0.1:9810
Copy the emitted contact blob from Bob to Alice through an out-of-band channel.
- Alice creates registry
zkac-node registry create alice localhost:9800 --roles analyst,operator
Save the registry_id from command output.
- Bob starts one-shot receiver
zkac-node p2p-listen bob --host 127.0.0.1 --port 9810
- Alice grants Bob
analyst
zkac-node grant alice --server localhost:9800 --registry <REGISTRY_ID> \
--role analyst --to "<BOB_CONTACT_BUNDLE>"
- Bob verifies local credential
zkac-node credentials list bob
- Bob authenticates
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server localhost:9800
Workflow: Revoke a Role
Revoke only one role:
zkac-node registry revoke alice localhost:9800 --registry <REGISTRY_ID> --role analyst
Revoke all roles:
zkac-node registry revoke alice localhost:9800 --registry <REGISTRY_ID> --all
After revocation, existing credentials for bumped epoch(s) no longer authenticate.
Workflow: I2P Connectivity
Run server intended for I2P tunnel exposure:
zkac-node-i2p-server alice --host 127.0.0.1 --port 9800
For outbound client traffic to .i2p endpoints, configure SOCKS5:
export ZKAC_SOCKS5_PROXY=127.0.0.1:4447
Then use normal commands against *.b32.i2p:port:
zkac-node net check exampledestination.b32.i2p:9800
zkac-node net check exampledestination.b32.i2p:9800 --handshake --key <SERVER_PK_HEX>
zkac-node auth bob --registry <REGISTRY_ID> --role analyst --server exampledestination.b32.i2p:9800
Local Storage Layout
Per user directory (~/.zkac/<userid>/):
identity.json issuance + p2p transport identity data
admin/<registry_id>.json local admin material for owned registries
credentials/<rid>_<role>.json received credentials
servers/sha256_*.json pinned server public keys
server/ server state if `serve` is run for this userid