oneseed 0.4.0

Deterministic cryptographic keys from a single seed
oneseed-0.4.0 is not a library.
Visit the last successful build: oneseed-0.7.0

1seed

Rust License: MIT Crates.io zread

Deterministic cryptographic keys from a single seed, stored securely in your OS keychain.

What This Does

  • Stores seed securely in OS-native credential stores (no plaintext files)
  • Derives age, SSH, and signing keys from one master secret
  • Encrypts and decrypts files using age
  • Signs and verifies data using Ed25519
  • Generates site-specific passwords
  • Generates BIP39 mnemonic phrases

What This Does Not Do

  • Store secrets (use files, encrypted with 1seed)
  • Sync secrets (use git)
  • Manage contacts (use a text file)
  • Replace hardware security keys for high-value assets
  • Generate TOTP codes (time-based, not derivable)

Installation

Quick Install

curl -fsSL https://raw.githubusercontent.com/oeo/1seed/master/install.sh | bash

From crates.io

cargo install oneseed

From Source

cargo install --path .

Requires: ssh-add (for agent integration)

Quick Start

# Initialize with a random seed (recommended)
1seed init --generate

# Or use a memorable passphrase
1seed init --passphrase

# Show your age public key
1seed age pub

# Add SSH key to agent
1seed ssh add

# Encrypt to self
echo "secret" | 1seed age encrypt > secret.age

# Decrypt
1seed age decrypt < secret.age

# Derive a password
1seed derive password github.com

# Check status
1seed status

Seed Storage

Seeds are stored in OS-native credential stores:

  • macOS: Keychain.app
  • Linux: Secret Service (GNOME Keyring / KWallet)
  • Windows: Credential Manager

The OS prompts for approval on first access per application.

For testing/automation, override with SEED_FILE environment variable:

SEED_FILE=/path/to/seed 1seed age pub

Commands

Initialization

1seed init [OPTIONS]          Store seed in OS keychain
  -g, --generate              Generate random 32 bytes (recommended)
  -p, --passphrase            Use memorable passphrase
  --from-file PATH            Import from existing file

1seed forget --confirm        Remove seed from keychain
1seed status                  Show seed storage state and derived keys

Age Encryption

1seed age pub                      Show age public key
1seed age key                      Show age private key
1seed age encrypt [OPTIONS] [FILE]
  -R, --recipient KEY     Add recipient (repeatable)
  -F, --recipients-file   Add recipients from file (repeatable)
  -s, --self              Include self as recipient
  -p, --passphrase        Encrypt with passphrase
  -a, --armor             ASCII armor output
  -o, --output FILE       Output file

1seed age decrypt [OPTIONS] [FILE]
  -k, --key FILE          Key file (instead of derived)
  -p, --passphrase        Decrypt with passphrase
  -o, --output FILE       Output file

Default: encrypt to self, decrypt with derived key.

SSH Keys

1seed ssh pub             Show SSH public key
1seed ssh key             Show SSH private key
1seed ssh add [OPTIONS]   Add SSH key to agent
  -t, --lifetime SEC      Key lifetime
  -c, --confirm           Require confirmation

Signing

1seed sign pub                 Show signing public key
1seed sign data [OPTIONS] [FILE]
  -o, --output FILE       Output file
  --binary                Binary output (default: base64)

1seed sign verify SIGNATURE [FILE]
  -k, --pubkey KEY        Public key (default: derived)

Derivation

1seed derive password [OPTIONS] SITE
  -l, --length N          Password length (default: 16)
  -n, --counter N         Rotation counter (default: 1)
  --no-symbols            Alphanumeric only
  --symbols SET           Symbol set (default: !@#$%^&*)

1seed derive raw [OPTIONS] PATH
  -l, --length N          Byte length (default: 32)
  --hex                   Output as hex (default)
  --base64                Output as base64
  --binary                Output as raw bytes

1seed derive mnemonic [OPTIONS]
  -w, --words N           Word count: 12/15/18/21/24 (default: 24)

Management

1seed update        Update to latest release from GitHub
  --check           Check for updates without installing

Realms

Realms namespace all derived keys. Same seed, different realm = different keys.

1seed --realm personal age pub     # Personal age key
1seed --realm work age pub         # Work age key (different)
1seed --realm work ssh add         # Work SSH key

Set a default realm:

export SEED_REALM=personal

Password Rotation

When a password is compromised:

1seed derive password github.com -n 2   # Increment counter

Same site, different counter = different password.

Backup

Your backup is the seed itself. Export it securely:

# Option 1: Export to encrypted file
1seed init --generate
# Your seed is now in OS keychain. To backup:
# On macOS: Open Keychain.app, search "1seed", export
# On Linux: Use secret-tool or seahorse
# On Windows: Use Credential Manager

# Option 2: Use a memorable passphrase you can write down
1seed init --passphrase
# Write down the passphrase in a secure location

From the seed, everything derives deterministically:

  • Same seed + same realm = same keys (always)
  • Different seeds or realms = different keys (always)

Migration from File-Based Storage

If you were using v0.2.0 or earlier with file-based storage:

# Store your existing seed in keychain
1seed init --from-file ~/.seed

# Verify it works
1seed status

# Securely delete the old file
shred -u ~/.seed  # Linux
rm -P ~/.seed     # macOS

Security Notes

Keyring storage: OS-native credential store with hardware encryption support (Secure Enclave on macOS, TPM on Windows/Linux where available).

Passphrase: If using --passphrase, processed through scrypt (N=2^20, r=8, p=1). Uses ~1GB RAM, takes ~1 second. Resists brute force, but use a strong passphrase (6+ random words).

Memory: Keys are zeroized when dropped.

Mnemonic warning: Deriving BIP39 phrases means your cryptocurrency keys share fate with your master seed. Consider using a dedicated realm and understand the risk.

Examples

Encrypt for team

# Collect public keys
cat > team.txt << EOF
age1alice...
age1bob...
$(1seed age pub)
EOF

# Encrypt
1seed age encrypt -F team.txt < secrets.json > secrets.json.age

Sign a release

1seed sign data release.tar.gz > release.tar.gz.sig
1seed sign pub > signing-key.pub

# Others verify
1seed sign verify -k "$(cat signing-key.pub)" "$(cat release.tar.gz.sig)" release.tar.gz

Multiple machines

# Machine A
1seed ssh pub >> ~/.ssh/authorized_keys

# Machine B (same seed in keychain)
1seed ssh add
ssh user@machine-a  # works

Environment Variables

SEED_FILE    Override keychain, use file instead (for testing/automation)
SEED_REALM   Default realm (default: "default")

Version History

v0.4.0 (BREAKING): Keyring-only storage, removed config file v0.3.0: Self-update command, simplified config v0.2.0: Domain-based namespaces (age, ssh, sign, derive) v0.1.0: Initial release

License

MIT