ssh keys today are used directly as signing/encryption keys. this works but limits what you can derive from them.
proposal: use the ssh key as entropy input to a domain-separated kdf, then derive purpose-specific keys from that root. the ssh key becomes a seed, not a leaf.
root = hkdf(ssh_private_key_bytes, "zcli-v1")
├── signing = hkdf(root, "ed25519-signing")
├── license = hkdf(root, "zpro-license")
├── ring-vrf = hkdf(root, "bandersnatch-ring")
├── encryption = hkdf(root, "x25519-encryption")
└── ...future purposes without touching the ssh key again
backwards compat: if the derived signing key doesn't match existing on-chain state, fall back to direct ssh key usage. new users get the kdf path by default.
why:
- one ssh key -> unlimited purpose-specific keys
- domain separation prevents cross-protocol attacks
- ring vrf needs bandersnatch keys, not ed25519 - kdf handles this naturally
- license identity needs a stable non-rotating key - another derivation path
- no new secrets to manage. ssh-agent already protects the root.
ssh keys today are used directly as signing/encryption keys. this works but limits what you can derive from them.
proposal: use the ssh key as entropy input to a domain-separated kdf, then derive purpose-specific keys from that root. the ssh key becomes a seed, not a leaf.
backwards compat: if the derived signing key doesn't match existing on-chain state, fall back to direct ssh key usage. new users get the kdf path by default.
why: