SigilIdentityProvider

Derives the user's sigil DID — the stable identity string a Kuira dApp uses to recognise a user across sessions and apps.

The interface is intentionally opaque about how the DID is computed. Today the default implementation (Ed25519PrfSigilProvider) derives a deterministic Ed25519 keypair from PRF(passkey, SIGIL_SALT) and encodes its public key as a W3C did:key:z6Mk…. Future implementations (e.g. zk-passport integration, midnightOS-Passkeys interop, multi-credential aggregation) plug in here by replacing the Hilt binding.

Contract:

  • The returned DID MUST be deterministic in (passkey, implementation). The same user authenticating the same credential MUST get the same DID on every device, in every Kuira app sharing the relying party.

  • The DID is treated as an opaque identifier by every consumer in the codebase today — no caller extracts a public key from it, verifies it cryptographically, or uses it to validate signatures. Implementations are free to choose any encoding.

  • Implementations MUST NOT persist their own state beyond what the PasskeyManager ceremony already records. The caller persists via SigilStateStore.

Why an interface (not a concrete class): identity primitives shift on long horizons (W3C did spec, midnightOS interop, ZK proofs). Owning this seam now means future changes are a Hilt binding swap, not a refactor through five call sites.

Inheritors

Properties

Link copied to clipboard
abstract val prfSalt: ByteArray

The 32-byte PRF salt this provider uses for its ceremony.

Functions

Link copied to clipboard
abstract fun deriveFromPrfOutput(prfOutput: ByteArray): String

Pure derivation: 32-byte PRF output → DID string. No ceremony, no biometric, no Credential Manager.

Link copied to clipboard
abstract suspend fun deriveSigilDid(activity: Activity, passkeyManager: PasskeyManager): SigilDerivation

Convenience one-shot: runs a PRF ceremony with prfSalt, derives the DID, returns it plus the credential ID from the assertion.