# 1seed
[](https://www.rust-lang.org)
[](https://opensource.org/licenses/MIT)
[](https://crates.io/crates/oneseed)
[](https://zread.ai/oeo/1seed)
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
```bash
curl -fsSL https://raw.githubusercontent.com/oeo/1seed/master/install.sh | bash
```
### From crates.io
```bash
cargo install oneseed
```
### From Source
```bash
cargo install --path .
```
Requires: `ssh-add` (for agent integration)
## Quick Start
```bash
# 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:
```bash
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.
```bash
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:
```bash
export SEED_REALM=personal
```
## Password Rotation
When a password is compromised:
```bash
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:
```bash
# 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:
```bash
# 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
```bash
# 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
```bash
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
```bash
# 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