Phase 1 Threat Model
Threat model for Phase 1 — the self-sovereign user flow, credential issuance, and stealth address generation. Phase 2 (delegated-user flow, VOPRF network, token layer) is out of scope.
STRIDE we employ the STRIDE methodology and assign each threat a value:
- Spoofing: pretending to be a different entity.
- Tampering: changing data or code.
- Repudiation: taking an action, denying it, without provenance to correctly attribute it.
- Information disclosure: reading data you should not.
- Denial of service: stopping or degrading the system so legitimate user experience is harmed.
- Elevation of privilege: crossing a privilege boundary to gain rights over a specified level.
Lifecycle stages:
- Identity generation
- Registration and deduplication
- Credential issuance
- Credential verification
- Stealth addresses
- Revocation and recovery
1. Identity generation
The device generates a 32-byte secret from the platform CSPRNG and derives the secp256k1 account, spending, viewing, and auth keys from it, with networkId = keccak256(DOMAIN_NETWORK_ID ‖ pubkeyX ‖ pubkeyY). The P-256 secure-enclave key signs credential bindings, and the identity key is derived from it by ECDH. Nothing is onchain at this stage of the lifecycle.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| User | A software secret in the OS keystore derives the account, spending, viewing, and auth keys, so malware on an unlocked or rooted device reads all of them. | Information disclosure, Spoofing | Keystore-gated behind biometric unlock. The app SHOULD refuse to run on a jailbroken or rooted phone. |
| Platform RNG | A weak platform RNG produces a low-entropy, guessable secret. | Spoofing, Information disclosure | Use only the platform CSPRNG — throw rather than fall back to a weaker RNG. |
| App supply chain | A malicious build, update, or dependency exfiltrates the device secret for every user of that network member. | Tampering, Information disclosure, Spoofing | Would need reproducible builds, pinned dependencies, signed updates. |
| Device thief | A copy of the phone's storage restored onto another device reproduces the secret. | Spoofing, Information disclosure | The secret is device-bound in the keystore, so a raw image copy is unusable elsewhere. |
2. Registration and deduplication
An approved network member authorises every write with an anonymous Semaphore membership proof. It is bound to one action, payload, registry and chain. Any address can submit the transaction, so a network member submits from a paymaster-sponsored stealth address and the chain records that an approved network member made the change without recording which one. Registration rejects a networkId that already has an entry. Update and removal also use a proof for access control. Deduplication runs against the network ID.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| User | Enrols under two different identities to get two accounts (Sybil). | Spoofing | KYC is done properly with specific common identifiers supported, members hold identity to common identifier link offchain so can detect when someone signs up again — a duplicate onboarding hits the same identifier and the registry read catches it. A second member may not detect a second ID type is used |
| Network member | Its server submits the registration and could bind a wrong meta-address. | Tampering | The user reads its entry back and checks it resolves to the meta-address it derived. |
| Network member | Withholds the submission. | Denial of service | Liveness risk. Any other approved network member can submit the same entry. |
| Network member | A compromised auth key resets the network member's own meta-address in the NetworkMemberRegistry and publishes issuer keys in its name. | Spoofing, Tampering, Denial of service | The auth address is fixed at approval to the address of the account key the registry derives the network member's networkId from. Network members should store their keys securely |
| Network member | Registers a user's identity with keys it controls, so it holds that user's meta-stealth address instead of the user. | Spoofing, Elevation of privilege | Network members are trusted, KYC'd entities, and registration rests on that trust. |
| Network member | Registration holds the link from a user's real-world identity to their networkId, so a breach de-anonymises every user it enrolled against onchain activity. | Information disclosure | Network members secure backend infra to best practice. |
| Any network member | Updates or removes any networkId entry, including users it never onboarded, and re-points it at a meta-address it controls. | Repudiation, Elevation of privilege | Trust in the admitted network member set, which governance controls. |
| Other network member | Looks up a user's identifier to find their accounts. | Information disclosure | identity(networkId) is public because anyone with the account's public key can derive the id. It only reveals the meta-stealth address, and the stealth accounts still need the viewing key. |
| Governance | A compromised governance key admits an attacker as a network member, or overwrites a network member's onchain record. | Tampering, Spoofing, Denial of service | Signing thresholds among trusted parties and secure signing practices. A deployment can add a delay before governance actions execute, so members see them before they take effect. |
| Public chain observer | Reads the networkId => metaStealthAddress entry. Attempts to link onchain data to real-world identity. | Information disclosure | No personal data onchain. A user's networkId hides its account address until the account key signs onchain (a transaction or 7702 authorization reveals its public key), which no current flow does (Limitations). |
| Public chain observer | Records the entry now to recover the key once quantum computers arrive (harvest now decrypt later). | Information disclosure | Known threat. The architecture can be upgraded to be post quantum secure, but harvest now decrypt later is a remaining vulnerability for existing accounts |
| Public chain observer | Attributes every user a network member enrols to it, by the identity that submitted the registration. | Information disclosure | Registrations come from a paymaster-sponsored stealth address, so the paying address attributes nothing, though a bundle's tx.from is the bundler's account. No personal data onchain. |
| Public chain observer | Reads the nullifier and scope that every registry write publishes, and tries to link writes to one network member. | Information disclosure | The nullifier is poseidon(secret, scope), so different scopes give unlinkable nullifiers even when the scopes are public. A reused scope repeats the nullifier, which Semaphore rejects. The client chooses the scope, and a new one per proof is enough. |
| Sponsored sender | One membership proof sponsors the same account without limit, because the paymaster does not validate the nullifier. | Elevation of privilege | Deliberate. The proof scope is the sender address, so reuse buys operations for that one account and no other. |
| Sponsored sender | Inflates self-declared preVerificationGas, which can drain the paymaster deposit and deny sponsorship to everyone else. | Denial of service | MAX_COST_PER_OP bounds each operation. Additional option is a design such as GasLimitedPaymaster |
| Device thief | A stolen device holds the account key and would rotate networkId => attackerMetaStealthAddress. | Tampering | Every write needs an approved network member's proof, which the account key cannot produce. Recovery is handled by network members and deactivates the old networkId and registers a fresh one — relies on KYC being done correctly. |
3. Credential issuance
An approved network member issues a credential, bound to the P-256 device key and the identity key, and delivered offchain (VC Issuance and Verification). No claim in it is ever disclosed to a verifier. The one onchain write is the member's signing key, published at onboarding as an entry in the approved-issuer set.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| Network member | Whoever holds the issuer signing key can mint valid credentials for any user. Issuing a credential writes nothing onchain, so a forged one is invisible until someone tries to verify it. | Spoofing | The reference issuer service signs in process with the key from ISSUER_PRIVATE_KEY; a key service that never releases it is future work. If the key is stolen, retireIssuerKeyImmediately retires it and stops every set root it could still be proven against, so forged credentials stop verifying at once. |
| Network member | An attacker with API access to the issuer service signs forged approvals. | Spoofing, Elevation of privilege | No key service yet. The key signs only inside POST /v1/credentials, after a fresh challenge, the holder's proofs, the device key's security level and confirmed enrolment. The eligibility policy approves whoever POST /v1/registrations enrolled, so its member server token is the real boundary. |
| Network member | publishIssuerKey takes any on-curve point without proof of possession, so a network member can publish another member's key. Credentials signed with it still verify, but the owner cannot retire it, and it is retired if the publisher is removed. | Denial of service | Accepted: network members are trusted. Governance can retire the leaf. MAX_ISSUER_KEYS_PER_MEMBER caps a network member at eight live keys. |
| Network member | publishIssuerKey admits a mixed-order variant of a published key, a prime-order point plus a torsion point, which defeats the duplicate check. | Spoofing | The circuit clears the cofactor, so only the original key's holder can sign under a variant. TypeScript publishing rejects variants. One secret holds at most eight live leaves. Governance can retire a leaf. |
| Network member | Withholds the credential. | Denial of service | Accepted. Issuance is the network member's own gate, so unlike registration no other party can issue in its place. |
| Network member | The issuer stores credentialId => networkId. A breach de-anonymises every one of its users against onchain activity. | Information disclosure | Needs access control and minimised retention. |
| User | The device key is a software key, or a dishonest wallet claims hardware it lacks. | Spoofing, Elevation of privilege | Issuer checks attestation. Residuals: Google roots; a leaked RKP or factory attestation key, or userspace back-dating a key, passes until revoked; agreement key unattested; issuer sees OS, patch, boot key; broken TEE. |
| Governance | Admits a network member, and a malicious admission lets it issue valid approvals. | Elevation of privilege | Signing thresholds among trusted parties and secure signing practices. A deployment can add a delay before governance actions execute, so members see them before they take effect. Before approving, network members confirm the candidate's details, including that the issuer public key it will publish is its own. |
4. Credential verification
The user presents a zero-knowledge proof to a relying party, usually another network member (VC Issuance and Verification). The proof establishes that an approved network member signed the credential and that the holder controls the three keys it was bound to, the P-256 device key, the holder key and the revocation key. The verifier does not read the issuer identity, which issuer anonymity forbids, and checks the signing key against the approved-issuer set root instead. Presentation still verifies offline against cached reads, and now needs local proof generation on the holder's device as well.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| Relying party | Asks for more than the decision needs. | Information disclosure | The proof answers only the scope equality the verifier states, so asking for more returns nothing extra. |
| Circuit | An under-constrained circuit accepts proofs of statements that are false, which is a universal forgery with no visible symptom. | Spoofing, Elevation of privilege | Circuit review by someone other than its author, plus negative tests that mutate one input at a time and require rejection. Accepted risk: neither shows the constraint set is complete, so soundness rests on review until an audit. Withdrawing a circuit found unsound means redistributing the artifact to every verifier, each of which keeps accepting the old one until it does. |
| Proof toolchain | Noir, Barretenberg and the hash and signature libraries are new dependencies under both the prover and the verifier, and a tampered or broken one corrupts every verification. | Tampering, Spoofing | Prover and verifier runtimes are pinned to exact versions, and the Noir libraries to upstream tags where one exists. Accepted risk: the EdDSA library has no usable tag and tracks a branch, so it is not reproducible, and at least one library carries no public audit. |
| Holder device | The proof is generated live at the counter, so a mid-range handset that proves slowly or exhausts memory turns into queue time or a failed presentation. | Denial of service | TBD: proving time and peak memory on the target handset are unmeasured, so this cost is not yet bounded. |
| Verifier device | Validity is checked against the verifier's own clock and registry reads are cacheable, so a wrong clock or stale cache accepts an expired, revoked, or removed-network-member credential. | Tampering | Bound the cache lifetime. Offline verification is a requirement. |
| RPC node | A malicious RPC node feeds the verifier a fake issuer-set root or revocation root. | Tampering, Denial of service | RPC is trusted actor. |
| Verifiable Credential SDK provider | A tampered VC SDK or config ships the wrong contract addresses. | Tampering, Spoofing | Out of scope. The VC SDK is trusted by the verifier. |
| Network observer | Captures a presentation and replays it. | Spoofing | A presentation is bound to the verifier and session, so a captured one verifies nowhere else. |
| Network observer | Sees the IP, timing, and size of presentations and reads. | Information disclosure | Out of scope for the reference deployment. |
| Credential thief | Copies the stored credential data and presents it as if it were the holder. | Spoofing | The proof needs the device signing key, which never leaves the secure element and needs the user (biometric, or device PIN, pattern or password) for every signature. A lock-screen unlock alone does not authorise a signature. A lost phone means reissuance. Residuals: the app supplies the prompt text, the signing call still accepts any 32-byte digest (it is not narrowed to presentation components), and the device agreement key stays usable for 10 seconds after an authentication. |
5. Stealth addresses
ERC-5564 stealth addresses keep two things unobservable: the link from a user's meta-address to its stealth accounts, and a network member's relationship to a user's stable identity. The sender derives a fresh stealth address with an ephemeral key and can post an announcement, the network member's indexer scans with the viewing key. Stealth addresses are generated and registered in Phase 1, they are used fully with scoped tokens in Phase 2.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| Network member | A reused ephemeral key sends funds to the same address as before. | Information disclosure | Requires a fresh ephemeral key per send (ERC-5564). |
| Network member | The network member runs the indexer and holds the user's viewing key, so it sees the entire receiving history. | Information disclosure | An accepted privacy concern. The viewing key reveals what is received, never spending authority. |
| Network member | Stealth accounts are underivable onchain without the viewing key, so if its indexer goes down the user is blind to what has arrived. | Denial of service | Open source indexer. Assume network members run indexers securely. |
| Announcement spammer | ERC5564Announcer.announce is permissionless, so anyone can flood it and inflate every indexer's scan cost. | Denial of service | None in the design. The view tag is a 1-in-256 pre-filter. Scanning is offchain, so the cost lands on indexer operators. |
| Auditor | Receives the history a network member discloses, and may try to read beyond the agreed scope. | Information disclosure | Holds no keys, so it cannot scan or derive stealth accounts. The network member does not provide the viewing key and limits disclosure to the agreed users, window, and fields. |
| Public chain observer | Reads every announcement and may try to cluster a user's stealth accounts, or link a network member to a user. | Information disclosure | Each transfer lands in a fresh stealth address, the link to the meta-stealth address is underivable without the viewing key or shared secret. Graph leaks such as co-spending accounts and public transfer values are known limitations |
6. Revocation and recovery
A network member revokes a credential by publishing its revocation commitment to a revocation registry, and the holder's proof shows that commitment is absent from the registry's tree (Revocation in Coordination Network). The verifier reads only the registry's current root. On device loss, KYC deactivates the old networkId and registers a new one.
| Actor | Capability | STRIDE | Mitigations |
|---|---|---|---|
| User | An impersonator passes re-KYC as the user and recovers to keys they control. | Spoofing, Elevation of privilege | Recovery is only as strong as the re-KYC gate. |
| Network member | Runs recovery, so it can deactivate a networkId to deny or stall service. | Denial of service | Network members are trusted entities and must follow security best practices |
| Network member | Runs a recovery the user did not ask for and re-registers their identity with keys it controls, so it holds that user's meta-stealth address instead of the user. | Spoofing, Repudiation, Elevation of privilege | Network members are trusted, KYC'd entities, and recovery rests on that trust. |
| Network member | Recovery mints a new networkId and a network member still resolving the old one reads the retired meta-address. | Denial of service, Information disclosure | Clear the old entry on a network member's proof, so resolution comes back empty. |
| Public chain observer | Pairs the old entry's removal with the new registration by sender or timing, or reads IdentityUpdated, linking a recovered user's new identity to the old one. | Information disclosure | Recovery removes and re-registers, never updates. Both writes go through the sponsored path, each from its own disposable sender via a shared bundler, apart in time. Accepted residual: at low volume few registrations fall between the two. |
| Network member | Withholds the revocation write, so a credential it should have revoked keeps verifying. | Elevation of privilege | The network member holds the only copy of the commitment, so no one can publish it in its place. Governance removes the network member. |
| Network member | A forged credential carries an attacker-chosen commitment, so the registry can never reach it. | Spoofing, Elevation of privilege | None at the registry. The commitment sits outside it by construction, so retiring the compromised key with retireIssuerKeyImmediately is the only closure. |
| Other network member | Writes a revocation for a credential another network member issued, or spams the registry. | Tampering, Denial of service | Revoking means publishing a credential's revocation commitment, and a member only holds the commitments it issued. The registry takes writes only from approved network members, but it never sees a commitment before revocation, so it cannot tell who owns one. |
| Other network member | Undoes another member's revocation with unrevoke, or replaces the revoked commitment, so the credential verifies again. | Tampering | Accepted. A revoked commitment is public and the registry checks only membership, so any approved member can undo it. A wrong revocation cannot be traced to its author, so it has to stay repairable. |
| Governance | Removes a network member, invalidating every credential it issued. | Denial of service | Signing thresholds among trusted parties and secure signing practices. A deployment can add a delay before governance actions execute, so members see them before they take effect. |
Guarantees
| Property | Description |
|---|---|
| Containment to one user | No key spans users, so a user device compromise stops at that user. |
| No master key across accounts | Spending keys stay on the device, and no user key reaches beyond its account. One derivation signature yields a user's spending, viewing and auth keys. |
| Recipient unlinkability | Deliveries land on fresh stealth accounts, so there is no permanent onchain identity and an outside observer cannot tie them to each other. |
| Anonymous registry writes | The chain records that an approved network member made a registry change, without recording which one. |
| De-duplication without sharing personal data | A network ID check determines whether a user already exists, and no PII passes between network members. |
| User controls the account | The account is a keypair the user holds. The network member never holds the spending key, so it cannot sign as the user. It does hold the viewing key. |
| Unlinkable presentation | Two presentations of one credential share no value beyond the public inputs the verifier itself chose, so a verifier cannot recognise a returning holder. |
| Issuer anonymity | A verifier learns that an approved network member signed the credential without learning which one. |
| Private non-revocation | The proof shows the credential is unrevoked without revealing its revocation commitment to the verifier. |
| No personal data onchain | No PII (including hashed) onchain. |
Limitations
Limitations constitute known design trade-offs and accepted threats. Accepted threats are drawn from the threat model lifecycle tables.
Design trade-offs
| Limitation | Impact | Mitigation / future work |
|---|---|---|
| Single device is a single point of loss | Losing the device loses the identity, the keys, and the device-bound credentials. | Recovery registers a new identity for the same user, and credentials are reissued. |
| A user has no privacy from network members | A user has one identity across the network, so any network member can resolve it to that user's registry entry. Privacy holds against outside observers, not against network members. | Accepted: self-sovereign users are known, KYC'd businesses, not anonymous. The wallet still hides from one network member which others have issued that user a credential. |
| Attribution depends on the submission path | A write from a network member's own EOA puts that address in the transaction and attributes every user that it enrols to it. A paymaster-sponsored stealth address leaves the write unattributed. | Registrations use the sponsored path. No PII onchain, and stealth addresses hide the link from a meta-stealth address to onchain activity. |
| Any approved network member can write any entry | One network member can update or remove any entry, including users it never onboarded. Applies to both the identity registry and the revocation registry. | Accepted. Network members are trusted not to act maliciously toward each other. |
| Network members are a single point of failure | A network member can withhold a registration, a credential, a revocation write, or a recovery, and its indexer can go down. | Accepted. Network members are trusted, centralised entities. |
| Deduplication depends on KYC quality | The chain only checks whether an identity already exists, so dedup is only as strong as the KYC gate. A user who registers two separate devices gets two identities — for example, a user presents two valid IDs to two separate network members in a single jurisdiction. | One identity per user at the gate, and the registry read catches a repeat. Mandate a single common identifier across network members. |
| A compromised viewing key cannot be rotated | A leaked viewing key reveals past actions. The meta-address is written to storage and is then marked as stale in a recovery scenario. Past announcements stay readable and nothing revokes that. | Recovery to a fresh identity protects future receipts only. Past receipts will be revealed, and an observer may link the new identity to the old one (see section 6). |
| Network member is the recovery authority | It runs recovery, so it can deny, stall, or mistime service. | Accepted. Recovery can support more self-sovereign paths. |
| Issuer anonymity is bounded by the anonymity set | Issuer anonymity is only as strong as the number of network members in the approved-issuer set, and a deployment with one gets nothing from it. | A deployment property that strengthens as network members are admitted. |
Accepted threats
| Limitation | Impact | Mitigation / future work |
|---|---|---|
| Receiving history is visible to the indexer | The network member runs the indexer and holds the viewing key, so it sees every receipt. | The viewing key reveals receiving only, never spending authority. |
| Indexer bearer token grants full access to the API | The indexer checks one shared bearer token on every route. Whoever holds it can read any user's accounts and balances, register keys, and delete values. A leaked token exposes receiving history, allows registration, and lets the holder delete. | Accepted. Each network member runs its own indexer, reached only from its own backend over a private network, so the token grants no more than the member already holds. |
| A network member has recovery rights | At registration or recovery it can enrol keys it controls, so the meta-stealth address is its own rather than the user's. | Network members are trusted, KYC'd entities. Nothing onchain tells this apart from a genuine registration. |
| A network member can publish another member's issuer key | Credentials still verify, but the owner cannot retire the key, and it is retired if the publisher is removed. | Accepted: network members are trusted. |
| Issuer key theft forces mass reissuance | A stolen issuer signing key mints credentials for any user. retireIssuerKeyImmediately stops it verifying at once, and every genuine credential it signed must be reissued. | TBD: no commodity KMS or HSM signs EdDSA over Baby Jubjub, so the custody model has no managed-vault answer on this curve. |
| A forged credential cannot be revoked | A forgery carries an attacker-chosen commitment, so the registry can never reach it. | Removal of the compromised key closes it, but a verifier cannot attribute a forgery to a network member, so detection at presentation does not say whose key to remove. |
| Governance is a powerful authority | Governance can admit a malicious network member, and every admitted network member can write any registry entry. | Sensible signing thresholds among trusted parties reduce the risk but do not remove it. A delay before governance actions execute would bound it further. |
| Contract owners rotate separately | The governance Safe owns the network member registry and group, while the paymaster is owned by the Safe's founding signer. Changing the Safe's signers leaves the paymaster owner unchanged, and each contract's ownership moves in its own transaction, so owners can drift apart. | Accepted. Each contract's ownership is transferred individually. |
| Removing a network member does not end its gas sponsorship | Governance removes a network member from the network member registry and group, but nothing onchain removes it from the paymaster's own group. Until the paymaster owner does, the removed member's transactions are still sponsored. | Accepted. The paymaster owner must be responsible for replicating the correct admission and removal. |
| A superseded root narrows issuer anonymity | An older root may list fewer issuers, so the verifier has fewer candidates for who issued the credential. From the root a proof uses, the verifier can also tell roughly when the user's wallet last fetched the issuer list. | Accepted. The window defaults to one hour, the wallet proves against the current root, and keeping rootDuration short is up to governance. |
| RPC nodes are trusted | A malicious RPC node can feed a verifier a fake issuer-set root or revocation root. The indexer's RPC provider sees every /balances call, which lists one user's stealth accounts together. | Accepted. A verifier or network member indexer can use its own full node, a provider it trusts, or several independent endpoints to remove or reduce the exposure. |
| The Verifiable Credential SDK is trusted | Whoever ships the VC SDK, its contract addresses and its circuit artifact holds bootstrap trust, like a browser's certificate list. A substituted verifying key makes a verifier accept anything, and the verifier has no independent way to tell. | Out of scope. The VC SDK is delivered by the reference implementer. The circuit artifact is supplied by the deployment, so its integrity is that distribution's integrity. Planned: publish it as a versioned package verified at install and load it directly, rather than reading a configured path. |
| Network metadata is visible | An observer sees the IP, timing, and size of presentations and registry reads. | Out of scope for the reference deployment. |
| Account structure is visible | Sponsored sends leave an EIP-7702 delegation designator on the sending stealth account, distinguishing it from undelegated custodied accounts. | Accepted for Phase 1. Keep the current spending path and revisit both spending designs in Phase 2. |
| Onchain graph leaks | Accounts spent together in one transaction link to each other, and transfer values are public. | Accepted for Phase 1. Fresh stealth addresses do not hide transaction-graph links. |
| Harvest-now-decrypt-later on existing accounts | Recorded onchain keys can be broken by a future quantum computer, de-anonymising accounts that exist today. | The architecture can move to post-quantum crypto, but data already recorded stays exposed. |
Open questions
- Audit-side scanning. How auditing works is not fully specified.