Protocol & Cryptography
The ZK, compliance, and contract layer under the SDK.
Overview
Shield is a privacy bridge with programmable compliance. Two properties have to hold at once: a deposit into private mode must be untraceable on-chain, and it must only be openable by a party the user consented to, under conditions the user agreed to. This page explains the cryptography and contracts that make both true.
Shield does not ship its own zero-knowledge rollup. It is an implementation of the Aztec Portal pattern and inherits Aztec’s proving system for all rollup-level proofs. The pieces Shield adds on top are: an identity gate (Proof of Clean Hands, with a Human Passport fallback), on-chain signature checks in the bridge contracts, and an optional encrypt-to-a-controller path enforced by the Human Network.
This page is developer and protocol reference. It is not required reading to bridge funds. If you just want to use the app, see Getting Started.
Proof of Clean Hands (ZK circuits)
Proof of Clean Hands (PoCH) is a reusable, privacy-preserving identity and sanctions proof. A user verifies once, holds the credential on their own device, and then generates unlimited zero-knowledge proofs from it. No raw personal data is written on-chain or held by Human Tech; every identity field is Poseidon-hashed inside the credential.
The credential
At issuance the user completes a government-ID check (passport via NFC, driver’s license, residence permit, visa, or
voter card) plus a liveness check, and is screened against sanctions, PEP, and watchlist sources. On success the issuer
signs a credential with EdDSA over the BabyJubJub curve. The credential leaf is a Poseidon hash over the issuer key, a
secret nullifier, birthdate, a hash of (name, date of birth, address, expiry), issuance time, and scope, where
name = Poseidon(firstName, lastName). No raw PII enters the leaf or the chain.
- A duplicate-identity nullifier (derived from name and date of birth) blocks re-registration for about 11 months. This is the Sybil-resistance property.
- Credentials expire after about one year, with a randomized 0 to 30 day jitter so issuance timestamps cannot be correlated.
The circuit
The zero-knowledge circuit is Holonym’s V3CleanHands, open source in holonym-foundation/id-hub-contracts. It proves
possession of a validly-issued, unexpired, issuer-signed Clean Hands credential whose screening passed at issuance,
binds the proof to a recipient, an action ID, and a scope, and (see Proof of encryption) emits a
provably-correct encryption of the identity fields. Its public signals are encryptedTo, recipient, actionId, and
expiry. From one credential a user can prove different predicates without re-verifying: “I hold a valid Clean Hands
credential,” “I am over 18,” “I am not a US person (Reg S),” or “my country is in this allowed set.” The verifier learns
only that the predicate is true.
Shield’s bridge contracts do not verify this ZK proof directly. The proof is produced and checked in the Human ID and Human Network system; Shield’s bridge contracts verify the attestation signature that the attester issues after a successful PoCH check (see Smart contracts).
Proof of encryption
A privacy tool hides data. PoCH does something stronger: it makes the same proof that hides your identity also carry a
provably-recoverable encryption of it. The V3CleanHands circuit forces the user to ElGamal-encrypt their identity
fields (first name, last name, and date of birth, each mapped to BabyJubJub points) to a designated audit network, and
proves, as a public output of the same proof, that this ciphertext is well-formed and corresponds to the exact
credential being presented. The single-use ephemeral key used for that encryption also signs the on-chain conditions
contract, binding this encryption to this release policy.
So a valid proof establishes two things at once: “this person is clean,” and “here is an encryption of who they are, recoverable only by the audit network, only when a pre-committed on-chain condition is met.” Accountability is carried inside the cryptographic object rather than bolted on afterward. This is verifiable encryption in the Camenisch-Shoup (2003) sense.
Be precise about what the proof does and does not guarantee. It proves the ciphertext is well-formed and bound to the credential under the key the circuit was given. It does not, by itself, prove that key is the legitimate audit key, nor that the data will only ever be released under the agreed conditions. Those two properties are enforced by the attestation checks and by the network and its conditions gate (see Programmable decryption), not by the proof alone.
Programmable decryption
If encrypted identity data can ever be recovered, the rules for recovering it are the whole ballgame. Programmable
decryption means those rules are enforced by a public, pre-committed policy, not by an operator’s discretion. The audit
ciphertext opens only when an on-chain conditions contract returns canDecrypt(decryptor, recordHash) = true for that
specific record. Decryption is per-record and rate-limited; there is no batch path that could open a whole population at
once.
When a request is authorized, the plaintext is reconstructed through the threshold network: distributed key generation (Feldman-VSS DKG), Lagrange interpolation of partial shares, and a per-node DLEQ proof that each share is correct. No single node ever holds the full key or sees the full plaintext (see The Human Network).
Shipped vs roadmap, stated honestly
- Today: the gate is a general-purpose on-chain
canDecryptboolean served by a single allowlisted decryptor (v0), with a 4-of-6 threshold configuration on testnet at a static epoch 0. A specific legal-process binding (for example a verified court-order condition) is a policy the gate can express, not a shipped feature. - Roadmap: the decentralized threshold network as the default, independent release governance, and epoch rotation plus slashing activated in production.
The most important property to state plainly: the conditions gate is checked off-chain, by each operator, before it returns its share. The DLEQ proofs guarantee each share is correct; they do not, by themselves, prevent a threshold-sized set of colluding operators from reconstructing a record without authorization. Unauthorized decryption is deterred by threshold trust plus economic stake (restaking and slashing), not by mathematics alone. Two structural limits bound the harm: decryption is strictly per-record (no batch), and the quorum is re-drawn from the operator pool each epoch. Users can also elect a semi-trusted additive key share, so that operator collusion alone is not sufficient to recover their data.
The proving system
There are two distinct proving systems in play, and it helps to keep them separate.
PoCH identity proofs
- The
V3CleanHandsproof is generated client-side, proved through a VOLE-in-the-head adapter. - The derived compliance proofs (age, Reg S non-US, country-set membership, EU residency) use the same V3 Groth16 framework, which carries a trusted-setup assumption.
- The identity credential itself is signed with EdDSA over BabyJubJub, and the audit encryption is ElGamal over BabyJubJub.
Aztec rollup proving
- All rollup-level proving (transaction execution, state transitions, and the validity proofs posted to and verified on Ethereum) is Aztec’s. Shield implements no custom rollup circuits of its own and inherits this through the native Portal pattern rather than adding a separate relay or trust assumption.
- Shield’s deployments run with real proofs enabled (deployment snapshots carry
realProofs: true), not a mock prover. - The only Shield-specific on-chain cryptography is signature verification: ECDSA on L1 and Schnorr over the Grumpkin curve on L2 (see Smart contracts).
NEEDS SME REVIEW (Caleb, eng). One genuinely-open item: name the exact Aztec proving-system generation the live v5
deployment targets, if you want it stated in public docs. It is an upstream Aztec property tied to the pinned @aztec
package version. Everything else in this section is grounded in the PoCH design and the repo.
The smart contracts
Assets are held 1:1 in the L1 Portal as collateral; L2 tokens are minted on deposit and burned on withdrawal. Private mode mints separate “Clean” tokens (for example cUSDC) that are distinct from the public token, which is what prevents an unverified public-to-private hop from bypassing the entry check.
L1 (Ethereum, Solidity)
TokenPortal.sol: core portal. Public and private deposits, withdrawals, fee calculation and collection, and compliance verification for private deposits. Two independent pause switches (a full pause, and a deposit-only pause that keeps withdrawals live for migration windows).SwapBridgeRouter.sol: atomic gas top-up plus deposit in one L1 transaction. Pulls tokens via Permit2, routes a portion through the fuel swap for Fee Juice, and deposits both legs. The private path requires the router to be registered as a trusted forwarder on each portal.UniswapFuelSwap.sol: stateless Uniswap V4 swap from an ERC-20 into Fee Juice, single- or multi-hop with a native-ETH intermediary.
L2 (Aztec, Noir)
TokenBridge(main.nr): claims minted tokens (public and private), exits to L1 (public and private), and verifies compliance for private exits. Attester and signer public keys (Grumpkin) are stored in a delayed-mutable slot with a 600-block delay before a key change takes effect, which is the response window if an owner key is compromised. Includes nonce replay protection and an owner pause.TokenMinterProxy(main.nr): an allowlist proxy between the bridge and the token contract, so a new bridge version can be authorized without redeploying the token.Token: a standard Aztec token contract (AIP-20 compatible), not custom to the bridge.
Where compliance is enforced
Compliance is checked only at the boundary where privacy begins or ends. Public mode has no gate.
| Operation | Layer | Check |
|---|---|---|
| Public deposit / public exit | n/a | None |
| Private deposit (L1 to L2) | L1 TokenPortal | Clean Hands or Passport, ECDSA |
| Private exit (L2 to L1) | L2 TokenBridge | Clean Hands or Passport, Schnorr over Grumpkin, with max amount and deadline |
In both directions Clean Hands is checked first and Passport is the fallback (amount-capped). Exits also re-run sanctions screening and require a fresh, address-bound attestation with a single-use nonce, so a captured attestation cannot be replayed.
Contract addresses are not hardcoded in these docs on purpose. Read them from the SDK, which treats
deployments.json as the single source of truth: getDeployment(ACTIVE_DEPLOYMENT_ID) returns the active token,
portal, bridge, and network addresses. That way this page can never drift from the live deployment. The current
mainnet set is also listed on the Contracts page.
Audit status
Shield’s components are independently audited, each scoped to that component:
| Component | Auditor |
|---|---|
| Bridge contracts (Ethereum L1 and Aztec L2 Noir) | Nethermind Security (NM-0756, May 2026) |
| Clean Hands ZK circuits | Hexens (2024) |
| Human Network threshold cryptography | Halborn (2024) |
No single firm reviewed all of Shield; each audit covers only its own component. Shield still carries early-network risk regardless (see the early-network risk notice).
NEEDS SME REVIEW (Caleb, eng). Keep this scoping exact. Nethermind reviewed the bridge contracts; Hexens the Clean Hands ZK circuits; Halborn the Human Network threshold cryptography. Do not cross-attribute (Hexens and Halborn did not audit the bridge contracts), do not present a single full-scope Shield contract review, and do not publish finding/severity counts or link the NM-0756 report until the artifact is confirmed shareable.
The Human Network
The audit layer runs on the Human Network (network.human.tech), the threshold-cryptography network that holds the keys behind Shield’s compliance model. It operates as an Actively Validated Service on restaked Ethereum security (EigenLayer and Symbiotic), so its economic security comes from restaked collateral and its operator set is decentralized rather than a fixed multisig. The decryption key is never held in one place: it is split across operators, and each returns only a partial decryption share.
- The operator set is public and includes established professional operators (for example Alchemy, Nansen, P2P, EigenYields, Pier Two, HashKey, Stakely, and Kelp by Luganodes), on the order of 21 operators across roughly two dozen nodes.
- The network implements Forward-Secure Public-Key Encryption (FSPKE) for the keyshares exchanged between operators, so an attacker who records inter-operator traffic and later compromises a node cannot decrypt prior-epoch shares. Corruptions accumulated over time do not eventually yield the network secret.
- The audit encryption is ElGamal over BabyJubJub (a decentralized-ElGamal construction); threshold reconstruction uses Feldman-VSS DKG, Lagrange interpolation, and per-node DLEQ correctness proofs.
One operational fact matters for how you read the accountability path: to date the network’s production workload has been key derivation (a verifiable oblivious PRF that generates Human Keys), not decryption. Threshold decryption is implemented and gated, but no production decryption has been performed. The lawful-access path has been exercised with restraint, and it is also, as of today, untested in production.
Two honest caveats. (1) A threshold-sized coalition of colluding operators could, in principle, reconstruct a record; the mitigations are the restaking-based operator set, epoch-rotated quorums, per-record-only decryption, and the optional user-elected additive key share. (2) The stored audit ciphertext is ElGamal over BabyJubJub, a discrete-log construction, so it is a harvest-now-decrypt-later target for a future quantum adversary. Because audit records have long confidentiality lifetimes, the commitment is to migrate or re-encrypt the audit layer toward NIST post-quantum standards (ML-KEM / FIPS 203) and to minimize retention.
NEEDS SME REVIEW (Nanak, crypto). Node counts, keys-generated, and total-value-secured figures move over time (roughly 3.4 million keys and about $1.8 billion restaked as of late May 2026). Pin any number you publish to a fresh reading of the Human Network dashboard and its date.