A clean, simple C implementation of Sigma protocols with Fiat-Shamir transformation for non-interactive zero-knowledge proofs.
- Schnorr Protocol: Prove knowledge of discrete logarithm
- Chaum-Pedersen Protocol: Prove discrete logarithm equality (DLEQ)
- Non-interactive proofs: Using Fiat-Shamir transformation with SHAKE128
- Minimal API: Just 6 functions for complete functionality
- No abstractions: Direct use of byte arrays, no wrapper types
- Secure: Built on libsodium's Ristretto255 group operations
Prerequisites:
- C compiler (clang or gcc)
- libsodium development libraries
Initialize the library (wraps sodium_init).
Proves knowledge of x where Y = x*G (G is the generator).
Proves that log_g1(h1) = log_g2(h2) without revealing the exponent.
What it proves: Knowledge of a secret value (discrete logarithm) without revealing it.
Mathematical property: Proves "I know x such that Y = x*G" where G is the generator and Y is public.
Use cases:
- Digital signatures: Prove you own the private key corresponding to a public key
- Authentication: Log in to a service without transmitting your password
- Cryptocurrency wallets: Prove ownership of funds without revealing private keys
- Access control: Demonstrate you have credentials without exposing them
- Password-authenticated key exchange (PAKE): Establish secure channels based on passwords
Example scenario: Alice wants to prove she owns a Bitcoin address. She uses Schnorr to prove she knows the private key corresponding to the public address, without revealing the private key itself.
What it proves: Two discrete logarithms are equal, without revealing the common exponent.
Mathematical property: Proves "log_g1(h1) = log_g2(h2)" or equivalently "h1 = g1^x AND h2 = g2^x" for some secret x.
Use cases:
- Verifiable encryption: Prove a ciphertext encrypts a specific value without decryption
- Anonymous credentials: Show two credentials belong to the same user without revealing identity
- Mix networks: Prove correct re-encryption in privacy protocols
- Cross-chain atomic swaps: Prove same secret is used in multiple transactions
- Verifiable shuffles: Prove a list was correctly permuted without revealing the permutation
- Blind signatures: Prove consistency between blinded and unblinded values
Example scenario: A voting system needs to prove that an encrypted vote was correctly re-encrypted (same vote, different randomness) during the mixing phase, without revealing the actual vote.
Proof size | 64 bytes | 96 bytes |
What's proven | Knowledge of one secret | Equality of two discrete logs |
Complexity | Simpler | More complex |
Computation | 2 exponentiations to verify | 4 exponentiations to verify |
Primary use | Authentication, signatures | Verifiable encryption, DLEQ proofs |
- Elliptic Curve Group: Ristretto255 (via libsodium)
- Hash Function: SHAKE128 for Fiat-Shamir challenges
- Proof Sizes: Fixed - 64 bytes (Schnorr), 96 bytes (Chaum-Pedersen)
- Security: 128-bit security level