Skip to main content

Crate jevil

Crate jevil 

Source
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_cliff is 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_starMTKeyGenSignVerifySig
1272¹¹2²⁷0.4 s0.22 s0.10 s333 KB
10232¹⁴2³⁰3.1 s1.3 s0.7 s428 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} with X² = 7 and Y² = X.
Params
Configuration for a Jevil signer/verifier. Realizes the parameter recipe of paper §4.1.
PublicKey
A Jevil public key. Realizes the pk = (root, w, n*) of paper §4.3, Construction 1 (KeyGen).
SecretKey
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.
SignerCache
Cached signer state held in memory after keygen for fast signing.

Enums§

Error
The error type returned by crate::verify and the byte parsers.

Functions§

keygen
Generate a fresh (PublicKey, SecretKey, SignerCache) triple from a CSPRNG. Realizes Jevil.KeyGen of the paper (§4.3, Construction 1).
sign
Produce a Jevil signature on msg under (pk, sk). Realizes Jevil.Sign of the paper (§4.3, Construction 2).
verify
Verify a Jevil signature. Realizes Jevil.Verify of the paper (§4.3, Construction 3).