aere-docs/AERE-PQ-SCREEN.md
Aere Network e4cead319d Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:01:36 +03:00

208 lines
14 KiB
Markdown

# AerePQ-Screen: an institution-grade post-quantum compliance passport
AerePQ-Screen upgrades Aere Network's compliance stack so it interoperates with the identity
standards banks and regulated institutions already use, W3C Verifiable Credentials 2.0, Decentralized
Identifiers (DID), and the ERC-3643 / ONCHAINID accreditation model, and adds the differentiator no
other stack carries today: issuer attestations that are POST-QUANTUM signed (Falcon-512) and verified
in full on-chain via Aere's live precompile at 0x0AE1.
It is built ON the existing compliance contracts (AereZKScreen, AereCompliancePool, AereSanctionsRegistry,
AereTravelRuleHashRegistry, and the live AerePQCKeyRegistry), not in place of them. It adds three new
contracts under `aerenew/contracts/contracts/compliance/` and does not modify any deployed contract.
## Honest status (read this first)
- CONTRACTS: built and tested. Three new Solidity 0.8.23 contracts, 12 passing Hardhat tests
(`test/aere-pq-screen.test.js`), verified against the repo's MockPQCPrecompile at 0x0AE1 exactly as
the erc8004 and PQC test suites do.
- POST-QUANTUM SIGNATURE PATH: real. Issuer attestations are Falcon-512 signatures verified on-chain
through the live AerePQCKeyRegistry, which routes to precompile 0x0AE1 (live on chain 2800,
activation block 9,189,161). The local test exercises this via the faithful mock; the real
precompile is separately proven against live mainnet via eth_call, as the rest of the PQC stack is.
- ZK NON-REVOCATION CIRCUIT: **[MEASURE]**. The on-chain W3C Bitstring Status List, the verifier
interface, the public-input shape, and the freshness binding are all built and tested. The SP1
circuit that actually produces a zero-knowledge non-revocation proof is NOT yet implemented. It is
to be built on Aere's existing SP1 zk stack (the same stack behind AereZKScreen).
- CONSENSUS SCOPE: unchanged. Aere consensus stays classical secp256k1 ECDSA QBFT. What is
post-quantum here is the AUTHENTICITY of compliance attestations, an application-layer property.
- ADOPTION AND ACCREDITATION: NOT claimed. Whether any real institution issues credentials here, and
whether accreditation in this registry carries legal weight under eIDAS 2.0 or any regime, is a
partnership and regulatory matter external to this code. Deploying these contracts asserts none of
it. This document describes what the code does, not who uses it.
## Architecture
The flow is Trust Registry, then VC issuance, then Bitstring status, then zk non-revocation.
```
Aere Foundation (trusted-list operator, registry owner)
|
| accredits issuers (scope + Falcon key ref)
v
AereTrustRegistry ----- verifyIssuerSignature() -----> AerePQCKeyRegistry (LIVE)
federated set of verifyWithKey() --> 0x0AE1 Falcon-512
accredited issuers (in-full on-chain PQC verify)
|
| isAccredited(issuerId, type)
v
AereVerifiableCredential ---- statusOf(list, index) ----> AereBitstringStatusList
W3C VC 2.0 anchor + verify: W3C Bitstring Status List
1. issuer accredited? revocation / suspension bitset
2. Falcon-512 issuer signature valid? (via 0x0AE1) + zk non-revocation verifier
3. within validity window? interface + public-input shape
4. not revoked? (status list bit == 0) (SP1 circuit = [MEASURE])
```
### 1. AereTrustRegistry (federated accredited issuers)
Trust is not a single Foundation key. It is a federated SET of accredited issuers, each with a DID,
an accreditation scope (which credential types it may issue), a lifecycle status, and an optional
Falcon-512 key reference. This mirrors, in spirit, the eIDAS 2.0 / EUDI trusted-list model, in which
a supervisory body maintains a machine-readable list of trust service providers and the services each
is accredited for. Here the Foundation is the trusted-list operator (the registry owner).
- Each issuer entry: `controller` (the issuer id / address), `did` (a did:aere DID, a public
identifier and not PII), accreditation `scope` (a set of opaque bytes32 credential-type tags),
`status` (Active / Suspended / Revoked), and `pqcKeyId` (an optional Falcon-512 keyId in the live
AerePQCKeyRegistry, sentinel `NO_KEY` when absent).
- FAIL-CLOSED: `isAccredited(issuerId, type)` is true only when the issuer is Active and the type is
in scope. Unknown, suspended, and revoked issuers, and out-of-scope types, all resolve to false.
- APPEND-ONLY HISTORY, NO SILENT REWRITE: every status transition and scope change is pushed to an
append-only log. The current status is a pointer; how it got there is immutable and auditable.
- TERMINAL REVOCATION: accreditation revocation cannot be reversed; suspension can.
- `verifyIssuerSignature(issuerId, message, sig)` verifies a Falcon-512 issuer attestation over a
32-byte message via the live AerePQCKeyRegistry (which calls precompile 0x0AE1), fail-closed.
### 2. AereVerifiableCredential (W3C VC 2.0 anchor + verify)
A credential binds an accredited `issuerId`, a subject `did:aere` DID (bound by its hash; the DID
string is carried off-chain, no PII on chain), a `credentialType`, a validity window (`validFrom` /
`validUntil`, the W3C VC 2.0 member names), a W3C BitstringStatusListEntry (`statusListId` +
`statusIndex`), and a `claimsHash` (keccak256 of the off-chain credentialSubject claims, so the anchor
commits to content without publishing it).
Verification (`verifyPresented`, and the live `isValid` for anchored credentials) checks, fail-closed:
1. the issuer is ACCREDITED for the credential type (AereTrustRegistry);
2. the issuer's Falcon-512 signature over the credential digest verifies on-chain via 0x0AE1;
3. the credential is WITHIN its validity window (not-yet-valid and expired both fail);
4. the credential is NOT REVOKED per its Bitstring Status List entry.
`anchorCredential` runs the full path fail-closed and records the credential once; authorship is the
post-quantum signature alone, so anchoring is relayable by any sender. `isValid` then re-checks a
recorded anchor LIVE, so it flips to false the instant the issuer is suspended or revoked or the
credential's status bit is set. `anchorCredentialWithDid` additionally binds and emits the subject's
`did:aere` DID string (enforcing the hash match and the `did:aere:` prefix).
The DID method is `did:aere`, consistent with AereIdentityRegistry8004's `did:aere:<chainId>:<id>`.
### 3. AereBitstringStatusList (W3C Bitstring Status List + zk non-revocation)
An on-chain implementation of the W3C Bitstring Status List v1.0 mechanism: a compact bitset where
each credential is assigned a status index, and the bit at that index encodes its status (default
0 = active). Revoking a credential flips one bit. Because one list packs many credentials, a verifier
learns only the queried bit, giving herd privacy.
- A list is created for one W3C statusPurpose: Revocation (bits are monotonic and terminal) or
Suspension (bits are reversible). Bits are packed 256 to a word and exposed via `getWord` so anyone
can recompute a commitment over the full bitstring off-chain.
- Controller-only mutation; a re-set of the same value reverts (no silent no-op).
**Zero-knowledge non-revocation ([MEASURE] circuit).** The plain read `statusOf(list, index)` reveals
the queried index. For privacy-preserving verification, a holder can instead prove in zero knowledge
that "the status bit of the credential I hold is 0" (my credential is not revoked) WITHOUT revealing
which index, bound to the list's current committed state. This file defines the verifier interface
and the exact public-input shape; the SP1 circuit is not yet built.
Public-input shape (the SP1 program's committed public values), ABI-encoded exactly as:
```
abi.encode(
uint256 chainId, // must equal block.chainid
address statusListContract, // must equal the AereBitstringStatusList address
uint256 statusListId, // the list the credential's status lives in
bytes32 statusRoot, // commitment to the bitstring the proof was made against
bytes32 credentialCommitment, // hiding commitment to the holder's credential (binds a real
// credential without revealing its status index)
uint8 purpose // must equal the list's statusPurpose
)
```
In-circuit private witness (**[MEASURE]** to be implemented): the status index `i`, an opening of
`statusRoot` at `i` proving `bitstring[i] == 0`, and an opening of `credentialCommitment` to the
credential, so the statement proven is "there is an index i, committed by credentialCommitment, whose
bit under statusRoot is 0", revealing neither `i` nor the credential.
On-chain, `verifyNonRevocation` enforces chainId / contract / listId / purpose, requires `statusRoot`
to equal the list's published root AT THE CURRENT EPOCH (so a stale proof is rejected), then delegates
the bit-is-0 statement to the SP1 verifier (reverts on an invalid proof, the canonical SP1 gateway
ABI). It is fail-closed: it reverts `NonRevocationNotConfigured` when no verifier or vkey is set, so
"unconfigured" can never be mistaken for "not revoked". **[MEASURE]** In this version the status root
is controller-attested via `publishStatusRoot`; a future version derives the root on-chain or inside
the SP1 VM from the raw words so it is trustless. The raw words are exposed regardless.
## Standards alignment
- **W3C Verifiable Credentials 2.0.** The Credential struct maps to the VC 2.0 data model: `issuer`
(the accredited issuer), `credentialSubject` (the subject DID + off-chain claims committed by
`claimsHash`), `validFrom` / `validUntil`, `type` (the `credentialType` tag), and `credentialStatus`
(a BitstringStatusListEntry: `statusListId` + `statusIndex`). The contract anchors a COMMITMENT to
the VC (digest + claims hash), not the JSON-LD document. [VERIFY] the exact JSON member names and
serialization against the finalized VC 2.0 spec before claiming wire-level conformance.
- **W3C Bitstring Status List v1.0.** Implemented directly on-chain (bitset + statusPurpose +
status index). [VERIFY] the W3C-recommended large minimum list size for herd privacy is a
deployment policy choice and is not enforced by the contract.
- **DID / did:aere.** Subjects and issuers use `did:aere`, consistent with AereIdentityRegistry8004.
The contract enforces the `did:aere:` prefix on the binding path; full DID Core syntax validation is
off-chain. [VERIFY] against a finalized did:aere method registration.
- **ERC-3643 / ONCHAINID.** ERC-3643 (T-REX) gates permissioned tokens on ONCHAINID identities that
carry signed CLAIMS from trusted claim issuers held in a Trusted Issuers Registry. AerePQ-Screen
provides the same three primitives, in the same shape: AereTrustRegistry is the trusted-issuers
registry (with scoped accreditation), AereVerifiableCredential is the claim (issuer-signed, typed,
time-bounded, subject-bound), and AereBitstringStatusList is claim revocation. The ERC-3643 claim
signature is ECDSA; AerePQ-Screen's is additionally Falcon-512. [VERIFY] a concrete ONCHAINID
claim-topic mapping (claim topic <-> `credentialType`) before asserting drop-in ERC-3643 interop.
- **eIDAS 2.0 / EUDI trusted lists.** The federated accredited-issuer model mirrors the EUDI trusted
list, where a supervisory body maintains a machine-readable list of trust service providers and
their accredited services. This is a STRUCTURAL alignment. Legal qualification under eIDAS is
external and is NOT claimed.
## The post-quantum differentiator
Every institutional identity stack in production, ERC-3643 / ONCHAINID claims, EUDI wallet
attestations, classic PKI credentials, authenticates the issuer's attestation with ECDSA or RSA,
which a cryptographically relevant quantum computer forges (harvest-now, decrypt-later applies to
long-lived compliance attestations especially). AerePQ-Screen binds an optional Falcon-512 key to each
issuer and verifies the issuer's attestation with a NIST post-quantum signature scheme in full
on-chain via the live precompile 0x0AE1. That is the property banks and regulated institutions cannot
get elsewhere, and it is the reason this passport exists.
## Files
- `aerenew/contracts/contracts/compliance/AereTrustRegistry.sol`
- `aerenew/contracts/contracts/compliance/AereVerifiableCredential.sol`
- `aerenew/contracts/contracts/compliance/AereBitstringStatusList.sol`
- `aerenew/contracts/test/aere-pq-screen.test.js` (12 passing tests)
## Test result
`npx hardhat test test/aere-pq-screen.test.js` from `aerenew/contracts`: 12 passing. Covers
accreditation lifecycle (append-only history, terminal revocation, fail-closed accreditation),
credential issue and verify with a Falcon-512 signature via the 0x0AE1 mock, revocation via the
Bitstring Status List flipping verification to false, a non-accredited (wrong-scope) issuer being
unable to issue, a tampered PQC signature failing closed, fail-closed behavior on issuer suspension
with recovery on reinstatement, expiry rejection, did:aere subject binding, and the zk non-revocation
stub's public-input shape with freshness binding (mock SP1 verifier) plus its fail-closed
unconfigured path.
## Open items ([MEASURE] / [VERIFY])
- **[MEASURE]** Implement the SP1 non-revocation circuit for the public-input shape defined above,
publish its vkey via `setNonRevocationVKey`, and wire the real SP1VerifierGateway.
- **[MEASURE]** Derive the Bitstring Status List root on-chain or in the SP1 VM (currently
controller-attested via `publishStatusRoot`).
- **[VERIFY]** Exact W3C VC 2.0 JSON serialization and member names.
- **[VERIFY]** Concrete ONCHAINID claim-topic to `credentialType` mapping for ERC-3643 interop.
- **[VERIFY]** Finalized did:aere method registration and full DID syntax validation policy.
- **[VERIFY]** W3C-recommended minimum status-list size (herd-privacy policy) at deployment.