Technical Deep Dive

How LiberProof works

From notarization and signed attestations to our zero-knowledge layer and on-chain anchoring — how LiberProof turns claims into independently verifiable proofs.

What is a zero-knowledge proof?

A ZK proof lets you convince someone that a statement is true — without revealing anything about why it's true. The math enforces the privacy; there's no trust required. Our zero-knowledge layer is in active development — the age-threshold circuit is live today, with more circuits expanding from there.

🧮
The core intuition
Imagine you want to prove you know the solution to a puzzle without showing the solution itself. A zero-knowledge proof is exactly that — a mathematical protocol where a Prover convinces a Verifier that a statement is true, without the Verifier learning anything else.

Formally, a ZK proof satisfies three properties: Completeness (an honest prover always convinces the verifier), Soundness (a dishonest prover cannot fake a valid proof), and Zero-Knowledge (the verifier learns only that the statement is true — nothing more). LiberProof implements ZK-SNARKs: Succinct Non-interactive Arguments of Knowledge. "Succinct" means proofs are small (typically ~128 bytes for Groth16) and fast to verify. "Non-interactive" means no back-and-forth — you generate the proof once and anyone can verify it.
🎭
Prover vs Verifier
The Prover (you) holds private data — your credential attributes. You generate a proof that commits to specific claims without revealing the underlying data. The Verifier (a service, smart contract, or institution) receives the proof and a set of public inputs — the claims being made — and verifies the proof is valid. They learn whether the claims are true. Nothing else.
🔑
Public inputs vs private witness
Every ZK proof has two parts: the public inputs (what you're claiming — "age ≥ 18") and the private witness (the data that makes it true — your actual age of 31). The circuit encodes the relationship between them. The proof proves the witness satisfies the circuit — without revealing the witness itself.

Groth16 — the proving system

LiberProof's ZK layer is built on Groth16, a pairing-based ZK-SNARK construction that produces constant-size proofs with millisecond-class verification — ideal for both browser and on-chain use.

~128 B
Proof size (constant)
O(1)
Verification cost
BN254
Elliptic curve pairing
3 points
Proof structure (A, B, C)

Figures are standard Groth16 characteristics; LiberProof's prover is in active development.

⚙️
Trusted Setup
Groth16 requires a per-circuit trusted setup to generate proving and verification keys. A full multi-party setup ceremony is on our roadmap — for the current age circuit, follow the documented setup to generate keys.
🔗
Pairing-based cryptography
Groth16 relies on bilinear pairings over the BN254 elliptic curve. The pairing operation allows the verifier to check a linear relationship between the prover's commitments without evaluating the polynomial directly — this is what makes verification constant-time regardless of circuit complexity.
📐
R1CS constraint system
Each circuit is expressed as a Rank-1 Constraint System (R1CS) — a set of equations that must hold for a valid witness. For example, the age circuit enforces age - threshold ≥ 0 as a constraint. Compilation converts the R1CS into the Groth16 proving/verification key pair.
📦
Proof structure
A Groth16 proof consists of three elliptic curve points: π_A (in G1), π_B (in G2), and π_C (in G1). These 128 bytes are all a verifier needs — along with the public inputs — to confirm the proof's validity. No additional communication required.

Credential to proof — step by step

Every LiberProof flow follows the same four-stage pipeline. Private data stays local at every stage.

01
Stage 1 — Issuance
Issuer signs a credential
A trusted issuer — a government registry, institutional verifier, or LiberVault wallet itself — signs a credential containing your attributes: { age, citizenship, balance, ... }. The signature is an EdDSA commitment over the attribute set. The credential is delivered to you and stored only on your device.
Local
02
Stage 2 — Witness Generation
Select claims to prove
You choose which claims to prove from your credential — for example, age ≥ 18. LiberProof constructs the witness: the full private inputs to the circuit, including your actual age value and the credential signature. The witness never leaves your device.
Local
03
Stage 3 — Proof Generation
Groth16 proof computed in browser
The Groth16 prover runs entirely in your browser using snarkjs and WebAssembly. It takes the witness and the circuit proving key, and outputs a 128-byte proof along with the public inputs. The private witness is discarded after proof generation — it is never transmitted.
Local
04
Stage 4 — Verification
Proof verified — on-chain or off
The proof and public inputs are submitted to a verifier — locally, via API, or anchored on-chain (EVM today; Cardano is our launch chain, rolling out). On-chain smart-contract verification is on the roadmap. The verifier learns only the result and the public claims — nothing else.
Public

API reference

LiberProof exposes a clean JavaScript API. Notarize, attest, and verify in a few lines.

liberproof-sdk / example.js
import { LiberProof } from '@liberproof/sdk'; // Initialize with a signer (any secp256k1 / Ed25519 key) const lp = new LiberProof({ signer: { privateKey: '0xabc...', algorithm: 'secp256k1', verificationMethod: 'did:key:z6Mk...', }, }); // Notarize a document — SHA-256 + sign + timestamp (local, offline) const record = lp.notarize({ data: fileBytes, mimeType: 'application/pdf', label: 'Contract' }); console.log(record.documentHash); // SHA-256 hex // Issue a signed attestation (W3C-VC aligned) const attestation = lp.attest({ subject: '0xSubject...', claim: { isOver18: true } }); // Verify it — no LiberProof server needed const result = lp.verify(attestation, issuerPublicKey); console.log(result.valid); // true // Optional: anchor the proof hash on-chain (EVM today; Cardano on the roadmap) import { EvmAnchorAdapter } from '@liberproof/anchors'; const anchored = await lp.anchor(record, new EvmAnchorAdapter({ publicClient, walletClient, chainName: 'ethereum' }));
@liberproof/zk — In Development
// Zero-knowledge proofs — separate package, in active development, // requires snarkjs + a compiled circuit import { generateProof, verifyProof } from '@liberproof/zk'; const proof = await generateProof({ witness: { age: 25, minAge: 18 }, wasmPath, zkeyPath });

Anchoring & on-chain verification

Today, LiberProof anchors a proof's hash on-chain (EVM calldata; Cardano is our launch chain, rolling out) — anyone can independently confirm an anchor by its txHash on a block explorer. On the roadmap: generated Solidity verifiers, an attestation registry, and composable on-chain verification.

📜
Solidity Verifier Roadmap
On the roadmap: a generated Solidity verifier contract per circuit type, exposing a verifyProof() function that runs the Groth16 pairing check on-chain at constant gas cost — in active development.
🗃️
Attestation Registry Roadmap
On the roadmap: a registry contract recording verified proofs with nullifier-based double-submission protection, attesting a proof was valid at a specific block height while preserving privacy.
🔁
Composable Verification Roadmap
On the roadmap: other smart contracts querying the registry or calling verifiers directly — composable governance where a DAO can require a verified proof as a prerequisite for participation, with no identity exposure.

Own your
proof layer.

LiberProof is open source and ready to integrate. Start building privacy-preserving credentials for your sovereign systems.

GitHub Repository