basil-nats 0.7.1

Generic, dependency-light builder for NATS account/user JWTs (ed25519-nkey) where signing is delegated to an external signer (e.g. a key held in a vault/HSM).
Documentation

basil-nats

Build NATS JWTs (the ed25519-nkey JWS profile) without holding the signing key. NATS credentials are JWTs signed by an Ed25519 NKey; normally the tool that mints them (nsc) holds the operator or account seed. This crate produces the exact wire bytes a NATS server expects but splits signing out: you build the signing input, hand it to whatever holds the key (an HSM, a vault transit engine, an nkeys::KeyPair, or the Basil broker) for a raw 64-byte Ed25519 signature, then [assemble] the final token. The seed never has to enter your process, which is the whole point of minting from a broker.

The crate is dependency-light, no_std-capable (--no-default-features --features alloc), and generic: Basil uses it, but nothing in it depends on Basil.

Minting flow

claims → signing_input() → <external Ed25519 signer> → assemble(input, sig) → JWT

Builders exist for each claim shape: [UserJwt], [AccountJwt] (imports, exports, limits, service latency), [OperatorJwt], and [RoleJwt], with typed [Permissions] / [UserPermissions] rather than raw JSON. [format_user_creds] renders the final nsc-style .creds document from a signed user JWT plus the user seed.

Wire format

Matches nats-io/jwt v2 / nsc byte-for-byte:

  • header {"typ":"JWT","alg":"ed25519-nkey"};
  • jti is base32 (no pad) of SHA-512/256 over the standard claims only (aud, exp, jti="", iat, iss, name, nbf, sub); the nats object is excluded;
  • header and claims are base64url no-pad; the signing input is header.claims;
  • the signature is a raw 64-byte Ed25519 signature, base64url no-pad, as the third part.

Verification and NKey helpers

The crate also decodes and checks tokens it did not mint: [decode_nats_jwt] parses a compact token into [DecodedNatsJwt], and [NatsJwtValidation] matches it against candidate signers with closed, diagnostic [NatsJwtValidationReason] outcomes. NKey utilities cover [encode_public] / [decode_public] / [require_public_prefix] for the CRC-checked base32 public encodings ([NkeyType]: operator, account, user, server, curve, …) and [verify_public_signature].

For curve (X) keys, [seal_nats_curve] / [open_nats_curve] implement the nkeys xkey sealed-box construction (X25519 + XSalsa20-Poly1305), with private scalars in Zeroizing owners.

Scope

This crate builds, signs (by delegation), and validates tokens. It does not talk to NATS, manage accounts on a server, or store anything. Resolver push, credential distribution, and custody policy belong to the caller.