AccountManager struct handles all cryptographic key operations for Hoot, including key generation, secure storage using platform-specific keychains, and unwrapping gift-wrapped Nostr events.
Struct fields
Vector of loaded Nostr keypairs currently available in memory
Methods
new()
Creates a newAccountManager instance with no loaded keys.
A new AccountManager instance with an empty loaded_keys vector
generate_new_keys_and_save()
Generates a new Nostr keypair and saves it securely to the system keychain and database.Database instance for storing the public key reference
The newly generated Keys object if successful
Behavior
- Generates a new random Nostr keypair
- Saves the private key to the system keychain (platform-specific secure storage)
- Saves the public key to the database pubkeys table
- Adds the keys to the
loaded_keysvector - Returns the generated keys
Private keys are stored in:
- macOS: Keychain via Security Framework
- Linux: Secret Service API (or file-based fallback)
- Windows: Credential Manager
save_keys()
Saves an existing keypair to secure storage and the database.Database instance for storing the public key reference
Nostr keypair to save
Ok(()) if successful, or an error if storage fails
load_keys()
Loads all keypairs from the database and system keychain.Database instance to query for public keys
Vector of successfully loaded Keys objects
Behavior
- Queries the database for all saved public keys
- For each public key, retrieves the corresponding private key from the system keychain
- Constructs Keys objects from the private keys
- Stores the loaded keys in the
loaded_keysfield - Returns the vector of loaded keys
delete_key()
Removes a keypair from both the database and system keychain.Database instance for removing the public key reference
Keypair to delete
Ok(()) if successful, or an error if deletion fails
Behavior
- Removes the public key from the database pubkeys table
- Deletes the private key from the system keychain
- Removes the keys from the
loaded_keysvector in memory
unwrap_gift_wrap()
Decrypts and unwraps a gift-wrapped Nostr event (NIP-59).The gift-wrapped event (kind 1059) to unwrap
The unwrapped gift containing the rumor (unsigned event) and sender information
Behavior
- Extracts the target public key from the gift wrap’s p tag
- Searches
loaded_keysfor a matching keypair - Uses the private key to decrypt the sealed event
- Unwraps the seal to reveal the rumor (the actual message content)
- Verifies that the seal signer matches the rumor’s pubkey
- Returns the
UnwrappedGiftcontaining the rumor and sender
create_auth_event()
Creates a signed authentication event (NIP-42) for relay authentication.Keypair to sign the authentication event with
WebSocket URL of the relay requesting authentication
Challenge string provided by the relay in its AUTH message
A signed authentication event (kind 22242) containing relay and challenge tags
This is a static method that doesn’t require a mutable AccountManager instance.
validate_nsec()
Validates and parses a bech32-encoded Nostr private key (nsec).The nsec string to validate (e.g., “nsec1…”)
A Keys object if valid, or an error message string if invalid
Return values
Ok(Keys)- Valid nsec, returns the parsed keypairErr("Please enter a private key")- Empty inputErr("Invalid nsec format")- Invalid bech32 encoding or incorrect format
This is a standalone function, not a method on AccountManager.
Example usage
Setting up accounts on first run
Loading existing accounts
Importing an existing key
Unwrapping received messages
Authenticating with a relay (NIP-42)
Deleting an account
Security considerations
- Private keys never leave secure storage except when in memory during active use
- Platform-specific keychains provide OS-level encryption and access control
- Gift wrap verification ensures the seal signer matches the rumor pubkey before accepting
- Automatic cleanup removes keys from memory when AccountManager is dropped
Related
- MailMessage - For creating gift-wrapped messages
- RelayPool - For authentication and message transmission
- Database - For storing public key references