sable · secure attested biometric library for edge

Prove who you are without revealing your biometrics.

Biometric identity today trades privacy for convenience: a central database, a cloud MPC service, or a proprietary scanner. sable does neither. A Halo2 zero-knowledge proof — generated in ~250ms on a phone — shows a verifier your live face matches the enrolled template, revealing nothing else. Offline. No special hardware.

Halo2 ZK · Pedersen commit · Poseidon hash BBS+ selective disclosure · offline NFC/BLE Android · iOS · Apache 2.0 · 519 tests passing

Every biometric system today trades something you shouldn't have to trade.

A face is not a password — it can't be rotated. Yet the industry ships architectures that centralise, cache, or transmit the one credential you can never replace. Breaches are irrevocable. Trust is assumed. The privacy-preserving alternatives rely on cloud MPC or blockchain.

What the alternatives trade

Centralised databases — a single breach exposes millions of irrevocable biometric records.

Cloud MPC — templates are sharded across nodes, but you still trust the operators and need always-on internet.

Blockchain ID — solves uniqueness, not privacy; requires gas fees and on-chain verification.

Hardware systems — iris scanners and secure enclaves lock deployment to controlled environments.

What sable gives up nothing on

Biometrics never leave the device — enrolment produces a Pedersen commitment; the template stays on the phone.

Real zero-knowledge proofs over the biometric data itself — not statistical matching on encrypted fragments.

Offline verification via NFC or BLE — no cloud, no blockchain, no internet dependency.

Any smartphone camera works — screen-flash liveness detection prevents photo-replay without special hardware.

Five steps from a face to a proof a verifier can check.

Enrol, authenticate, prove, verify, disclose. Click through a real sable flow.

01
Enrol
Face captured; Pedersen commitment stored on device.
02
Liveness check
Screen-flash reflectance defeats photo & screen replay.
03
Generate proof
Halo2 ZK: live scan matches commitment. ~250ms.
04
Verify offline
Verifier reads proof over NFC/BLE. ~2ms check.
05
Selective disclosure
BBS+ credential — prove "over 18" without showing DOB.
sable · edge device
user@phone  sable enrol

[camera]   capturing face …              ✓ 512-d embedding
[quant]    quantising to field elements  ✓ 256 limbs
[hash]     Poseidon(template) …          ✓ 32 B digest
[commit]   Pedersen(template, r) …       ✓ 64 B commit

stored on device:
   · encrypted template (AES-GCM, device key)
   · commitment  C = g^t · h^r
   · opening r   (never leaves secure storage)

# Nothing sent off-device. No server sees anything.
user@phone  sable auth --verifier gate-42

[camera]    starting liveness sequence …
[flash]     screen → white    reflectance 0.82    
[flash]     screen → red      reflectance 0.41    
[flash]     screen → blue     reflectance 0.53    
[classify]  3D face vs planar display            ✓ real

liveness:  pass   (Tang et al. NDSS 2018 · controlled-illumination)

# The screen is the light source. No depth camera needed.
# Photos and phone-screen replays fail the reflectance model.
user@phone  # generating Halo2 proof

[circuit]  face-match (Poseidon + Pedersen opening)
[witness]  live_template, stored_template, r
[prove]    Halo2 …                        ✓ 248 ms

proof size:   ~11 KB
public input: commitment C, context nonce
private:      template, opening, live scan

proof π generated   (transparent setup — no trusted ceremony)

# The verifier learns: "this person owns a template that opens C,
# and that template matches a live, liveness-checked capture."
# Nothing else.
verifier@gate  # receives proof over BLE, no internet

[ble]      received (C, π, nonce) · 11.2 KB
[verify]   Halo2 verify …                 ✓ 1.8 ms

result:  ACCEPT
learnt:  this bearer controls commitment C
        proof is fresh (nonce matches challenge)

NOT learnt:
   · the template itself
   · the embedding
   · any feature of the face
   · the opening r

# Verification is fully offline. No server, no phone-home.
user@phone  sable disclose --claim "age >= 18"

[credential]  loading VC issued by gov-au-id
[bbs+]        generating selective disclosure proof …
[bind]        binding to biometric proof π            

proved:
   · bearer of commitment C holds a VC from gov-au-id
   · VC asserts date-of-birth <= 2008-04-13
   · VC is not revoked

NOT revealed:
   · actual DOB, name, address, passport number
   · any other attribute on the credential

# BBS+ signatures make "prove predicate, hide attribute" a primitive.
# Combined with the biometric proof: you prove you are the holder,
# and you prove one fact about the holder — nothing more.

Three properties no biometric system combines.

01 · True ZK

Proofs over the data, not about it.

Halo2 circuits prove that a live, quantised embedding opens a stored Pedersen commitment. The template stays secret. No trusted setup, no ceremony, no toxic waste.

  • Halo2 proofs, transparent setup
  • Pedersen commitments over quantised embeddings
  • Poseidon hashing (SNARK-friendly)
  • ~250ms prove, ~2ms verify
  • ~11 KB proof size
02 · Offline-first

No cloud, no blockchain, no phone-home.

Verification happens peer-to-peer over NFC or BLE. The verifier doesn't need a database, an API, or an internet connection. The phone holds the template; the verifier checks the proof.

  • NFC / BLE peer-to-peer flow
  • No central registry, ever
  • Works in border crossings, clinics, disasters
  • Verifier learns only what the proof asserts
  • Replay-resistant via challenge nonces
03 · Any phone

A camera and a screen is the hardware.

Liveness uses controlled-illumination reflectance (Tang et al., NDSS 2018): the screen flashes colours, the camera measures how a 3D face reflects them differently from a flat display. Works on commodity phones.

  • Android and iOS native integrations
  • Screen-flash liveness — no IR, no depth cam
  • Defeats photo & display replay
  • BBS+ verifiable credentials bound to biometric
  • Apache 2.0, 519 tests, 89% coverage

A commitment stays on the phone. A proof leaves.

Enrolment hashes and commits to the template. Authentication regenerates the embedding, proves equality under the commitment, and binds the proof to a fresh challenge from the verifier. Optional verifiable credentials carry attested attributes you can reveal selectively.

┌──────────────────────┐ optional │ Issuer (government) │ ───────────┐ │ BBS+ signed VC │ ▼ └──────────────────────┘ ┌────────────────┐ │ phone (bearer) │ ┌──────────────┐ │ │ ┌────────────────┐ │ face capture │ ───────────────► │ ZK engine │ ─────► │ verifier │ │ liveness │ │ Poseidon │ │ │ │ check │ │ Pedersen │ NFC/ │ Halo2 verify │ └──────────────┘ │ Halo2 prove │ BLE │ check VC │ │ BBS+ disclose │ │ │ └────────────────┘ └────────────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌─────────────────────┐ │ never leaves │ │ learns only │ │ template │ │ what proof asserts │ │ opening r │ │ pass / fail │ │ embedding │ │ disclosed predicate│ └──────────────────┘ └─────────────────────┘

Poseidon + Pedersen

SNARK-friendly primitives keep the circuit small enough to prove in ~250ms on a modern phone.

Halo2, transparent setup

No trusted ceremony, no toxic waste, no "we promise nobody kept the τ." The proof system is auditable.

Liveness as a sensor

Controlled-illumination reflectance uses the screen as a light source. Defeats photo and screen replay without IR hardware.

Selective disclosure via BBS+

A government-issued VC can be shown as "age >= 18" without revealing DOB — or any other attribute.

Binding prevents splicing

The VC disclosure is cryptographically bound to the biometric proof, so a stolen VC can't be replayed by another holder.

Open, auditable, testable

Apache 2.0, 519 tests (77 Halo2-specific), 89% coverage. Build it, fuzz it, read the circuits.

Frequently asked questions.

How is this different from Apple Face ID or Android biometrics?
Apple and Android biometrics unlock the device for its owner. They can't prove identity to a third party — there's no exportable, verifiable proof. sable generates a proof you can hand to a verifier over NFC or BLE, while keeping the template on the device.
How is this different from cloud MPC biometric services?
MPC services split your template across nodes and perform statistical matching over the shards. You still trust the operators, still need always-on connectivity, and still don't have a true ZK proof. sable computes a real ZK proof over the template on-device and verifies offline.
What stops someone stealing my proof?
Every proof is bound to a fresh challenge nonce from the verifier. Proofs can't be replayed because the nonce changes per session. Theft of a prior proof gives the attacker nothing useful.
Is this ready for production?
No — and the README says so. It's an experimental library with AI-assisted development. The cryptographic implementations need independent security auditing before any safety-critical use. Demo, research, and pre-production integration: yes. Real deployments: after audit.
Does the liveness detection really work without a depth camera?
Reflectance analysis with controlled illumination (Tang et al., NDSS 2018) distinguishes 3D faces from screens and photos with high accuracy. It's not equivalent to a dedicated IR depth sensor, but it defeats the replay attacks you actually see in the wild.
Where's the source?
Open source, Apache 2.0, hosted on Codeberg. Rust core with Android and iOS bindings.

A biometric proof you can verify, never own.

Halo2 ZK on the edge. Offline NFC/BLE verification. Selective disclosure. Built on commodity phone hardware, open source under Apache 2.0.

clone: git clone https://codeberg.org/anuna/sable
Disclaimer: experimental code under active development. The cryptographic implementations require independent security auditing before production use. Not suitable for safety-critical deployments today.