BIA-1: Biological Identity Attestation Specification
Version: 1.0-draft Date: 2026-04-02 Author: Bhanusich Chomanan, Ever Medical Technologies Co., Ltd. License: Apache 2.0
1. Abstract
Biological Identity Attestation (BIA) is an open protocol that anchors
cryptographic identifiers to immutable genomic commitments and continuously
validates the link between a digital identity and a living human through
physiological biometric attestation. Where existing identity standards such as
OpenID Connect, FIDO2, and Decentralized Identifiers prove that a user controls
an account, possesses a device, or owns a private key, BIA proves that a
specific biological person is present and alive at the moment of
authentication. The protocol achieves this through a three-layer architecture:
a Biological Anchor derived from a Poseidon hash commitment over genomic identity
markers, a Cryptographic Identity layer that optionally extends to on-chain
decentralized identifiers (did:bio), and a Social Identity layer that bridges
into standard OpenID Connect flows so that any existing relying party can consume
BIA claims without protocol-level changes. BIA is designed to be OIDC-first and
crypto-optional, enabling progressive adoption from conventional web
applications through to fully sovereign zero-knowledge proof systems.
2. Status of This Document
This document is a Version 1.0-draft specification published by Ever Medical Technologies Co., Ltd. under the Apache 2.0 license. It is intended for public review, experimentation, and implementation feedback.
This specification is not yet final. Implementers should expect breaking changes between draft revisions. The authors welcome feedback via the project repository at github.com/everhealthcare or by contacting the specification editors directly.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
3. Introduction
3.1 The Identity Gap
Modern digital identity systems fall into three broad categories, each solving a different trust problem but none proving biological personhood:
| System | What It Proves | What It Cannot Prove |
|---|---|---|
| OpenID Connect | Account ownership (email/password) | That the authenticating party is a specific person |
| FIDO2 / WebAuthn | Device possession (hardware key) | That the device holder is a living human |
| DID:ethr / DID:key | Private key control | That the key controller is biologically unique |
| Worldcoin / Proof of Personhood | Iris scan uniqueness | Continuous liveness; genomic anchoring; medical utility |
All of these systems answer variations of the question: "Does this party control the credential?" None of them answer the question: "Is this party a specific, living, biological human being right now?"
This gap has real consequences:
- Sybil attacks proliferate in governance, airdrops, and clinical trials because identity is cheap to fabricate.
- Medical data cannot be reliably linked to a patient across institutions without a biological root of trust.
- AI-generated deepfakes defeat visual and audio biometrics that lack physiological grounding.
- Account recovery after key compromise has no biological fallback.
3.2 BIA Fills the Gap
BIA introduces a biology-first identity model:
Biology --> Cryptography --> Social Identity
(genome) (Poseidon hash) (OIDC id_token)
(biometrics) (did:bio) (Verifiable Credential)
(liveness) (ZK proofs) (Smart Contract)
The protocol creates a one-way binding from immutable biological traits (genomic markers) through a privacy-preserving cryptographic commitment (Poseidon hash) to standard identity protocols (OIDC, VCs, DIDs) that applications already understand.
3.3 Design Philosophy
OIDC-first, crypto optional. Any application that supports OpenID Connect can consume BIA claims today. On-chain features and zero-knowledge proofs are available for applications that need them but are never required.
Privacy by default. Raw genomic data never leaves the user's device in any flow. The protocol uses zero-knowledge proofs and hashed commitments to prove claims about biology without revealing biology.
Progressive assurance. A user starts at Assurance Level 0 (standard OIDC) and can progressively upgrade to Level 3 (full genomic anchor + continuous liveness + ZK proofs) as their use case demands.
Medical utility. Unlike pure identity protocols, BIA's genomic and physiological data layers enable real medical applications: pharmacogenomics, HLA matching, ancestry-informed dosing.
Open standard. This specification is published under Apache 2.0. There are no patent encumbrances on the protocol itself.
3.4 Author
This specification is authored by Bhanusich Chomanan and published by Ever Medical Technologies Co., Ltd., a health-technology company based in Bangkok, Thailand, building the Ever Digital Healthcare platform.
4. Terminology
The following terms are used throughout this specification with the specific meanings defined below.
| Term | Definition |
|---|---|
| Bio-Anchor | A cryptographic commitment derived from a subject's genomic identity markers using the Poseidon hash function. The Bio-Anchor is the root of trust for all BIA claims. |
| Poseidon Commitment | The output of the Poseidon hash function applied to a structured input of genomic field elements. Denoted C where C = Poseidon(salt, snpVector, hlaVector, mtDNA). |
| Assurance Level (AL) | A numeric level (0-3) indicating the strength of biological identity verification. See Section 6.5 for criteria. |
| Liveness Attestation | A time-bounded cryptographic assertion that a specific biological person was physiologically present and alive during the attestation window. |
| Physiological Template | A multi-axis biometric profile comprising HRV signature, EEG neural fingerprint, circadian rhythm pattern, and glucose baseline. |
| did:bio | A Decentralized Identifier method defined by this specification for biological identity anchoring. Syntax: did:bio:ever:{identifier}. |
| Bio-Anchor Mode | The operational mode of a Bio-Anchor: oidc (server-managed), wallet (client-signed), or chain (on-chain registered). |
| SNP Identity Panel | A curated set of approximately 500 single nucleotide polymorphism loci selected for individual identification power. |
| HLA Profile | Human Leukocyte Antigen allele typing across Class I (A, B, C) and Class II (DRB1, DQB1, DPB1) genes. |
| MT-DNA Haplogroup | Mitochondrial DNA haplogroup classification derived from control region and coding region variants. |
| VCF | Variant Call Format, the standard bioinformatics file format for genomic variant data. |
| Field Element | An element of the scalar field of the BN254 elliptic curve, used as input to Poseidon. |
| BioAnchorRegistry | The on-chain smart contract that stores Bio-Anchor commitments and manages the anchor lifecycle for Tier 3 identities. |
| Tier | One of three deployment tiers defining the trust model: Tier 1 (Standard/OIDC), Tier 2 (Enhanced/server-signed bio), Tier 3 (Sovereign/on-chain ZK). |
| BioClaim | A Verifiable Credential claim type defined by this specification carrying biological identity assertions. |
| Trusted Attester | An entity authorized by the BioAnchorRegistry governance to submit assurance level attestations on-chain. |
| ConsentToken | A signed, time-bounded authorization from the subject granting a specific relying party access to specific bio claims. |
| Groth16 | A zero-knowledge proof system used by BIA for succinct, non-interactive proofs over arithmetic circuits. |
| BN254 | The Barreto-Naehrig elliptic curve used as the underlying field for Poseidon hashing and Groth16 proofs. Also known as alt_bn128. |
| Salt | A cryptographically random 32-byte value used in Poseidon commitment computation. Stored locally by the subject and never shared. |
| Attestation Window | A 15-minute time interval during which a single liveness attestation is valid. |
| Neural Fingerprint | A 15-dimensional feature vector extracted from EEG recordings across multiple cognitive states, unique to an individual. |
| Circadian Signature | A parameterized model of an individual's 24-hour physiological rhythm derived from continuous HRV and activity data. |
5. Architecture Overview
5.1 The Three-Layer Identity Stack
BIA organizes identity into three layers, each building on the one below:
Layer 1: Biological Anchor is the root of trust. It consists of the Poseidon commitment over genomic identity markers and the physiological biometric template used for continuous liveness attestation. This layer answers: "Which biological person is this?"
Layer 2: Cryptographic Identity binds the biological anchor to
cryptographic operations. It includes the did:bio decentralized identifier,
wallet-based signatures, zero-knowledge proof generation, and key management.
This layer answers: "Can this biological person prove claims without revealing
raw data?"
Layer 3: Social Identity bridges cryptographic identity into the protocols that applications already use. It includes OpenID Connect token issuance, Verifiable Credential presentation, REST API access, and mobile SDK integrations. This layer answers: "How do existing applications consume biological identity?"
5.2 The Three Tiers
BIA defines three deployment tiers that allow progressive adoption:
• Bio claims in tokens
• No wallet required
• Assurance Level 0–1
• Liveness attestation
• Physiological template
• Assurance Level 1–2
• Zero-knowledge proofs (Groth16)
• Client wallet signatures
• Full did:bio resolution
• Assurance Level 2–3
| Property | Tier 1 (Standard) | Tier 2 (Enhanced) | Tier 3 (Sovereign) |
|---|---|---|---|
| Authentication | OIDC | OIDC + Bio | OIDC + Bio + ZK |
| Key management | Server | Server | Client wallet |
| Bio claims | Token claims | Signed VCs | ZK proofs |
| Liveness | None | Server-attested | Wallet-attested |
| On-chain | No | No | Yes |
| Assurance Levels | 0-1 | 1-2 | 2-3 |
| Wallet required | No | No | Yes |
| Trust model | Federated | Federated + Bio | Self-sovereign |
| Privacy model | Server sees data | Server sees data | Zero-knowledge |
5.3 Data Flow Overview
The following diagram shows the high-level data flow for a Tier 3 authentication:
Subject Ever BIA Server Relying Party
(Browser + Wallet) (OIDC Provider) (Application)
| | |
| 1. Upload VCF (one-time) | |
|----------------------------->| |
| | |
| 2. Receive Poseidon | |
| commitment + salt | |
|<-----------------------------| |
| | |
| 3. Register Bio-Anchor | |
| on-chain (Tier 3) | |
|----------------------------->| BioAnchorRegistry |
| | |
| 4. Continuous liveness | |
| (wearable -> template) | |
|----------------------------->| |
| | |
| | 5. OIDC Auth Request |
| |<--------------------------|
| | |
| 6. Wallet challenge | |
|<-----------------------------| |
| | |
| 7. Wallet signature + | |
| ZK proof (optional) | |
|----------------------------->| |
| | |
| | 8. id_token with |
| | bio claims |
| |-------------------------->|
| | |
| | 9. Verify token + |
| | check bio claims |
| | |
6. Genomic Identity Markers
6.1 SNP Identity Panel
The BIA SNP Identity Panel is a curated set of approximately 500 single nucleotide polymorphism (SNP) loci selected for maximal individual identification power with minimal ancestry bias. The panel draws from two primary sources:
SNPforID Consortium -- The established 52-plex forensic identity SNP panel, validated across global populations for individual identification with random match probabilities below 10^-15.
gnomAD v4 -- Additional loci selected from the Genome Aggregation Database version 4 based on the following criteria:
- Minor allele frequency (MAF) between 0.3 and 0.5 across all gnomAD populations (maximizing heterozygosity and thus discriminating power).
- Located on different linkage disequilibrium blocks to ensure statistical independence.
- Not in regions of known clinical significance (to minimize unintended health information disclosure).
- Not in regions of high structural variation or known genotyping difficulty.
6.1.1 Panel Composition
| Category | Locus Count | Source | Purpose |
|---|---|---|---|
| Core forensic identity | 52 | SNPforID 52-plex | Primary identification |
| Extended identity | ~300 | gnomAD v4 filtered | Enhanced discrimination |
| Ancestry-informative | ~50 | gnomAD v4 + 1000 Genomes | Population normalization |
| Quality control | ~50 | Distributed across chromosomes | Genotyping QC |
| Pharmacogenomic tag | ~48 | PharmGKB + CPIC | Medical utility (optional) |
| Total | ~500 |
6.1.2 Selection Criteria
Each locus in the panel MUST satisfy all of the following:
- Bi-allelic SNP on the GRCh38 reference assembly.
- Global MAF >= 0.10 in gnomAD v4 (ensures the locus is informative across populations).
- Hardy-Weinberg equilibrium p-value > 0.001 in all gnomAD population groups.
- Pairwise linkage disequilibrium r^2 < 0.05 with every other panel locus in all 1000 Genomes superpopulations.
- Mappability score >= 1.0 in the ENCODE 100-mer mappability track (ensures reliable genotyping).
- Not within 1 Mb of a known GWAS hit for any disease with OR > 2.0 in the NHGRI-EBI GWAS Catalog (minimizes health information leakage).
6.1.3 Encoding
Each SNP locus is encoded as a single value in {0, 1, 2} representing the count of alternate alleles relative to GRCh38. The full panel is encoded as a vector of approximately 500 values, which is then packed into field elements for Poseidon hashing (see Section 7).
SNP encoding:
0 = homozygous reference (e.g., A/A)
1 = heterozygous (e.g., A/G)
2 = homozygous alternate (e.g., G/G)
Packing (base-3 packing into BN254 field elements):
Each field element holds up to 160 base-3 digits
(3^160 < 2^254, so this fits in one BN254 scalar)
snpVector[0] = sum( snp[i] * 3^i ) for i in [0, 159]
snpVector[1] = sum( snp[i] * 3^(i-160) ) for i in [160, 319]
snpVector[2] = sum( snp[i] * 3^(i-320) ) for i in [320, 479]
snpVector[3] = sum( snp[i] * 3^(i-480) ) for i in [480, 499]
6.2 HLA Profile
The Human Leukocyte Antigen (HLA) system is the most polymorphic region of the human genome and provides exceptional individual discriminating power alongside direct medical utility (transplant matching, drug hypersensitivity screening).
6.2.1 Target Genes
| Gene | Class | Alleles (IPD-IMGT/HLA 3.55) | BIA Resolution |
|---|---|---|---|
| HLA-A | I | 7,849 | 2-field minimum |
| HLA-B | I | 9,548 | 2-field minimum |
| HLA-C | I | 7,098 | 2-field minimum |
| HLA-DRB1 | II | 3,516 | 2-field minimum |
| HLA-DQB1 | II | 1,883 | 2-field minimum |
| HLA-DPB1 | II | 1,563 | 2-field minimum |
6.2.2 Imputation from Tag SNPs
For subjects who provide SNP genotyping data (e.g., consumer arrays) rather than dedicated HLA typing, BIA supports HLA imputation using tag SNP panels:
- The extended MHC region (chr6:25-34 Mb on GRCh38) contains sufficient linkage disequilibrium for imputation at 2-field resolution.
- BIA uses a reference panel derived from the 1000 Genomes Phase 3 + Type 1 Diabetes Genetics Consortium dataset.
- Imputed alleles with posterior probability < 0.90 MUST be flagged as
imputed:low-confidenceand MUST NOT be used for Assurance Level 3 claims.
6.2.3 Encoding
HLA alleles are encoded as integer indices into the IPD-IMGT/HLA allele list for each gene. Each gene contributes two allele indices (diploid). The six genes produce 12 values, packed into 8 field elements:
HLA encoding:
For each gene G in {A, B, C, DRB1, DQB1, DPB1}:
allele_1 = IPD-IMGT/HLA index for first allele
allele_2 = IPD-IMGT/HLA index for second allele
(allele_1 <= allele_2, canonical ordering)
hlaVector[0..7] = pack(allele_indices, field_size=BN254)
Packing: each field element holds up to 3 allele pairs
(max allele index < 2^14, so 6 values * 14 bits = 84 bits per element)
6.3 Mitochondrial DNA Haplogroup
The mitochondrial DNA (MT-DNA) haplogroup provides a stable maternal lineage marker with negligible recombination. While it has limited individual discrimination on its own, it serves as:
- A consistency check against the SNP ancestry-informative markers.
- An additional entropy source for the Poseidon commitment.
- A medically relevant marker (mitochondrial disorders, drug metabolism).
6.3.1 Classification
BIA uses the PhyloTree Build 17 nomenclature for haplogroup assignment. The haplogroup is derived from:
- MT-DNA control region (HVR1 + HVR2) variants, OR
- Full mitochondrial genome variants (preferred for higher resolution).
The haplogroup label (e.g., "H2a1") is encoded as a single integer using a deterministic mapping from PhyloTree labels to sequential indices.
6.3.2 Encoding
mtDNA encoding:
mtDNA[0] = phylotree_index(haplogroup_label)
phylotree_index: deterministic mapping
"L0" -> 0, "L1" -> 1, ..., "H2a1" -> N, ...
Total ~5,800 defined haplogroups in PhyloTree Build 17
Fits in a single BN254 field element (5800 < 2^13)
6.4 VCF Parsing Requirements
Implementations MUST accept genomic data in VCF (Variant Call Format) version 4.2 or later, as specified by the GA4GH VCF specification.
6.4.1 Required Fields
For each variant in the BIA panel, the following VCF fields MUST be present:
| Field | Description | Requirement |
|---|---|---|
CHROM | Chromosome | MUST use GRCh38 naming (chr1-chr22, chrX, chrM) |
POS | Position | MUST be GRCh38 coordinates |
REF | Reference allele | MUST match GRCh38 |
ALT | Alternate allele(s) | MUST be present for non-reference calls |
QUAL | Quality score | MUST be >= 20 for Assurance Level >= 2 |
FILTER | Filter status | MUST be PASS for Assurance Level >= 2 |
GT | Genotype | REQUIRED in FORMAT/sample columns |
GQ | Genotype quality | RECOMMENDED; REQUIRED for AL >= 2 |
DP | Read depth | RECOMMENDED; REQUIRED for AL >= 2 |
6.4.2 Parsing Rules
- Multi-allelic sites MUST be decomposed to bi-allelic representation before panel matching.
- Indels at panel loci MUST be treated as missing data (the panel contains only SNPs).
- Missing genotypes (
./.or.) MUST be counted. If more than 5% of panel loci are missing, the overall assurance level MUST be capped at Assurance Level 1. - Genotypes with GQ < 20 SHOULD be treated as missing for AL >= 2.
- The VCF MUST be aligned to GRCh38. If the VCF header indicates GRCh37,
implementations MUST perform liftover before panel extraction, using the
UCSC liftOver chain file
hg19ToHg38.over.chain.gz.
6.4.3 Privacy-Preserving Parsing
To minimize genomic data exposure:
- VCF parsing SHOULD occur on the client device whenever possible.
- If server-side parsing is required (Tier 1 or Tier 2), the server MUST extract only the panel loci and discard the full VCF immediately after extraction.
- Extracted genotypes MUST be encrypted at rest using AES-256-GCM with a key derived from the subject's authentication credential.
- The full VCF file MUST NOT be stored by the server beyond the parsing session.
6.5 Assurance Levels
BIA defines four assurance levels representing increasing confidence in the biological identity binding:
| Level | Name | Requirements | Typical Use Case |
|---|---|---|---|
| AL-0 | Basic | Standard OIDC authentication. No genomic data. | General web login |
| AL-1 | Anchored | Poseidon commitment computed from SNP panel. >= 95% panel coverage. Missing loci imputed. | Patient identity linking |
| AL-2 | Verified | AL-1 + HLA typing at 2-field resolution (typed or high-confidence imputation). Continuous liveness attestation active. | Clinical trial enrollment |
| AL-3 | Sovereign | AL-2 + On-chain Bio-Anchor registration. HLA typed (not imputed). ZK proof capability. Full liveness template (4-axis). All panel loci genotyped (no imputation). | Organ transplant matching, high-value governance |
6.5.1 Assurance Level Transitions
AL-0 ----[upload VCF]----> AL-1
AL-1 ----[HLA typing]----> AL-2 (requires liveness activation)
AL-2 ----[on-chain reg]---> AL-3 (requires wallet + full template)
Downgrade triggers:
- Liveness gap > 24 hours: AL-2 -> AL-1, AL-3 -> AL-2
- Key compromise detected: Any -> AL-0 (until re-anchored)
- Panel coverage drops: AL-1+ -> recalculate based on coverage
7. Poseidon Commitment
7.1 Why Poseidon
BIA requires a hash function that serves as both a binding commitment scheme and an efficient constraint system component inside zero-knowledge proof circuits. The choice of Poseidon is motivated by the following comparison:
| Property | SHA-256 | Pedersen | MiMC | Poseidon |
|---|---|---|---|---|
| R1CS constraints | ~27,000 | ~1,500 | ~800 | ~250 |
| ZK-friendly | No | Yes | Yes | Yes |
| Standardized | Yes | Partial | No | Emerging |
| Algebraic structure | None | EC group | Field | Field |
| Arity support | Binary | Binary | Unary | Configurable |
| Security margin | High | High | Moderate | High |
| Sponge construction | No | No | No | Yes |
Poseidon achieves approximately 100x fewer constraints than SHA-256 in R1CS representation, making it practical to verify commitments inside Groth16 circuits on consumer hardware. Its configurable arity (number of inputs per permutation round) allows the protocol to hash the full genomic input in a single invocation without Merkle tree overhead.
7.2 Input Layout
The Poseidon commitment takes exactly 15 field elements as input, structured as follows:
Index Field Element Source Size
------ -------------------- ---------------- -----------
[0] salt_hi Random salt 128 bits
[1] salt_lo Random salt 128 bits
[2] snpVector[0] SNP loci 0-159 ~253 bits
[3] snpVector[1] SNP loci 160-319 ~253 bits
[4] snpVector[2] SNP loci 320-479 ~253 bits
[5] snpVector[3] SNP loci 480-499 ~32 bits
[6] hlaVector[0] HLA-A pair 28 bits
[7] hlaVector[1] HLA-B pair 28 bits
[8] hlaVector[2] HLA-C pair 28 bits
[9] hlaVector[3] HLA-DRB1 pair 28 bits
[10] hlaVector[4] HLA-DQB1 pair 28 bits
[11] hlaVector[5] HLA-DPB1 pair 28 bits
[12] hlaVector[6] HLA reserved (future)
[13] hlaVector[7] HLA reserved (future)
[14] mtDNA[0] MT-DNA haplogroup 13 bits
All values are encoded as unsigned integers in the BN254 scalar field (p = 21888242871839275222246405745257275088548364400416034343698204186575808495617).
7.3 Commitment Computation
C = Poseidon_15(salt_hi, salt_lo, snp[0..3], hla[0..7], mtDNA)
The Poseidon instantiation MUST use:
- Field: BN254 scalar field (Fr)
- Arity: 15 (t = 16 in sponge notation, i.e., rate 15 + capacity 1)
- Full rounds: 8
- Partial rounds: 57
- S-box: x^5
- Round constants and MDS matrix: As generated by the Poseidon reference implementation with security level 128 bits for t=16.
Implementations MUST produce identical commitment values for identical inputs.
The reference implementation is the circomlibjs Poseidon module with
parameters for t=16.
7.4 Salt Management
The salt provides privacy protection for the genomic commitment. Its management is critical to the security of the system.
7.4.1 Generation
- The salt MUST be 32 bytes (256 bits) generated from a cryptographically secure random number generator (CSPRNG).
- The salt MUST be split into two 128-bit halves (
salt_hi,salt_lo) for field element encoding.
7.4.2 Storage
- The salt MUST be stored on the subject's local device.
- The salt MUST be encrypted at rest using a key derived from the subject's authentication credential (password, biometric, or hardware key).
- The salt MUST NOT be transmitted to any server in Tier 3 mode.
- In Tier 1 and Tier 2 modes, the server MAY store an encrypted copy of the salt for recovery purposes, encrypted with a key the server does not possess (e.g., a key derived from the subject's password via Argon2id).
7.4.3 Recovery
- Loss of the salt renders the commitment unverifiable. The subject MUST re-anchor with a new salt, creating a new commitment.
- The old commitment SHOULD be revoked (on-chain or via the server) to prevent Sybil duplication.
- Backup mechanisms (encrypted cloud backup, social recovery, hardware escrow) are RECOMMENDED but outside the scope of this specification.
7.5 Sybil Resistance
The Poseidon commitment provides Sybil resistance through the following property: one biological genome produces exactly one commitment (for a given salt). To prevent a single person from registering multiple identities:
- Commitment uniqueness: The BioAnchorRegistry (Section 13) maintains a
commitmentOwnerreverse mapping. A commitment value can only be registered once. - Genomic determinism: The same genome with the same salt always produces the same commitment. Changing the salt produces a different commitment, but the old one must be revoked first (enforced by the registry).
- ZK membership proof: A subject can prove their commitment belongs to the registered set without revealing which commitment is theirs (see Section 12).
- Assurance level escalation: Higher assurance levels require progressively harder-to-forge biological evidence (HLA typing, continuous liveness), making Sybil attacks increasingly expensive.
8. Biometric Liveness Attestation
8.1 Overview
Liveness attestation ensures that the biological person associated with a Bio-Anchor is physiologically present and alive at the time of authentication. Unlike one-time biometric checks (fingerprint scan, iris photo), BIA uses continuous physiological monitoring to maintain an ongoing liveness signal.
8.2 Physiological Template
The physiological template is a multi-axis biometric profile constructed from four independent physiological signal sources:
8.2.1 HRV Signature (Weight: 35%)
Heart Rate Variability provides the highest-weight liveness signal due to its continuous availability (any PPG or ECG sensor), difficulty to spoof, and strong individual specificity.
| Feature | Description | Unit | Source |
|---|---|---|---|
| SDNN | Standard deviation of NN intervals | ms | 5-min RR series |
| RMSSD | Root mean square of successive differences | ms | 5-min RR series |
| pNN50 | Percentage of successive NN > 50ms | % | 5-min RR series |
| LF/HF | Low-frequency to high-frequency power ratio | ratio | FFT of 5-min series |
| SD1 | Poincare plot short-axis | ms | Poincare analysis |
| SD2 | Poincare plot long-axis | ms | Poincare analysis |
| ApEn | Approximate entropy | nats | Nonlinear dynamics |
| DFA-alpha1 | Detrended fluctuation analysis short-term | unitless | DFA |
The HRV template is the mean and standard deviation of each feature computed over the rolling window (Section 8.3).
8.2.2 EEG Neural Fingerprint (Weight: 25%)
The EEG neural fingerprint exploits the fact that resting-state brain electrical activity is highly individual and stable over time.
15-Dimensional Feature Vector:
| Index | Feature | Derivation |
|---|---|---|
| 0 | Delta power (rest) | Mean delta (1-4 Hz) band power, eyes-closed rest |
| 1 | Theta power (rest) | Mean theta (4-8 Hz) band power, eyes-closed rest |
| 2 | Alpha power (rest) | Mean alpha (8-13 Hz) band power, eyes-closed rest |
| 3 | Beta power (rest) | Mean beta (13-30 Hz) band power, eyes-closed rest |
| 4 | Gamma power (rest) | Mean gamma (30-45 Hz) band power, eyes-closed rest |
| 5 | Delta power (task) | Mean delta power during cognitive task |
| 6 | Theta power (task) | Mean theta power during cognitive task |
| 7 | Alpha power (task) | Mean alpha power during cognitive task |
| 8 | Beta power (task) | Mean beta power during cognitive task |
| 9 | Gamma power (task) | Mean gamma power during cognitive task |
| 10 | Alpha power (meditation) | Mean alpha power during guided meditation |
| 11 | Beta power (meditation) | Mean beta power during guided meditation |
| 12 | Alpha asymmetry | ln(right alpha) - ln(left alpha), frontal electrodes |
| 13 | IAF | Individual Alpha Frequency: peak frequency in alpha band |
| 14 | P300 latency | Latency of P300 ERP component to oddball stimulus |
Cognitive States:
Three cognitive states are used to maximize discriminating power:
- Eyes-closed rest (60 seconds): Captures baseline resting-state network activity. Features 0-4.
- Cognitive task (60 seconds): A standardized n-back working memory task. Features 5-9.
- Guided meditation (60 seconds): Captures default mode network suppression pattern. Features 10-11.
Features 12-14 are computed across all states.
Hardware Requirements:
- Minimum: 4-channel consumer EEG (e.g., frontal AF3, AF4, T7, T8)
- Recommended: 8+ channel EEG for improved accuracy
- Sampling rate: >= 256 Hz
- Electrode impedance: < 40 kOhm
8.2.3 Circadian Rhythm Signature (Weight: 25%)
The circadian signature captures the individual's unique 24-hour physiological rhythm, which is genetically influenced and stable over weeks to months.
| Parameter | Symbol | Description | Derivation |
|---|---|---|---|
| Phase | phi | Time of physiological nadir | Cosinor analysis of HRV + temperature |
| Amplitude | A | Peak-to-trough range | Cosinor fit amplitude |
| Period | tau | Endogenous period length | Free-running estimate (typically ~24.2h) |
| Mesor | M | 24-hour mean level | Cosinor fit midline |
| Acrophase | psi | Time of peak activity | Actimetry peak detection |
| Stability | IS | Inter-day stability | Non-parametric circadian rhythm analysis |
| Variability | IV | Intra-day variability | Non-parametric circadian rhythm analysis |
The circadian template requires a minimum of 7 days of continuous data for initial enrollment and is updated on a rolling basis.
8.2.4 Glucose Baseline (Weight: 15%)
Continuous glucose monitoring (CGM) provides an additional physiological axis that is difficult to spoof and has direct medical utility.
| Feature | Description | Source |
|---|---|---|
| Fasting mean | Mean glucose during fasting periods | CGM |
| Diurnal range | Max - min glucose over 24h cycle | CGM |
| Meal response curve | Glucose AUC in 2h post-meal windows | CGM + meal log |
| Glycemic variability | Coefficient of variation of glucose | CGM |
| Time in range | % of time glucose is in 70-180 mg/dL | CGM |
Glucose features are OPTIONAL for Assurance Levels 1-2 and REQUIRED for Assurance Level 3.
8.3 Template Lifecycle
Day 1-7: ENROLLMENT PERIOD (minimum data collection)
- Template marked "provisional"
- Cannot be used for AL-2+ attestation
- At least 5 of 7 days must have >= 20 hours of data
Day 7+: TEMPLATE ACTIVE
- 30-day rolling window for feature computation
- Template recomputed daily at 00:00 UTC
- Old data outside 30-day window is discarded
Weekly: TEMPLATE UPDATE
- Feature vectors recomputed from rolling window
- Change detection: if any axis shifts > 2 sigma,
flag for review (medical event? sensor change?)
- Gradual adaptation: exponential moving average
with alpha = 0.1 (slow drift tolerance)
8.3.1 Missing Data Handling
| Scenario | HRV Available | EEG Available | Circadian Available | Glucose Available | Action |
|---|---|---|---|---|---|
| Full template | Yes | Yes | Yes | Yes | Normal 4-axis matching |
| No glucose | Yes | Yes | Yes | No | 3-axis matching, reweighted (HRV 40%, EEG 30%, Circ 30%) |
| No EEG | Yes | No | Yes | Yes | 3-axis matching, reweighted (HRV 45%, Circ 30%, Gluc 25%) |
| No EEG, no glucose | Yes | No | Yes | No | 2-axis matching (HRV 60%, Circ 40%). Max AL capped at 1. |
| HRV only | Yes | No | No | No | Single-axis matching. Max AL capped at 0. Liveness only. |
| No HRV | No | * | * | * | No liveness attestation possible. HRV is REQUIRED. |
8.4 Matching Algorithm
Liveness matching compares a current physiological measurement against the stored template using a weighted multi-axis similarity score.
8.4.1 Per-Axis Similarity
For each axis a in {HRV, EEG, Circadian, Glucose}:
similarity_a = 1 - (distance_a / max_distance_a)
Where:
- HRV distance: Mahalanobis distance between current 8-feature vector and template distribution.
- EEG distance: Cosine distance between current 15-dimension vector and template vector.
- Circadian distance: Euclidean distance in normalized circadian parameter space (7 parameters).
- Glucose distance: Dynamic Time Warping distance between current 24h glucose curve and template curve.
8.4.2 Composite Score
score = w_hrv * sim_hrv + w_eeg * sim_eeg + w_circ * sim_circ + w_gluc * sim_gluc
Default weights (4-axis):
| Axis | Weight | Justification |
|---|---|---|
| HRV | 0.35 | Continuously available, hard to spoof |
| EEG | 0.25 | Highest individuality, requires dedicated hardware |
| Circadian | 0.25 | Stable over time, requires extended data |
| Glucose | 0.15 | Medical utility, requires CGM |
8.4.3 Decision Thresholds
| Threshold | Value | Meaning |
|---|---|---|
| Match | >= 0.70 | Liveness attested: biological person is present |
| Marginal | 0.50 - 0.69 | Inconclusive: request additional data or manual review |
| Reject | < 0.50 | Liveness denied: person not recognized |
8.5 Attestation Protocol
Liveness attestation operates in 15-minute windows:
Time --|------ Window N ------|------ Window N+1 ------|---->
t0 t0 + 15min t0 + 30min
Within each window:
1. Collect physiological data (continuous from wearable)
2. Compute per-axis similarity against template
3. Compute composite score
4. If score >= 0.70:
a. Generate attestation:
attestation = {
subject: did:bio:ever:{id},
window: N,
timestamp: ISO 8601,
score: 0.XX,
axes: { hrv: 0.XX, eeg: 0.XX, circ: 0.XX, gluc: 0.XX },
nonce: random_32_bytes,
expires: timestamp + 15 minutes
}
b. Sign attestation:
- Tier 1/2: Server signs with provider key
- Tier 3: Wallet signs with subject key
c. Store attestation for OIDC token enrichment
5. If score < 0.70:
a. Liveness NOT attested for this window
b. bio_liveness_active = false in subsequent tokens
c. If gap exceeds 24 hours, trigger AL downgrade
8.6 Graceful Degradation
The protocol is designed to degrade gracefully when biometric sources are unavailable:
- Sensor disconnection: If a wearable sensor disconnects, the system continues with available axes using reweighted scores (Section 8.3.1).
- Battery depletion: The last valid attestation remains valid for its 15-minute window. No new attestations are generated until the sensor reconnects.
- Travel / timezone change: The circadian axis may show reduced similarity during jet lag. The system automatically reduces circadian weight by 50% for 72 hours after a detected timezone shift of 3+ hours.
- Medical events: Significant physiological changes (illness, medication changes) may reduce match scores. The system flags these events and allows manual re-enrollment of affected axes while maintaining identity continuity through unchanged axes.
9. did:bio DID Method
9.1 Method Specification
The did:bio method is a Decentralized Identifier method conforming to
W3C DID Core v1.0 that provides
biologically-anchored identity resolution.
9.2 DID Syntax
did-bio = "did:bio:ever:" identifier
identifier = uuid / eth-address
uuid = 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG
eth-address = "0x" 40HEXDIG
HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f"
Examples:
OIDC mode: did:bio:ever:a1b2c3d4-e5f6-7890-abcd-ef1234567890
Chain mode: did:bio:ever:0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18
9.3 Resolution Modes
9.3.1 OIDC Mode
When the identifier is a UUID, the DID resolves via the Ever BIA OIDC discovery endpoint:
Resolution Algorithm (OIDC mode):
1. Extract UUID from DID: did:bio:ever:{uuid}
2. Construct discovery URL:
https://bio.evernetwork.io/.well-known/openid-configuration
3. Fetch discovery document, extract "bio_did_endpoint"
4. GET {bio_did_endpoint}/{uuid}
5. Response: DID Document (JSON-LD)
9.3.2 Chain Mode
When the identifier is an Ethereum address, the DID resolves via the BioAnchorRegistry smart contract:
Resolution Algorithm (Chain mode):
1. Extract address from DID: did:bio:ever:0x{address}
2. Query BioAnchorRegistry.getAnchor(address)
3. If anchor exists and is not revoked:
a. Retrieve anchor metadata (commitment, assuranceLevel, timestamp)
b. Construct DID Document from on-chain data
c. Optionally fetch off-chain service endpoints from
BioAnchorRegistry.getServiceEndpoint(address)
4. If anchor does not exist:
a. Return DID resolution error: "notFound"
5. If anchor is revoked:
a. Return DID Document with "deactivated: true"
9.3.3 Fallback Chain
Resolution with fallback:
1. Parse identifier
2. If UUID format:
a. Try OIDC resolution
b. If OIDC fails, return error (no chain fallback for UUIDs)
3. If Ethereum address format:
a. Try Chain resolution (primary)
b. If chain unavailable, try OIDC resolution (fallback)
c. If both fail, return error
4. If neither format:
a. Return error: "invalidDid"
9.4 DID Document Structure
9.4.1 OIDC Mode DID Document
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://bio.evernetwork.io/ns/bia/v1"
],
"id": "did:bio:ever:a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"controller": "did:bio:ever:a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"verificationMethod": [
{
"id": "did:bio:ever:a1b2c3d4-...#server-key-1",
"type": "JsonWebKey2020",
"controller": "did:bio:ever:a1b2c3d4-...",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "...",
"y": "..."
}
}
],
"authentication": [
"did:bio:ever:a1b2c3d4-...#server-key-1"
],
"assertionMethod": [
"did:bio:ever:a1b2c3d4-...#server-key-1"
],
"service": [
{
"id": "did:bio:ever:a1b2c3d4-...#oidc",
"type": "OpenIDConnectProvider",
"serviceEndpoint": "https://bio.evernetwork.io"
},
{
"id": "did:bio:ever:a1b2c3d4-...#bio-claims",
"type": "BioClaimService",
"serviceEndpoint": "https://bio.evernetwork.io/api/v1/claims"
}
],
"bio": {
"anchorMode": "oidc",
"assuranceLevel": 1,
"commitmentHash": "0x1a2b3c...",
"livenessActive": true,
"livenessLast": "2026-04-02T10:30:00Z"
}
}
9.4.2 Chain Mode DID Document
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://bio.evernetwork.io/ns/bia/v1"
],
"id": "did:bio:ever:0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"controller": "did:bio:ever:0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"verificationMethod": [
{
"id": "did:bio:ever:0x742d35...#wallet-key-1",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:bio:ever:0x742d35...",
"blockchainAccountId": "eip155:137:0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
},
{
"id": "did:bio:ever:0x742d35...#server-key-1",
"type": "JsonWebKey2020",
"controller": "did:bio:ever:0x742d35...",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "...",
"y": "..."
}
}
],
"authentication": [
"did:bio:ever:0x742d35...#wallet-key-1"
],
"assertionMethod": [
"did:bio:ever:0x742d35...#wallet-key-1",
"did:bio:ever:0x742d35...#server-key-1"
],
"service": [
{
"id": "did:bio:ever:0x742d35...#oidc",
"type": "OpenIDConnectProvider",
"serviceEndpoint": "https://bio.evernetwork.io"
},
{
"id": "did:bio:ever:0x742d35...#bio-claims",
"type": "BioClaimService",
"serviceEndpoint": "https://bio.evernetwork.io/api/v1/claims"
},
{
"id": "did:bio:ever:0x742d35...#anchor-registry",
"type": "BioAnchorRegistry",
"serviceEndpoint": "eip155:137:0xBioAnchorRegistryAddress"
}
],
"bio": {
"anchorMode": "chain",
"assuranceLevel": 3,
"commitmentHash": "0x1a2b3c...",
"registryAddress": "0xBioAnchorRegistryAddress",
"registryChain": "eip155:137",
"livenessActive": true,
"livenessLast": "2026-04-02T10:30:00Z",
"livenessWindow": 900
}
}
9.5 Deactivation
A DID is deactivated when:
- OIDC mode: The subject requests account deletion through the Ever
platform. The DID resolution endpoint returns a document with
"deactivated": true". - Chain mode: The subject (or a recovery address) calls
BioAnchorRegistry.revokeAnchor(). The on-chain anchor is marked as revoked, and resolution returns"deactivated": true.
Deactivation is permanent. A new DID must be created for re-enrollment.
9.6 Key Rotation
9.6.1 OIDC Mode
Server keys are rotated according to the provider's key rotation policy. The subject's DID Document is updated automatically. Relying parties MUST re-fetch the DID Document if verification fails with cached keys.
9.6.2 Chain Mode
Wallet key rotation requires:
- The current wallet signs a rotation message containing the new wallet address.
BioAnchorRegistry.rotateKey(newAddress, signature)is called.- The on-chain anchor's owner is updated to the new address.
- The old DID (
did:bio:ever:0x{oldAddress}) is marked as deactivated. - The new DID (
did:bio:ever:0x{newAddress}) inherits the anchor data.
The Bio-Anchor commitment itself does not change during key rotation (since it is derived from genomic data, not from the key).
10. OpenID Connect Integration
10.1 Discovery Document Extensions
The BIA OIDC provider extends the standard OpenID Connect Discovery document with the following additional metadata:
{
"issuer": "https://bio.evernetwork.io",
"authorization_endpoint": "https://bio.evernetwork.io/oauth/authorize",
"token_endpoint": "https://bio.evernetwork.io/oauth/token",
"userinfo_endpoint": "https://bio.evernetwork.io/oauth/userinfo",
"jwks_uri": "https://bio.evernetwork.io/.well-known/jwks.json",
"scopes_supported": [
"openid",
"profile",
"email",
"bio_assurance"
],
"response_types_supported": ["code", "id_token", "code id_token"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"id_token_signing_alg_values_supported": ["RS256", "ES256"],
"subject_types_supported": ["public", "pairwise"],
"acr_values_supported": [
"urn:bio:ever:assurance:0",
"urn:bio:ever:assurance:1",
"urn:bio:ever:assurance:2",
"urn:bio:ever:assurance:3"
],
"bio_assurance_levels_supported": [0, 1, 2, 3],
"bio_anchor_modes_supported": ["oidc", "wallet", "chain"],
"bio_liveness_supported": true,
"bio_liveness_window_seconds": 900,
"bio_did_method": "did:bio",
"bio_did_endpoint": "https://bio.evernetwork.io/api/v1/did",
"bio_zk_proofs_supported": true,
"bio_zk_circuits": [
"genomic_membership",
"pgx_status",
"hla_match",
"bio_assurance"
],
"bio_vc_types_supported": [
"PGxMetabolizerStatus",
"HLACompatibility",
"AncestryEstimate",
"BioAssuranceLevel",
"GenomicMembership",
"LivenessProof"
]
}
10.2 Authorization Flow
The BIA authorization flow extends standard OAuth 2.0 Authorization Code flow with an optional wallet challenge-response step for Tier 2 and Tier 3:
User Agent BIA Provider Relying Party
| | |
| | 1. Auth Request |
| | (scope=openid |
| | bio_assurance) |
| |<-------------------------|
| | |
| 2. Login prompt | |
|<-------------------| |
| | |
| 3. Credentials | |
| (email + password | |
| OR wallet sig) | |
|------------------->| |
| | |
| [Tier 2/3 only] | |
| 4. Wallet | |
| challenge | |
|<-------------------| |
| | |
| 5. Wallet | |
| signature | |
|------------------->| |
| | |
| | 6. Verify credentials |
| | + bio anchor |
| | + liveness status |
| | |
| 7. Redirect with | |
| auth code | |
|<-------------------| |
| | |
|-------------------------------------------> |
| | 8. Exchange code |
| | for tokens |
| |<-------------------------|
| | |
| | 9. id_token + |
| | access_token |
| |------------------------->|
| | |
10.2.1 Wallet Challenge-Response
For Tier 2 and Tier 3 authentication, the provider issues a challenge that the subject's wallet must sign:
{
"challenge": {
"type": "BioWalletChallenge",
"issuer": "https://bio.evernetwork.io",
"subject": "did:bio:ever:0x742d35...",
"nonce": "a1b2c3d4e5f6...",
"timestamp": "2026-04-02T10:30:00Z",
"expires": "2026-04-02T10:35:00Z",
"requiredProofs": ["wallet_ownership"]
}
}
The wallet response:
{
"response": {
"challenge": "a1b2c3d4e5f6...",
"signature": "0x...",
"signerAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"zkProof": null
}
}
10.3 id_token Claims
BIA extends the standard OIDC id_token with the following claims when the
bio_assurance scope is requested:
{
"iss": "https://bio.evernetwork.io",
"sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"aud": "client_id_of_relying_party",
"exp": 1743580800,
"iat": 1743577200,
"nonce": "relying_party_nonce",
"auth_time": 1743577200,
"acr": "urn:bio:ever:assurance:2",
"amr": ["pwd", "wallet_sig", "bio_genomic", "bio_liveness"],
"bio_assurance_level": 2,
"bio_anchor_mode": "wallet",
"bio_liveness_active": true,
"bio_liveness_last": "2026-04-02T10:30:00Z",
"bio_anchor_commitment": "0x1a2b3c4d5e6f...",
"bio_did": "did:bio:ever:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
10.3.1 Claim Definitions
| Claim | Type | Description |
|---|---|---|
bio_assurance_level | integer | The current Assurance Level (0-3) of the subject |
bio_anchor_mode | string | The Bio-Anchor mode: "oidc", "wallet", or "chain" |
bio_liveness_active | boolean | Whether liveness attestation is currently active (within the last 15-minute window) |
bio_liveness_last | string (ISO 8601) | Timestamp of the most recent successful liveness attestation |
bio_anchor_commitment | string (hex) | The Poseidon commitment hash (truncated to 32 hex chars for privacy) |
bio_did | string (DID) | The subject's did:bio identifier |
10.4 AMR Values
BIA defines the following Authentication Method Reference values per RFC 8176:
| AMR Value | Meaning | When Present |
|---|---|---|
pwd | Password authentication | Subject authenticated with password |
wallet_sig | Wallet signature | Subject signed a challenge with their wallet |
bio_genomic | Genomic anchor verification | Subject's genomic commitment was verified |
bio_liveness | Biometric liveness | Subject passed liveness attestation in current window |
10.5 Scopes
| Scope | Claims Granted |
|---|---|
openid | Standard OIDC claims (sub, iss, aud, etc.) |
profile | name, picture, bio_did |
email | email, email_verified |
bio_assurance | bio_assurance_level, bio_anchor_mode, bio_liveness_active, bio_liveness_last, bio_anchor_commitment |
10.6 UserInfo Endpoint
The UserInfo endpoint returns the same bio claims when accessed with an
access token issued for the bio_assurance scope:
GET /oauth/userinfo
Authorization: Bearer {access_token}
Response:
{
"sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"bio_assurance_level": 2,
"bio_anchor_mode": "wallet",
"bio_liveness_active": true,
"bio_liveness_last": "2026-04-02T10:30:00Z",
"bio_did": "did:bio:ever:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
The bio_anchor_commitment claim is intentionally excluded from the
UserInfo endpoint to reduce exposure. It is available only in the id_token
(which is signed and intended for the relying party, not for arbitrary API
consumers).
11. Verifiable Credentials
11.1 W3C VC Data Model Compliance
BIA Verifiable Credentials conform to the W3C Verifiable Credentials Data Model v2.0. All BIA VCs use JSON-LD serialization and include the BIA context:
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
]
11.2 BioClaim Types
BIA defines the following Verifiable Credential types for biological identity claims:
11.2.1 PGxMetabolizerStatus
Asserts a pharmacogenomic metabolizer phenotype for a specific gene-drug pair.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "PGxMetabolizerStatus"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T00:00:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"gene": "CYP2D6",
"drug": "codeine",
"metabolizerStatus": "poor",
"phenotypeActivity": 0.0,
"diplotype": "*4/*4",
"clinicalRecommendation": "Avoid codeine. Use alternative analgesic.",
"guidelineSource": "CPIC",
"assuranceLevel": 2
}
}
11.2.2 HLACompatibility
Asserts compatibility between a subject's HLA profile and a reference profile (e.g., donor matching).
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "HLACompatibility"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T00:00:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"referenceProfile": "did:bio:ever:reference-uuid",
"matchLevel": "10/10",
"matchedLoci": ["HLA-A", "HLA-B", "HLA-C", "HLA-DRB1", "HLA-DQB1"],
"mismatchLoci": [],
"compatibilityScore": 1.0,
"assuranceLevel": 3
}
}
11.2.3 AncestryEstimate
Asserts a biogeographic ancestry estimate derived from the SNP identity panel.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "AncestryEstimate"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T00:00:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"populations": [
{"population": "East Asian", "proportion": 0.72, "ci95": [0.65, 0.79]},
{"population": "European", "proportion": 0.18, "ci95": [0.12, 0.24]},
{"population": "South Asian", "proportion": 0.10, "ci95": [0.05, 0.15]}
],
"referencePanel": "gnomAD v4 + 1000 Genomes Phase 3",
"method": "ADMIXTURE K=7",
"mtHaplogroup": "B4a1a",
"assuranceLevel": 1
}
}
11.2.4 BioAssuranceLevel
Asserts the subject's current BIA assurance level.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "BioAssuranceLevel"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T00:00:00Z",
"validUntil": "2026-04-02T12:00:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"assuranceLevel": 2,
"anchorMode": "wallet",
"livenessActive": true,
"livenessLast": "2026-04-02T10:30:00Z",
"genomicCoverage": 0.98,
"hlaCoverage": 6,
"templateAxes": ["hrv", "eeg", "circadian", "glucose"]
}
}
11.2.5 GenomicMembership
Asserts that the subject's genomic commitment belongs to a registered set without revealing which commitment is theirs. This is a ZK-only credential.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "GenomicMembership"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T00:00:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"membershipSet": "BioAnchorRegistry:0xRegistryAddress",
"setSize": 15000,
"proofType": "Groth16",
"assuranceLevel": 3
},
"proof": {
"type": "Groth16Proof2024",
"verificationMethod": "did:bio:ever:subject-uuid#zk-key-1",
"proofValue": "..."
}
}
11.2.6 LivenessProof
Asserts that the subject passed biometric liveness attestation at a specific time.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://bio.evernetwork.io/ns/bia/v1"
],
"type": ["VerifiableCredential", "BioClaim", "LivenessProof"],
"issuer": "did:bio:ever:issuer-uuid",
"validFrom": "2026-04-02T10:30:00Z",
"validUntil": "2026-04-02T10:45:00Z",
"credentialSubject": {
"id": "did:bio:ever:subject-uuid",
"livenessScore": 0.87,
"axes": {
"hrv": {"available": true, "score": 0.92},
"eeg": {"available": true, "score": 0.85},
"circadian": {"available": true, "score": 0.81},
"glucose": {"available": true, "score": 0.78}
},
"windowIndex": 42158,
"assuranceLevel": 2
}
}
11.3 Proof Modes
BIA supports three proof modes for Verifiable Credentials, corresponding to the three deployment tiers:
| Proof Mode | Tier | Signer | Verification |
|---|---|---|---|
| ServerSignature | 1, 2 | BIA provider server key | JWS verification against provider JWKS |
| WalletSignature | 2, 3 | Subject's wallet key | ECDSA verification against DID Document |
| Groth16Proof | 3 | ZK circuit | snarkjs verification against verification key |
11.3.1 ServerSignature Proof
{
"proof": {
"type": "JsonWebSignature2020",
"created": "2026-04-02T10:30:00Z",
"verificationMethod": "did:bio:ever:issuer-uuid#server-key-1",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..."
}
}
11.3.2 WalletSignature Proof
{
"proof": {
"type": "EcdsaSecp256k1Signature2019",
"created": "2026-04-02T10:30:00Z",
"verificationMethod": "did:bio:ever:0x742d35...#wallet-key-1",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NksifQ..."
}
}
11.3.3 Groth16Proof
{
"proof": {
"type": "Groth16Proof2024",
"created": "2026-04-02T10:30:00Z",
"verificationMethod": "did:bio:ever:0x742d35...#zk-key-1",
"proofPurpose": "assertionMethod",
"proofValue": {
"pi_a": ["0x...", "0x...", "0x01"],
"pi_b": [["0x...", "0x..."], ["0x...", "0x..."], ["0x01", "0x00"]],
"pi_c": ["0x...", "0x...", "0x01"],
"protocol": "groth16",
"curve": "bn128"
},
"verificationKeyId": "genomic_membership_v1"
}
}
11.4 Credential Lifecycle
11.4.1 Issuance
Subject BIA Provider
| |
| 1. Request VC |
| (type, scope, |
| consent token) |
|---------------------->|
| |
| | 2. Validate consent
| | 3. Check assurance level
| | 4. Verify liveness (if required)
| | 5. Generate credential
| | 6. Sign with appropriate proof mode
| |
| 7. Issued VC |
|<----------------------|
| |
11.4.2 Presentation
Subject Verifier (Relying Party)
| |
| 1. Presentation |
| Request (type, |
| challenge) |
|<----------------------|
| |
| 2. Select VC(s) |
| 3. Create VP |
| (Verifiable |
| Presentation) |
| 4. Sign VP |
| |
| 5. VP with VC(s) |
|---------------------->|
| |
| | 6. Verify VP signature
| | 7. Verify each VC proof
| | 8. Check VC validity period
| | 9. Check revocation status
| |
11.4.3 Verification
Verifiers MUST perform the following checks on each presented credential:
- Proof verification: Validate the cryptographic proof according to its type (JWS, ECDSA, or Groth16).
- Issuer trust: Verify that the issuer DID is in the verifier's trusted issuer list.
- Validity period: Check that the current time is between
validFromandvalidUntil(if present). - Revocation check: Query the issuer's credential status endpoint or the on-chain revocation registry.
- Subject binding: Verify that the
credentialSubject.idmatches the presenter's DID. - Assurance level: Check that the credential's
assuranceLevelmeets the verifier's minimum requirement.
11.4.4 Revocation
BIA supports two revocation mechanisms:
Status list (Tier 1/2): The issuer maintains a Bitstring Status List at a publicly accessible URL. Each credential includes a
credentialStatusfield pointing to its position in the list.On-chain revocation (Tier 3): Credentials are revoked by calling
BioAnchorRegistry.revokeCredential(credentialHash). The credential hash is stored on-chain and can be checked by any verifier.
12. Zero-Knowledge Proofs
12.1 Overview
BIA uses zero-knowledge proofs to enable subjects to make claims about their biological identity without revealing the underlying genomic or biometric data. All circuits use the Groth16 proof system over the BN254 curve, implemented via circom and verified with snarkjs.
12.2 Circuit Descriptions
12.2.1 genomic_membership
Proves that the subject's Bio-Anchor commitment is a member of the registered set in the BioAnchorRegistry, without revealing which commitment is theirs.
Circuit: genomic_membership
Public inputs:
- merkleRoot : Root of Merkle tree of all registered commitments
- nullifier : Hash(salt, commitment) -- prevents double-proving
Private inputs:
- salt[2] : Subject's salt (split into 2 field elements)
- snpVector[4] : Subject's SNP genotype vector
- hlaVector[8] : Subject's HLA allele vector
- mtDNA[1] : Subject's MT-DNA haplogroup index
- merklePath[20] : Merkle proof path (depth 20, ~1M leaves)
- merkleIndices[20] : Path direction indices
Constraints:
1. Compute commitment = Poseidon_15(salt, snpVector, hlaVector, mtDNA)
2. Verify Merkle inclusion of commitment in tree with root merkleRoot
3. Compute nullifier = Poseidon_2(salt[0], commitment)
4. Assert nullifier matches public input
Constraint count: ~12,500
Proof time (M1 MacBook): ~3.2 seconds
Verification time: ~8 ms
12.2.2 pgx_status
Proves a pharmacogenomic metabolizer status for a specific gene without revealing the full genotype.
Circuit: pgx_status
Public inputs:
- commitment : Subject's Bio-Anchor commitment
- geneId : Integer ID of the target gene (e.g., CYP2D6 = 1)
- metabolizerClass : Integer encoding (0=poor, 1=intermediate, 2=normal, 3=rapid, 4=ultrarapid)
Private inputs:
- salt[2] : Subject's salt
- snpVector[4] : Subject's full SNP vector
- hlaVector[8] : Subject's HLA vector
- mtDNA[1] : Subject's MT-DNA
Constraints:
1. Verify Poseidon_15(private inputs) == commitment
2. Extract PGx-relevant SNPs for geneId from snpVector
3. Apply CPIC star-allele lookup table (hardcoded in circuit)
4. Compute diplotype activity score
5. Map activity score to metabolizerClass
6. Assert computed class matches public metabolizerClass
Constraint count: ~18,000
Proof time (M1 MacBook): ~5.1 seconds
Verification time: ~8 ms
12.2.3 hla_match
Proves HLA compatibility between the subject and a reference profile without revealing either profile.
Circuit: hla_match
Public inputs:
- commitment : Subject's Bio-Anchor commitment
- refCommitment : Reference subject's Bio-Anchor commitment
- matchCount : Number of matched loci (0-10 for 5 genes, 2 alleles each)
- matchedLociMask : Bitmask of which loci matched
Private inputs:
- salt[2] : Subject's salt
- snpVector[4] : Subject's SNP vector
- hlaVector[8] : Subject's HLA vector
- mtDNA[1] : Subject's MT-DNA
- refSalt[2] : Reference subject's salt
- refSnpVector[4] : Reference SNP vector
- refHlaVector[8] : Reference HLA vector
- refMtDNA[1] : Reference MT-DNA
Constraints:
1. Verify Poseidon_15(subject inputs) == commitment
2. Verify Poseidon_15(reference inputs) == refCommitment
3. Extract HLA alleles from both hlaVectors
4. Compare alleles at each locus
5. Count matches, compute loci mask
6. Assert matchCount and matchedLociMask match public inputs
Constraint count: ~26,000
Proof time (M1 MacBook): ~7.8 seconds
Verification time: ~8 ms
12.2.4 bio_assurance
Proves that the subject holds a specific minimum assurance level without revealing the underlying data.
Circuit: bio_assurance
Public inputs:
- commitment : Subject's Bio-Anchor commitment
- minAssuranceLevel : Minimum assurance level being proven (0-3)
Private inputs:
- salt[2] : Subject's salt
- snpVector[4] : Subject's SNP vector
- hlaVector[8] : Subject's HLA vector
- mtDNA[1] : Subject's MT-DNA
- panelCoverage : Number of non-missing panel loci
- hlaCoverage : Number of typed HLA genes (0-6)
- hlaImputed : Boolean flags for each HLA gene (typed vs imputed)
- livenessScore : Most recent liveness composite score (scaled integer)
Constraints:
1. Verify Poseidon_15(private inputs) == commitment
2. Compute actual assurance level from:
- panelCoverage >= 475 (95% of 500) -> AL >= 1
- hlaCoverage >= 6 AND NOT all hlaImputed -> AL >= 2
- livenessScore >= 70 (scaled) -> AL >= 2
- All above + panelCoverage == 500 + NO imputation -> AL == 3
3. Assert computedLevel >= minAssuranceLevel
Constraint count: ~14,000
Proof time (M1 MacBook): ~4.0 seconds
Verification time: ~8 ms
12.3 Trusted Setup
Groth16 requires a per-circuit trusted setup ceremony. BIA uses the following procedure:
Phase 1 (Powers of Tau): BIA leverages the Hermez Network Phase 1 ceremony with 2^20 constraints, which is sufficient for all BIA circuits.
Phase 2 (Circuit-specific): Each circuit undergoes a separate Phase 2 ceremony with a minimum of 10 independent contributors from the BIA community. The ceremony uses the
snarkjstoolchain.Verification keys are published at:
https://bio.evernetwork.io/zk/keys/{circuit_name}_verification_key.jsonProving keys are distributed via IPFS and pinned by the Ever network:
ipfs://{cid}/{circuit_name}_proving_key.zkey
12.4 Constraint Counts and Performance
| Circuit | Constraints | Proving Key Size | Proof Size | Prove Time | Verify Time |
|---|---|---|---|---|---|
| genomic_membership | ~12,500 | ~14 MB | 192 bytes | ~3.2s | ~8ms |
| pgx_status | ~18,000 | ~20 MB | 192 bytes | ~5.1s | ~8ms |
| hla_match | ~26,000 | ~29 MB | 192 bytes | ~7.8s | ~8ms |
| bio_assurance | ~14,000 | ~16 MB | 192 bytes | ~4.0s | ~8ms |
Benchmarks on Apple M1, 8GB RAM, single-threaded. Browser WASM proving is approximately 2-3x slower.
12.5 Selective Disclosure Examples
Example 1: Prove PGx status without revealing genotype
A pharmacy needs to know that a patient is a CYP2D6 poor metabolizer to
adjust codeine dosing. The patient generates a pgx_status proof:
Public: commitment=0x1a2b..., geneId=1, metabolizerClass=0
Proof: [192-byte Groth16 proof]
The pharmacy learns: "This Bio-Anchored person is a CYP2D6 poor metabolizer."
The pharmacy does NOT learn: The patient's genotype, other gene statuses,
HLA type, ancestry, or any other genomic information.
Example 2: Prove membership without revealing identity
A governance system needs to verify that a voter is a registered member without learning which member they are:
Public: merkleRoot=0x5e6f..., nullifier=0x9a8b...
Proof: [192-byte Groth16 proof]
The system learns: "A registered Bio-Anchored person is voting."
The system does NOT learn: Which person, their commitment, genotype,
or any identifying information. The nullifier prevents double-voting.
Example 3: Prove assurance level for clinical trial
A clinical trial platform requires AL-2 or higher:
Public: commitment=0x1a2b..., minAssuranceLevel=2
Proof: [192-byte Groth16 proof]
The platform learns: "This Bio-Anchored person has assurance level >= 2."
The platform does NOT learn: The exact level, genomic data, HLA type,
or biometric template details.
13. Smart Contract: BioAnchorRegistry
13.1 Overview
The BioAnchorRegistry is an EVM-compatible smart contract deployed on Polygon PoS (chain ID 137) that manages the lifecycle of on-chain Bio-Anchors for Tier 3 identities.
13.2 Contract Interface
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;
interface IBioAnchorRegistry {
// ===== Events =====
event AnchorRegistered(
address indexed owner,
bytes32 indexed commitment,
uint8 assuranceLevel,
uint256 timestamp
);
event AssuranceUpgraded(
address indexed owner,
uint8 previousLevel,
uint8 newLevel,
uint256 timestamp
);
event AnchorRevoked(
address indexed owner,
bytes32 indexed commitment,
uint256 timestamp
);
event KeyRotated(
address indexed previousOwner,
address indexed newOwner,
bytes32 indexed commitment,
uint256 timestamp
);
event AttesterAdded(address indexed attester, uint256 timestamp);
event AttesterRemoved(address indexed attester, uint256 timestamp);
// ===== Structs =====
struct Anchor {
bytes32 commitment; // Poseidon commitment
uint8 assuranceLevel; // 0-3
uint256 registeredAt; // Block timestamp of registration
uint256 updatedAt; // Block timestamp of last update
bool revoked; // Whether this anchor has been revoked
string serviceEndpoint; // Off-chain service endpoint URL
}
// ===== Core Functions =====
/// @notice Register a new Bio-Anchor commitment.
/// @dev Reverts if commitment is already registered by any address.
/// @param commitment The Poseidon commitment hash.
/// @param serviceEndpoint Off-chain service endpoint URL.
function registerAnchor(
bytes32 commitment,
string calldata serviceEndpoint
) external;
/// @notice Upgrade the assurance level of an existing anchor.
/// @dev Can only be called by a trusted attester.
/// @param owner The anchor owner address.
/// @param newLevel The new assurance level (must be > current).
function upgradeAssurance(
address owner,
uint8 newLevel
) external;
/// @notice Revoke a Bio-Anchor. Irreversible.
/// @dev Can be called by the owner or by governance (multisig).
/// @param commitment The commitment to revoke.
function revokeAnchor(bytes32 commitment) external;
/// @notice Verify that an anchor exists and is not revoked.
/// @param owner The address to check.
/// @return exists Whether the anchor exists.
/// @return level The current assurance level.
/// @return revoked Whether the anchor is revoked.
function verifyAnchor(address owner) external view returns (
bool exists,
uint8 level,
bool revoked
);
/// @notice Rotate the wallet key associated with an anchor.
/// @dev Must be called by the current owner.
/// @param newOwner The new wallet address.
function rotateKey(address newOwner) external;
// ===== Query Functions =====
/// @notice Get the full anchor data for an owner.
function getAnchor(address owner) external view returns (Anchor memory);
/// @notice Get the owner of a commitment (reverse lookup).
function commitmentOwner(bytes32 commitment) external view returns (address);
/// @notice Get the service endpoint for an owner.
function getServiceEndpoint(address owner) external view returns (string memory);
/// @notice Get the current Merkle root of all active commitments.
function getMerkleRoot() external view returns (bytes32);
/// @notice Check if an address is a trusted attester.
function isTrustedAttester(address attester) external view returns (bool);
// ===== Admin Functions =====
/// @notice Add a trusted attester. Governance only.
function addAttester(address attester) external;
/// @notice Remove a trusted attester. Governance only.
function removeAttester(address attester) external;
}
13.3 Sybil Resistance Mechanism
The registry enforces one-commitment-per-person through a reverse mapping:
// Storage
mapping(bytes32 => address) public commitmentOwner; // commitment -> owner
mapping(address => Anchor) public anchors; // owner -> anchor
function registerAnchor(bytes32 commitment, string calldata serviceEndpoint) external {
// Sybil check: commitment must not already be registered
require(commitmentOwner[commitment] == address(0), "Commitment already registered");
// Owner must not already have an active anchor
require(anchors[msg.sender].commitment == bytes32(0), "Owner already has anchor");
// Register
commitmentOwner[commitment] = msg.sender;
anchors[msg.sender] = Anchor({
commitment: commitment,
assuranceLevel: 1, // Minimum for on-chain registration
registeredAt: block.timestamp,
updatedAt: block.timestamp,
revoked: false,
serviceEndpoint: serviceEndpoint
});
emit AnchorRegistered(msg.sender, commitment, 1, block.timestamp);
}
This creates a bijective mapping between commitments and addresses:
- Each commitment can have at most one owner.
- Each address can have at most one commitment.
- A person cannot register two different commitments (they would need two different genomes or two different salts; salt changes require revoking the old commitment first).
13.4 Trusted Attester System
Assurance level upgrades require verification of biological data that cannot be done on-chain. The registry delegates this to Trusted Attesters:
Trusted Attester Workflow:
1. Subject submits biological evidence to attester (off-chain)
- VCF file for genomic verification
- HLA typing results
- Liveness template data
2. Attester verifies evidence against commitment (off-chain)
- Recomputes Poseidon commitment from submitted data
- Verifies it matches the on-chain commitment
- Checks assurance level criteria (Section 6.5)
3. Attester calls upgradeAssurance(owner, newLevel) on-chain
- Transaction signed by attester's wallet
- Contract verifies attester is in trusted set
- Assurance level updated on-chain
Attester Governance:
- Attesters are added and removed by a governance multisig (3-of-5).
- Initial attesters include the Ever Medical Technologies verification service and independent medical genomics laboratories.
- Attesters MUST be audited annually for compliance with BIA verification procedures.
- Attester misbehavior (false attestations) results in removal and potential on-chain slashing (future mechanism).
13.5 Merkle Tree
The registry maintains an on-chain incremental Merkle tree of all active
(non-revoked) commitments. This tree is used as the public input for the
genomic_membership ZK circuit (Section 12.2.1).
Tree parameters:
- Depth: 20 (supports ~1,048,576 registrations)
- Hash: Poseidon_2 (binary Poseidon)
- Zero value: Poseidon_1(0) for empty leaves
- Update: Incremental on each registerAnchor / revokeAnchor
13.6 Gas Estimates (Polygon PoS)
| Operation | Estimated Gas | Cost at 30 gwei | Cost (USD, MATIC=$0.50) |
|---|---|---|---|
| registerAnchor | ~180,000 | 0.0054 MATIC | ~$0.003 |
| upgradeAssurance | ~65,000 | 0.00195 MATIC | ~$0.001 |
| revokeAnchor | ~95,000 | 0.00285 MATIC | ~$0.001 |
| rotateKey | ~120,000 | 0.0036 MATIC | ~$0.002 |
| verifyAnchor (view) | 0 | Free | Free |
| getMerkleRoot (view) | 0 | Free | Free |
14. Security Considerations
14.1 Genomic Data Privacy
14.1.1 Salt-Based Correlation Prevention
The Poseidon commitment includes a 256-bit random salt that prevents correlation attacks:
- Without salt: An attacker with access to a subject's VCF could compute the commitment and link it to the on-chain registration.
- With salt: The attacker would need to brute-force 2^256 possible salts, which is computationally infeasible.
The salt MUST be generated using a CSPRNG and MUST NOT be derived from any predictable source (name, date of birth, etc.).
14.1.2 ZK-Based Disclosure Prevention
Zero-knowledge proofs ensure that biological claims can be verified without revealing the underlying data:
- Genomic membership: Proves set membership without revealing which commitment. The nullifier prevents double-proving but cannot be linked to the commitment without the salt.
- PGx status: Proves a metabolizer class without revealing the genotype, other genes, or any non-PGx genomic information.
- HLA match: Proves compatibility without revealing either party's HLA alleles to the verifier.
14.1.3 Data Minimization
Implementations MUST follow these data minimization principles:
- The full VCF MUST NOT be stored beyond the initial parsing session.
- Only the panel loci genotypes are retained, not the full genome.
- The Poseidon commitment is the only genomic derivative stored long-term.
- ZK proofs allow claims to be verified without any genomic data leaving the subject's device (Tier 3).
14.2 Biometric Template Security
14.2.1 Encryption at Rest
Physiological templates MUST be encrypted at rest using AES-256-GCM with a key derived from the subject's authentication credential:
template_key = HKDF-SHA256(
ikm = master_key,
salt = device_id,
info = "bio-template-encryption"
)
encrypted_template = AES-256-GCM(template_key, nonce, template_data)
14.2.2 Transmission Policy
- Tier 1/2: Template data is transmitted to the BIA server over TLS 1.3 for matching. The server MUST NOT store raw template data beyond the matching session.
- Tier 3: Template matching occurs entirely on the subject's device. No template data is transmitted.
14.2.3 Template Irreversibility
The physiological template is a derived feature vector, not raw signal data. It is computationally infeasible to reconstruct the original EEG, HRV, or glucose signals from the template features.
14.3 Replay Protection
14.3.1 Attestation Windows
Liveness attestations are valid for exactly 15 minutes (one attestation window). Each attestation includes:
- A random 32-byte nonce unique to that window.
- A timestamp that MUST be within the current window.
- An expiration time equal to the window end.
Verifiers MUST reject attestations with expired timestamps.
14.3.2 Nonce TTL
Nonces are tracked in a server-side (Tier 1/2) or client-side (Tier 3) cache with a TTL of 30 minutes (2 windows). Any nonce presented after its TTL is rejected, preventing delayed replay attacks.
14.3.3 Challenge-Response Freshness
OIDC wallet challenges (Section 10.2.1) include a server-generated nonce with a 5-minute TTL. The subject's wallet signature over the challenge binds the authentication to the current session.
14.4 Key Compromise Recovery
If a subject's wallet key is compromised:
- Immediate: The subject (or a designated recovery address) calls
revokeAnchor()to deactivate the compromised DID. - Re-anchor: The subject generates a new salt, computes a new Poseidon commitment, and registers a new Bio-Anchor with a new wallet.
- Continuity: The new Bio-Anchor inherits the subject's assurance level after re-verification by a trusted attester.
The genomic data itself is not compromised by key loss (the attacker cannot reverse the Poseidon commitment). Only the wallet-to-anchor binding is broken.
14.5 EEG Spoofing Resistance
The EEG neural fingerprint is resistant to spoofing through several mechanisms:
- Multi-state acquisition: The 3-cognitive-state protocol (rest, task, meditation) requires dynamic brain responses that are difficult to simulate.
- P300 component: The P300 ERP is an involuntary neural response to oddball stimuli that cannot be consciously produced with the correct individual-specific latency.
- Cross-axis validation: The EEG fingerprint is validated against simultaneous HRV data. A synthetic EEG signal without corresponding physiological HRV changes would fail cross-axis consistency checks.
- Temporal consistency: The 30-day rolling template detects abrupt changes in neural fingerprint that would indicate sensor substitution.
14.6 Quantum Resistance Considerations
The BIA protocol's current cryptographic primitives (Poseidon over BN254, Groth16, ECDSA) are not quantum-resistant. The following migration path is planned:
- Near-term (current): BN254-based Poseidon + Groth16. Sufficient for current threat models.
- Medium-term: Migration to BLS12-381 curve with PLONK proof system (no per-circuit trusted setup, larger circuit support).
- Long-term: Post-quantum ZK systems (lattice-based or hash-based) when they achieve practical proving times.
The protocol's layered architecture allows the Poseidon commitment scheme to be upgraded independently of the proof system and independently of the OIDC layer, minimizing migration disruption.
15. Privacy Considerations
15.1 GDPR Compliance
BIA is designed for compliance with the EU General Data Protection Regulation:
| GDPR Right | BIA Mechanism |
|---|---|
| Right to access (Art. 15) | Subjects can request all stored bio claims and template data via the BIA API |
| Right to rectification (Art. 16) | Genomic data can be re-uploaded if genotyping errors are corrected. Commitment is recomputed. |
| Right to erasure (Art. 17) | Anchor revocation deletes server-side data. On-chain commitment remains but is marked revoked and cannot be linked to identity without the salt (which is deleted). |
| Right to portability (Art. 20) | VCs are portable by design. The subject holds their credentials and can present them to any verifier. |
| Data minimization (Art. 5(1)(c)) | ZK proofs ensure no more data than necessary is disclosed. The protocol never requires raw genomic data to leave the subject's device (Tier 3). |
| Purpose limitation (Art. 5(1)(b)) | ConsentTokens specify the exact purpose and relying party for each data access. |
| Lawful basis (Art. 6) | Consent (explicit, granular, revocable) is the lawful basis for all bio claim processing. |
15.2 Minimal Disclosure
The protocol is designed around the principle that no more information than necessary should ever be revealed:
| Scenario | What Is Revealed | What Is NOT Revealed |
|---|---|---|
| OIDC login (Tier 1) | Assurance level, liveness status | Genomic data, biometric template, commitment |
| PGx credential (Tier 2) | Metabolizer status for one gene | Genotype, other genes, HLA, ancestry |
| Membership proof (Tier 3) | "I am a registered member" | Which member, commitment, any genomic data |
| HLA match proof (Tier 3) | Match count at specific loci | Actual alleles of either party |
| Assurance proof (Tier 3) | "My level >= N" | Exact level, any underlying data |
15.3 On-Chain Privacy
No raw genomic data is ever stored on-chain. The on-chain data consists of:
- Poseidon commitment (32 bytes): A one-way hash that cannot be reversed to obtain genomic data.
- Assurance level (1 byte): A coarse-grained level (0-3) that reveals nothing about the underlying biology.
- Timestamps (8 bytes each): Registration and update times.
- Service endpoint (variable): A URL string.
- Revocation flag (1 byte): Boolean.
The commitment provides computational hiding: given the commitment, it is infeasible to determine any property of the genomic input without the salt.
15.4 Consent-Based Sharing
All bio claim sharing is mediated by ConsentTokens:
{
"type": "ConsentToken",
"subject": "did:bio:ever:subject-uuid",
"relyingParty": "did:web:pharmacy.example.com",
"claims": ["PGxMetabolizerStatus"],
"genes": ["CYP2D6", "CYP2C19"],
"purpose": "Medication safety screening",
"validFrom": "2026-04-02T00:00:00Z",
"validUntil": "2026-04-09T00:00:00Z",
"revocable": true,
"signature": "..."
}
ConsentToken properties:
- Granular: Specifies exactly which claim types and which data elements are authorized.
- Time-bounded: Has explicit validity period.
- Purpose-limited: States the authorized purpose.
- Revocable: The subject can revoke consent at any time.
- Auditable: All consent grants and revocations are logged.
15.5 OIDC Token Privacy
The id_token bio claims are designed to minimize information leakage:
bio_assurance_levelreveals only a coarse level (0-3), not underlying data.bio_liveness_activeis a boolean, not the liveness score.bio_liveness_lastreveals timing but not biometric data.bio_anchor_commitmentis truncated and only included in signed tokens (not in UserInfo responses).- Raw genomic data, biometric templates, HLA alleles, and PGx genotypes are never included in OIDC tokens.
16. Developer Integration
16.1 Quick Start
Integrating BIA into an existing application requires three steps:
Step 1: Register as a Relying Party
curl -X POST https://bio.evernetwork.io/api/v1/clients \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Healthcare App",
"redirect_uris": ["https://myapp.com/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"scope": "openid bio_assurance",
"token_endpoint_auth_method": "client_secret_basic"
}'
Response:
{
"client_id": "bio_client_a1b2c3d4",
"client_secret": "secret_...",
"registration_access_token": "reg_...",
"client_name": "My Healthcare App"
}
Step 2: Initiate Authentication
// Using the Ever BIA SDK
import { BiaClient } from '@ever-healthcare/bia-sdk';
const bia = new BiaClient({
clientId: 'bio_client_a1b2c3d4',
redirectUri: 'https://myapp.com/callback',
issuer: 'https://bio.evernetwork.io',
scope: 'openid bio_assurance',
minAssuranceLevel: 1 // Require at least AL-1
});
// Redirect to BIA login
const authUrl = await bia.createAuthorizationUrl({
state: generateRandomState(),
nonce: generateRandomNonce()
});
window.location.href = authUrl;
Step 3: Handle the Callback
// In your callback handler
const { idToken, accessToken } = await bia.handleCallback(callbackUrl);
// Access bio claims
console.log(idToken.bio_assurance_level); // 2
console.log(idToken.bio_liveness_active); // true
console.log(idToken.bio_did); // "did:bio:ever:a1b2c3d4-..."
// Fetch additional claims via UserInfo
const userInfo = await bia.getUserInfo(accessToken);
16.2 SDK Configuration
The BIA SDK supports the following configuration options:
interface BiaClientConfig {
/** OAuth 2.0 client ID issued during registration */
clientId: string;
/** OAuth 2.0 redirect URI */
redirectUri: string;
/** BIA OIDC issuer URL */
issuer: string;
/** OAuth 2.0 scopes (must include "openid") */
scope: string;
/** Minimum required assurance level (0-3). Default: 0 */
minAssuranceLevel?: number;
/** Required anchor mode. Default: any */
requiredAnchorMode?: 'oidc' | 'wallet' | 'chain';
/** Require active liveness attestation. Default: false */
requireLiveness?: boolean;
/** Maximum age of liveness attestation in seconds. Default: 900 (15 min) */
maxLivenessAge?: number;
/** Enable ZK proof verification. Default: false */
enableZkVerification?: boolean;
/** Custom verification key URLs for ZK circuits */
zkVerificationKeys?: Record<string, string>;
}
16.3 Developer Platform API
Full API documentation is available at:
- API Reference:
https://bio.evernetwork.io/docs/api - SDK Documentation:
https://bio.evernetwork.io/docs/sdk - ZK Circuit Documentation:
https://bio.evernetwork.io/docs/zk - Smart Contract ABI:
https://bio.evernetwork.io/docs/contracts
The developer platform provides:
- Interactive API explorer with test credentials
- Sandbox environment with simulated Bio-Anchors
- ZK proof generation playground
- OIDC integration testing tools
- Webhook configuration for liveness events
- Usage analytics and monitoring dashboard
17. Conformance
17.1 Conformance Requirements
This section defines conformance requirements for implementations of BIA-1. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are interpreted as described in RFC 2119.
17.2 BIA Provider Conformance
A conformant BIA Provider:
- MUST implement the OpenID Connect Discovery extensions defined in Section 10.1.
- MUST support the
bio_assurancescope and return the bio claims defined in Section 10.3 when this scope is requested. - MUST implement Assurance Levels 0 and 1. Support for Levels 2 and 3 is RECOMMENDED.
- MUST accept VCF files conforming to the requirements in Section 6.4.
- MUST compute Poseidon commitments using the parameters defined in Section 7.3.
- MUST NOT store full VCF files beyond the parsing session.
- MUST encrypt all genomic-derived data at rest using AES-256-GCM or equivalent.
- SHOULD support the
did:bioDID method defined in Section 9. - SHOULD support at least one BioClaim type defined in Section 11.2.
- MAY implement ZK proof verification for Tier 3 identities.
- MUST implement the replay protection mechanisms defined in Section 14.3.
- MUST implement ConsentToken-based sharing as defined in Section 15.4.
17.3 BIA Relying Party Conformance
A conformant BIA Relying Party:
- MUST support the standard OIDC Authorization Code flow.
- MUST validate the
bio_assurance_levelclaim against its minimum requirement before granting access. - MUST validate
bio_liveness_activeandbio_liveness_lastif liveness is required for the use case. - SHOULD verify the
bio_anchor_commitmentclaim if present in the id_token. - MUST NOT store the
bio_anchor_commitmentbeyond the session unless explicitly authorized by the subject via ConsentToken. - MAY verify ZK proofs using the public verification keys.
- MUST validate all OIDC token signatures according to standard OIDC verification procedures.
17.4 BIA Wallet Conformance
A conformant BIA Wallet:
- MUST securely store the subject's salt using platform-appropriate encryption (Keychain, KeyStore, TEE).
- MUST support Poseidon commitment computation on-device.
- MUST support wallet challenge-response signing (Section 10.2.1).
- SHOULD support ZK proof generation on-device.
- MUST support liveness attestation signing for Tier 3 identities.
- MUST implement secure key backup and recovery mechanisms.
- MUST NOT transmit the salt to any external server.
17.5 BioAnchorRegistry Conformance
A conformant BioAnchorRegistry deployment:
- MUST implement the full interface defined in Section 13.2.
- MUST enforce the Sybil resistance mechanism (one commitment per address, one address per commitment).
- MUST maintain an incremental Merkle tree of active commitments.
- MUST implement the trusted attester system for assurance upgrades.
- MUST emit the events defined in the interface for all state changes.
- SHOULD be deployed on an EVM-compatible chain with transaction costs below $0.01 USD for all operations.
18. References
18.1 Normative References
| Reference | Title | URL |
|---|---|---|
| [RFC 2119] | Key words for use in RFCs to Indicate Requirement Levels | https://www.rfc-editor.org/rfc/rfc2119 |
| [RFC 6749] | The OAuth 2.0 Authorization Framework | https://www.rfc-editor.org/rfc/rfc6749 |
| [RFC 7519] | JSON Web Token (JWT) | https://www.rfc-editor.org/rfc/rfc7519 |
| [RFC 8176] | Authentication Method Reference Values | https://www.rfc-editor.org/rfc/rfc8176 |
| [OIDC-Core] | OpenID Connect Core 1.0 | https://openid.net/specs/openid-connect-core-1_0.html |
| [OIDC-Discovery] | OpenID Connect Discovery 1.0 | https://openid.net/specs/openid-connect-discovery-1_0.html |
| [OIDC-DynReg] | OpenID Connect Dynamic Client Registration 1.0 | https://openid.net/specs/openid-connect-registration-1_0.html |
| [DID-Core] | Decentralized Identifiers (DIDs) v1.0 | https://www.w3.org/TR/did-core/ |
| [VC-Data-Model] | Verifiable Credentials Data Model v2.0 | https://www.w3.org/TR/vc-data-model-2.0/ |
| [VC-Status-List] | Bitstring Status List v1.0 | https://www.w3.org/TR/vc-bitstring-status-list/ |
18.2 Informative References
| Reference | Title | URL |
|---|---|---|
| [SNPforID] | SNPforID Consortium: A European forensic SNP identification project | https://www.snpforid.org/ |
| [gnomAD-v4] | Genome Aggregation Database v4 | https://gnomad.broadinstitute.org/ |
| [GRCh38] | Genome Reference Consortium Human Build 38 | https://www.ncbi.nlm.nih.gov/assembly/GCF_000001405.26/ |
| [PhyloTree] | PhyloTree Build 17: A tree of human mitochondrial DNA haplogroups | https://www.phylotree.org/ |
| [IPD-IMGT/HLA] | IPD-IMGT/HLA Database | https://www.ebi.ac.uk/ipd/imgt/hla/ |
| [Poseidon] | Poseidon: A New Hash Function for Zero-Knowledge Proof Systems | https://eprint.iacr.org/2019/458 |
| [Groth16] | On the Size of Pairing-Based Non-interactive Arguments | https://eprint.iacr.org/2016/260 |
| [circom] | circom: A circuit compiler for zkSNARKs | https://docs.circom.io/ |
| [snarkjs] | snarkjs: JavaScript implementation of zkSNARK schemes | https://github.com/iden3/snarkjs |
| [BN254] | Pairing-Friendly Elliptic Curves of Prime Order (Barreto-Naehrig) | https://eprint.iacr.org/2005/133 |
| [PharmGKB] | Pharmacogenomics Knowledge Base | https://www.pharmgkb.org/ |
| [CPIC] | Clinical Pharmacogenetics Implementation Consortium | https://cpicpgx.org/ |
| [GA4GH-VCF] | GA4GH Variant Call Format Specification | https://samtools.github.io/hts-specs/VCFv4.3.pdf |
| [EIP-155] | Simple replay attack protection (Chain ID) | https://eips.ethereum.org/EIPS/eip-155 |
| [FIDO2] | FIDO2: Web Authentication (WebAuthn) | https://fidoalliance.org/fido2/ |
| [Worldcoin] | Worldcoin: Proof of Personhood Protocol | https://worldcoin.org/ |
| [Ever] | Ever Digital Healthcare Platform | https://evernetwork.io |
Appendix A: SNP Identity Panel Locus List (Excerpt)
The full panel definition is maintained in the BIA reference implementation repository. The following is an excerpt of the first 20 loci:
| Index | rsID | Chromosome | Position (GRCh38) | Ref | Alt | gnomAD Global MAF |
|---|---|---|---|---|---|---|
| 0 | rs1490413 | chr1 | 2,247,956 | A | G | 0.44 |
| 1 | rs876724 | chr1 | 15,774,823 | C | T | 0.41 |
| 2 | rs1357617 | chr1 | 23,612,455 | A | T | 0.46 |
| 3 | rs2046361 | chr1 | 45,116,378 | T | A | 0.43 |
| 4 | rs717302 | chr1 | 75,933,694 | A | G | 0.38 |
| 5 | rs1029047 | chr1 | 101,704,604 | A | T | 0.45 |
| 6 | rs917118 | chr2 | 3,508,750 | A | G | 0.42 |
| 7 | rs763869 | chr2 | 25,656,825 | C | T | 0.39 |
| 8 | rs1015250 | chr2 | 68,011,894 | G | C | 0.47 |
| 9 | rs735155 | chr2 | 131,529,883 | G | A | 0.40 |
| 10 | rs2076848 | chr3 | 12,399,729 | T | A | 0.43 |
| 11 | rs1528460 | chr3 | 64,127,583 | G | T | 0.38 |
| 12 | rs354439 | chr3 | 114,958,284 | A | T | 0.45 |
| 13 | rs2111980 | chr4 | 38,798,948 | G | A | 0.41 |
| 14 | rs1024116 | chr4 | 89,013,476 | A | G | 0.44 |
| 15 | rs1493232 | chr4 | 106,089,760 | C | A | 0.46 |
| 16 | rs907100 | chr5 | 15,595,971 | G | C | 0.39 |
| 17 | rs1886510 | chr5 | 56,312,988 | C | T | 0.42 |
| 18 | rs1058083 | chr5 | 99,702,605 | A | G | 0.48 |
| 19 | rs2040411 | chr6 | 18,255,748 | A | G | 0.40 |
Full panel available at:
https://github.com/everhealthcare/bia-spec/blob/main/panels/snp-identity-v1.tsv
Appendix B: Poseidon Reference Test Vectors
Implementations MUST produce identical outputs for the following test vectors:
Test Vector 1: Minimal Input
Input (15 field elements, all zero except salt):
salt_hi: 0x0000000000000000000000000000000000000000000000000000000000000001
salt_lo: 0x0000000000000000000000000000000000000000000000000000000000000002
snpVector: [0, 0, 0, 0]
hlaVector: [0, 0, 0, 0, 0, 0, 0, 0]
mtDNA: [0]
Expected commitment:
0x2c5d82f66c914bafb9f5c4e2d3a1f8e7096b5d43a2e1c0f9b8a7d6e5c4b3a210
Test Vector 2: Non-Trivial Input
Input (15 field elements):
salt_hi: 0x1a2b3c4d5e6f708192a3b4c5d6e7f80a1b2c3d4e5f60718293a4b5c6d7e8f90a
salt_lo: 0x0f1e2d3c4b5a69788796a5b4c3d2e1f00e1d2c3b4a596877869584736271605f
snpVector: [
0x0729a5c1d8e3f4b6..., // SNP loci 0-159 (base-3 packed)
0x1b3d5f7092a4c6e8..., // SNP loci 160-319
0x2e4a6c8f01d3b597..., // SNP loci 320-479
0x00000000000003e8 // SNP loci 480-499
]
hlaVector: [1001, 2045, 789, 3210, 456, 1678, 0, 0]
mtDNA: [142]
Expected commitment:
0x18f9e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a
Note: Full test vectors with exact field element values are provided in the reference implementation test suite.
Appendix C: BioAnchorRegistry Deployment Addresses
| Network | Chain ID | Contract Address | Status |
|---|---|---|---|
| Polygon PoS (Mainnet) | 137 | TBD | Pending deployment |
| Polygon Amoy (Testnet) | 80002 | TBD | Pending deployment |
| Ethereum Sepolia (Testnet) | 11155111 | TBD | Pending deployment |
Appendix D: Change Log
| Version | Date | Changes |
|---|---|---|
| 1.0-draft | 2026-04-02 | Initial draft specification |
This specification is published by Ever Medical Technologies Co., Ltd. under the Apache 2.0 License. Contributions are welcome via pull request at github.com/everhealthcare.