The NIP-05 name authority
Summary. Usernames like
alice@goblin.stcome from a small, self-hostable service (goblin-nip05d) that implements NIP-05 resolution and NIP-98-authenticated registration. Goblin ships withgoblin.stas the default authority, but it’s configurable: anyone can run their own and Goblin can point at it (federation).
Motivation
npub1… keys are unreadable. NIP-05 maps a friendly name@domain to a key over plain HTTPS, but the registration side (who gets a name, how squatting is prevented, how you prove you own a key) is not specified by NIP-05. goblin-nip05d is Goblin’s answer: a tiny authority that hands out names, proves ownership with signed Nostr events (no passwords), and resists abuse, and which you can host yourself so Goblin isn’t dependent on one operator.
How it works
- Resolution. A wallet resolving
alice@goblin.stfetcheshttps://goblin.st/.well-known/nostr.json?name=alice(over the mixnet) and reads the pubkey (and any relay hints). A reverse lookup (name-by-pubkey) lets a wallet show the@namefor a key it only knows bynpub. - Registration is keypair-authenticated. Claiming or releasing a name is a NIP-98-signed HTTP request: you prove control of the key, no account or password. The server enforces one active name per pubkey, a set of reserved names (and domain-label reservations), look-alike/homograph folding, a name length cap, and a change cooldown to stop churn/abuse. NIP-98 events are single-use within a freshness window (replay protection).
- Transfer. Rotating your key can carry your name with it: the old key authorizes a transfer to the new pubkey, so you keep
@aliceafter rotation. - Federation. The authority is just a host. Settings → Identity → Name authority lets you change it; bare names then resolve against your chosen domain, and foreign
name@otherdomainidentifiers resolve against their domain. Goblin only auto-trusts its own domain’s names; others pass through the unverified-key gate.
goblin.st) and the claim-username panel, dark.Reference
- Client side (
goblin/src/nostr/nip05.rs):split_identifier()(parseuser@domain/@user/ bare),is_valid_hostname(),resolve(),name_by_pubkey()(reverse),verify(),Nip05Check(Verified/Mismatch/Unreachable);set_home_domain()/home_domain(); defaultsHOME_NIP05_DOMAIN = "goblin.st",DEFAULT_NIP05_SERVER. - Server side (
goblin-nip05d/, a sibling Axum + SQLite crate): the.well-known/nostr.jsonendpoint,/api/v1name availability / register / release / transfer / by-pubkey, NIP-98 auth, reserved names, cooldown. It bundles a stockstrfryrelay write-policy and is deployed atgoblin.stbut designed to be self-hosted. - UI: claim/rotate/transfer flows in
goblin/src/gui/views/goblin/mod.rs(ClaimState,RotateState,NameAuthorityState); availability mapped to friendly copy viaavailability_feedback().
References
- NIP-05 (DNS-based names): https://nips.nostr.com/5.
- NIP-98 (HTTP auth): https://nips.nostr.com/98.
- Self-hosting: Run a name authority.