Expand description
§Jevil — a stateless few-time signature scheme with a sharp cliff
Jevil is a stateless few-time signature scheme parameterised by a single
signing budget n*. Signatures 1..=n* are existentially unforgeable; at
the (n* + 1)-th signature the secret signing key becomes publicly
recoverable by anyone observing the signatures — the cap is enforced not
by counters or hardware, but by the algebraic structure of a single
committed polynomial. Params::new accepts only n_star values for
which n_star + 1 is a power of two (the paper’s recommended regime), so
n_cliff = n_star + 1 exactly for every deployment.
§When to use Jevil
Jevil is designed for audit-budgeted credentials:
- firmware vendors capping their own release count,
- operators binding themselves to a per-tenure attestation budget,
- ephemeral session signers with a per-session cap,
- any setting where over-signing must be made self-exposing rather than merely policy-forbidden.
It is not a general-purpose signature scheme — for everyday signing, use a stateful or unlimited-use post-quantum scheme such as ML-DSA or Falcon. Jevil’s value is in the cliff.
§Properties
- Stateless signing. No counter, no per-signature state — the signer only stores a 32-byte seed.
- Cryptographic budget enforcement. The cliff at
n_cliffis intrinsic to the public-key commitment; no malicious signer can extend it. - Post-quantum. All primitives (Poseidon2, SHAKE256, WHIR) are plausibly post-quantum at 128-bit classical security (≥ 85 bits quantum at the recommended capacity; raise capacity for 128-bit quantum).
- Compact public keys (68 B) and moderate signatures (~94 KB at n*=1 up to a few hundred KB across the deployable range).
§Quick start
use jevil::{keygen, sign, verify, Params};
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
// Budget: at most 7 honest signatures (cliff fires at the 8th).
let params = Params::new(7);
let mut rng = ChaCha20Rng::seed_from_u64(0);
let (pk, sk, cache) = keygen(&mut rng, params);
let signature = sign(&sk, &pk, &cache, params, b"firmware-image-v1.0.0");
assert!(verify(&pk, params, b"firmware-image-v1.0.0", &signature).is_ok());§Parameter selection
Jevil takes a single integer parameter n_star (the signing budget).
n_star + 1 must be a power of two — i.e. n_star ∈ {1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, …}; Params::new panics on any other value to
prevent accidental deployment into the soft-degradation regime. Within
this set the cliff fires precisely at signature n_star + 1. See
Params for the full parameter derivation.
Reference sizes at the recommended K = 16 positions-per-signature,
measured post-size-optimisation on Apple-Silicon-class hardware:
n_star | M | T | KeyGen | Sign | Verify | Sig |
|---|---|---|---|---|---|---|
| 127 | 2¹¹ | 2²⁷ | 0.4 s | 0.22 s | 0.10 s | 333 KB |
| 1023 | 2¹⁴ | 2³⁰ | 3.1 s | 1.3 s | 0.7 s | 428 KB |
The deployable range extends up to n*=16,383 (the working field’s
2-adicity ceiling) but the cached-initial-Merkle-tree footprint
scales as ~N Goldilocks elements — at the ceiling this stresses
consumer-class memory budgets.
§Construction (one paragraph)
The secret is a univariate polynomial f ∈ F[X] of degree D = M − 1 over
the quartic Goldilocks extension F_{q_0^4} (|F| ≈ 2^256), derived
deterministically from a 32-byte seed σ. The public key is a zk-WHIR
commitment to the length-M coefficient vector c = (c_0, …, c_{M−1});
the Proposition 3.19 encoding randomness is sampled inside WHIR.Commit
from the same σ and never appears in the signer’s user-facing API. A
signature on a message M opens f at K = 16 message-derived positions
via a single batched zk-WHIR linear-form proof (Construction 6.3 sumcheck
plus Construction 7.2 base case). After n_cliff = ⌈M/K⌉ signatures the
outsider has accumulated ≥ D + 1 distinct evaluations of f and
reconstructs the secret by Lagrange interpolation.
For the full construction and security analysis see the Jevil paper. For
the per-construction compliance status against the zk-WHIR paper (ePrint
2026/391), see docs/zkwhir-spec-compliance.md.
§Modules
Most users will only touch the items re-exported from this crate root. Internal modules implement the underlying primitives:
- the Goldilocks quartic extension field and the position-to-field map ψ,
- the Poseidon2-Goldilocks sponge and SHAKE256 extendable-output function,
- a binary Merkle tree and the WHIR Reed–Solomon-proximity-test IOP,
- the Jevil-specific lift, transcript, and position-derivation procedures.
§License
Licensed under either of Apache License, Version 2.0 or MIT license, at your option.
Structs§
- Goldilocks4
- Quartic extension field element
F_{q₀⁴}represented as four base-field coefficients in the basis{1, X, Y, XY}withX² = 7andY² = X. - Params
- Configuration for a Jevil signer/verifier. Realizes the parameter recipe of paper §4.1.
- Public
Key - A Jevil public key. Realizes the
pk = (root, w, n*)of paper §4.3, Construction 1 (KeyGen). - Secret
Key - A Jevil signing secret: a 32-byte seed from which every other signer-side
value is deterministically derived (paper §4.3, Construction 1 step 1:
s ← {0,1}^256). - Signature
- A Jevil signature.
- Signer
Cache - Cached signer state held in memory after
keygenfor fast signing.
Enums§
- Error
- The error type returned by
crate::verifyand the byte parsers.
Functions§
- keygen
- Generate a fresh
(PublicKey, SecretKey, SignerCache)triple from a CSPRNG. RealizesJevil.KeyGenof the paper (§4.3, Construction 1). - sign
- Produce a Jevil signature on
msgunder(pk, sk). RealizesJevil.Signof the paper (§4.3, Construction 2). - verify
- Verify a Jevil signature. Realizes
Jevil.Verifyof the paper (§4.3, Construction 3).