Skip to content

K7 · Custody: Keeper trait + keripy/signify-compatible derivation paths (SaltyKeeper/RandyKeeper) #93

Description

@joeldsouzax

Goal

Key custody: a Keeper trait + keripy/signify-compatible derivation paths, so Secure Enclave / Android Keystore / HSM / encrypted-file backends plug in ABOVE cesr while inception/rotation/signing logic stays pure and portable.

References: keripy app/keeping.py (Keeper/Manager), core/signing.py L331–484 (Salter); signify-ts core/keeping.ts (the 4-algo IdentifierManager family: Salty/Randy/Group/Extern) + core/manager.ts L298–305 (path construction).

What goes IN cesr (pure)

  • Derivation paths, keripy/signify-compatible: path = "{pidx:x}.{ridx:x}.{kidx:x}" (keripy) / stem-prefixed "signify:aid" + ridx + kidx (signify) → Salter::stretch(path, tier) → seed → Signer. Both stem conventions supported; differential-tested against both implementations so a cesr client can interop with existing wallets.
  • The trait (modeled on signify's split, which cleanly hides Salty vs Randy vs hardware):
pub trait Keeper {
    fn incept(&mut self, transferable: bool, count: usize, ncount: usize) -> Result<(Vec<Verfer>, Vec<Diger>), Self::Error>;
    fn rotate(&mut self, count: usize, ncount: usize) -> Result<(Vec<Verfer>, Vec<Diger>), Self::Error>;
    fn sign(&self, ser: &[u8], indices: Option<&[u32]>) -> Result<Vec<Siger>, Self::Error>;
    fn params(&self) -> KeeperParams;  // serializable custody state (sxlt/prxs-style), NEVER raw keys
    type Error;
}

What stays OUT (bombay M4 custody card)

Platform backends (Secure Enclave/Keychain/Android Keystore/HSM = ExternKeeper impls), passcode UX, encrypted keystore files, group-multisig member coordination (the pure index math can live here; the ceremony can't).

Design note from the signify teardown

signify's model ships encrypted key state to the cloud agent (sxlt in keeper.params()). Our self-sovereign default is the opposite: params() exists for the caller to persist LOCALLY; document loudly that transmitting it is the key-light trade-off, not the default.

Acceptance

  • Salty derivation byte-identical to keripy AND signify vectors (same passcode → same AID)
  • Keeper object-safe; SaltyKeeper drives a full icp→rot chain in tests with zero heap key exposure (miri-checked drop/zeroize)
  • no_std + wasm32 green (argon2 crate no_std-verified)

From the 2026-07-05 signify-ts + keripy teardowns. Depends on: #84 (x25519 wrap) for RandyKeeper. Enables: bombay M4 custody backends, lite-bombay phone keys.

Metadata

Metadata

Assignees

No one assigned

    Labels

    cryptoCryptography crates / algorithms

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions