Passkey onboarding.
- STATUS
- Testnet
- CRATE
- tenzro-node
- STABILITY
- Stable
- REFERENCE
- passkey-onboarding
The model
Three pillars: the smart account address is the identity, not the signing key. Keys rotate without the address changing. Custody is enforced on-chain at signing time through composable ERC-7579 validator modules.
Reference implementations Tenzro is aligned with: Coinbase Smart Wallet, Daimo, Privy, Safe with modular validators, Argent on StarkNet. All share the same shape — passkey primary + guardian quorum recovery + session keys for app grants.
Substrate
tenzro-crypto::p256 # P-256 keypair, signer, verifier
tenzro-crypto::webauthn # full WebAuthn assertion verifier
tenzro-vm precompile 0x100 # EIP-7951 / RIP-7212 P256VERIFY
tenzro-vm::WebAuthnValidator # ERC-7579 primary validator
tenzro-vm::SocialRecoveryValidator # 0x101d N-of-M guardians
tenzro-vm::SessionKeyValidator # 0x101e scoped session keys
tenzro-vm::SpendingLimitValidator # 0x101f per-tx + daily caps
tenzro-vm::AccountFactory # ERC-4337 v0.8 EntryPoint compatibleEnrollment
The client acquires a WebAuthn registration credential from the platform authenticator and passes the P-256 public key + opaque credential ID + ML-DSA-65 verifying key (for the post-quantum leg) to tenzro_enrollPasskey. The node creates a TDIP human identity, deploys a smart account via the shared AccountFactory, installs WebAuthnValidator as the primary signer, and persists everything to CF_AGENTS + CF_VALIDATOR_MODULES.
POST https://rpc.tenzro.network
{
"jsonrpc": "2.0",
"method": "tenzro_enrollPasskey",
"params": {
"display_name": "Hilal's iPhone",
"passkey_public_key_hex": "0x04...",
"credential_id_hex": "0x...",
"ml_dsa_public_key_hex": "0x..."
},
"id": 1
}Signing
The client builds a UserOperation, hashes it per ERC-4337 v0.8, calls navigator.credentials.get() with the hash as the challenge, and submits the resulting WebAuthn assertion + ML-DSA-65 signature to tenzro_signWithPasskey. The node verifies the challenge matches the op hash, the P-256 leg validates against the registered public key, and the PQ leg validates against the registered ML-DSA verifying key.
For production transactions, the same hybrid signature packed as HybridWebAuthnSignature is supplied as the userOp.signature field on the standard eth_sendRawTransaction / ERC-4337 EntryPoint path. The on-chain WebAuthnValidator runs the same verification through the 0x100 P256VERIFY precompile.
Social recovery
When the user enrolls, they nominate guardians — typically family members, a recovery service, or a backup hardware key. Each guardian holds an Ed25519 + ML-DSA-65 composite key. To rotate the account to a new passkey (after device loss), the user enrolls a new passkey on a new device, calls tenzro_initiateRecovery, and shares the returned recovery_op_hash with the guardians. Each guardian signs and submits via tenzro_submitRecoverySignature. Once quorum is reached, the user calls tenzro_finalizeRecoveryand the node installs the new passkey as the smart account’s primary validator. The smart account address never changes.
tenzro_addGuardian # register one guardian
tenzro_initiateRecovery # open the rotation ceremony
tenzro_submitRecoverySignature # one per guardian
tenzro_finalizeRecovery # install new passkey on quorum
tenzro_listPendingRecoveries # observe ceremony stateSession keys for agents
Agents never hold the human’s passkey. The human grants the agent a scoped session key: tenzro_grantSessionKey installs a SessionKeyValidator config with allowed function selectors, target contracts, per-call value cap, cumulative lifetime cap, and validity window. The agent uses its own Ed25519 key to sign user ops within the scope; anything outside the scope is refused at the on-chain validator.
Revocation is one call: tenzro_revokeSessionKey. The session validator disengages immediately and the agent loses signing authority.
Hardware signers
Power users layer a Ledger / Trezor / GridPlus / YubiKey as an additional ANDed validator: tenzro_addHardwareSigner installs a hardware validator module that the EntryPoint AND-combines with the primary passkey validator. Configure required_always: true for a hardware second factor on every operation, or set required_above_wei for a value threshold above which the hardware key is mandatory.
Surfaces
The passkey RPCs map 1:1 to client surfaces:
- Rust SDK:
TenzroClient::passkey_rpc()returns aPasskeyClient. - TypeScript SDK:
TenzroClient.passkeyRpc. - CLI:
tenzro passkey enroll | add-guardian | initiate-recovery | grant-session-key | add-hardware-signer | list-accounts - MCP tools:
enroll_passkey,sign_with_passkey,add_passkey_guardian,initiate_passkey_recovery,submit_recovery_signature,finalize_passkey_recovery,grant_session_key,revoke_session_key,set_spending_limit,add_hardware_signer,get_smart_account,list_smart_accounts,list_pending_recoveries. - A2A:
passkey-walletskill.
Hybrid post-quantum
Every passkey-bound smart account on Tenzro carries a hybrid PQ leg in addition to the classical P-256. The WebAuthnValidatorAND-combines the two — both must verify for the user op to validate. The PQ key (ML-DSA-65, 1952-byte vk, 3309-byte sig) lives alongside the passkey in the user’s key store and is enrolled at the same time as the passkey. This aligns Tenzro with the genesis v3 PQ-hybrid posture: classical + ML-DSA on every validator and identity.