Skip to main content
Use Anon Aadhaar as an optional admission integration when your application requires evidence of an Aadhaar credential. The application chooses this policy; other apps can use invitations or another admission mechanism with the same Semaphore group APIs.
Status: experimental research, synthetic test mode only. The combined Anon Aadhaar-to-Semaphore admission adapter is not implemented. Do not advertise this as a production Aadhaar login or verified unique-person enrollment. An application’s policy does not establish legal RTI filing requirements or prove citizenship.

Where it fits

Anon Aadhaar gates joining a group. Semaphore gates submitting records after joining. Arkognito continues to handle encryption, relaying, one-time owners, record discovery and ownership proofs. Users do not need to present an Aadhaar credential for each subsequent record. For example, a reporting app could choose to admit credential holders to its private reporting group. Its admission service checks their credential proofs off-chain, then enrolls random-secret commitments. Reports use Semaphore proofs without publishing the credential or identifying which approved commitment submitted them. This is an application policy, not a legal RTI requirement. Neither Anon Aadhaar nor a credential adapter is required for apps that use invitations or admin-approved membership. Keep this integration optional.

Before you start

  • Create a group and configure its relayer using anonymous group permissions.
  • Use arkognito@0.1.0 containing arkognito/semaphore, or its main-branch source build.
  • Keep the admin signer and credential verifier server-side, with one writer queue for its wallet.
  • Use synthetic Anon Aadhaar test credentials throughout this project’s demonstration.
For a separate experiment matching the tested versions:
These are the experiment’s pinned versions, not a claim about the latest release. Use the upstream quick setup for its provider, proof UI and off-chain verification APIs. Set the provider’s _useTestAadhaar to true for synthetic credentials. Optional reveals include age above 18, gender, state and PIN code; request no optional fields unless your policy needs them.

Connect the enrollment flow

1. Derive a group commitment

In the browser, create or restore a vault for the group’s project:
Show the recovery code to the user and keep it private. Restore the same vault on subsequent visits; generating a new vault each visit creates a different identity. Send only the public commitment to the admission flow. Never derive this commitment from an Aadhaar number.

2. Prove the intended enrollment

Your admission service issues a short-lived, single-use challenge. Bind the credential proof’s signal to the target commitment, group, app and challenge. Define one canonical encoding that the client and verifier both implement, including: The installed core experiment required a numeric hex signal, rather than arbitrary text. Its public signalHash must be checked using the upstream encoding/hash rules. This page does not define a new wire protocol or an already implemented binding helper.

3. Verify privately and reserve enrollment

The admission service must check all of these before approving a commitment:
  • The cryptographic proof verifies against the intended test or production key policy.
  • The proof’s public signal matches the server’s expected enrollment binding.
  • The challenge is unexpired, unused and belongs to this enrollment request.
  • The credential timestamp meets the application’s freshness policy; proof creation time alone is insufficient.
  • The nullifier seed matches a fixed, application-controlled policy, rather than a browser-selected value.
  • Required disclosures match the policy, and repeated enrollment is handled atomically off-chain.
Test and production keys are different. A valid test proof must never authorize a production group. A browser’s login state or a Boolean saying “verified” is not server-side evidence. Store the challenge, replay guard and pending enrollment outcome off Arkiv. If the admin write has an uncertain outcome, reconcile it before releasing the reservation or appending again.

4. Append the approved commitment

After your admission service has verified and reserved the enrollment, use Arkognito’s existing API:
verifiedCommitment means the exact commitment authenticated by the admission checks above. This snippet does not implement the credential verifier. Wait for confirmed enrollment before proving group membership. The group must also reach its configured minimum size.

5. Use Arkognito normally

Subsequent submissions carry Semaphore membership proofs through the normal record endpoint. Use verified reads for group acceptance. Verification does not grant decryption access. Public metadata, group, scope, nullifier and timing remain observable; this integration does not provide complete anonymity.

What was tested

An isolated experiment used the official public synthetic QR/certificate with @anon-aadhaar/core and @anon-aadhaar/react 2.4.3. It generated and verified a test-mode proof. These are single Node observations. They do not establish mobile performance, physical credential handling or production enrollment. The experiment was separate from the integrated SDK tests.

Work required for a supported adapter

The credential verifier, canonical enrollment binding, challenge service and durable enrollment coordinator still need implementation. Before supporting the adapter, test rejection of invalid proofs, wrong issuer keys, test proofs under production policy, expired/reused challenges, substituted commitments, wrong groups, wrong seeds and concurrent duplicate enrollments. Also test recovery when enrollment is confirmed but its acknowledgement is lost. These are required future checks, not results claimed by the isolated proving experiment. Physical-device, browser/mobile and full credential-to-Semaphore enrollment tests remain undone.

Data that stays off Arkiv

Never publish Aadhaar numbers, QR contents, photos, credential proofs, attester data or credential-derived nullifiers, even as hashes. The tested Anon Aadhaar nullifier depends on credential-related data and is not the public nullifier used for subsequent Semaphore posts. Arkiv group commitments must derive from random/private vault secrets, not from Aadhaar numbers. Semaphore submission nullifiers come from the random group identity and its scope. They do not prove that only one identity was enrolled per person. See credential integrations and the Semaphore guide.
Last modified on October 17, 2026