1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
//! # 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
//!
//! ```no_run
//! 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.
pub use crateError;
pub use crateGoldilocks4;
pub use crate;
pub use crateParams;
pub use crate;
pub use crateverify;
/// A Jevil public key. Realizes the `pk = (root, w, n*)` of paper §4.3,
/// Construction 1 (`KeyGen`).
///
/// Layout: 32-byte zk-WHIR commitment root, 32-byte OOD value
/// `w = f(z) ∈ F`, and a 4-byte little-endian `n_star`. The OOD point `z`
/// itself is not transmitted — both signer and verifier re-derive it from
/// `root` via the `JV-OOD` SHAKE256 stream. The signing budget is carried
/// in the public key so that verifiers can derive every subsidiary
/// parameter (`M`, `T`, `ν`, the commit dimension `N`) from it.
/// 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`).
///
/// The seed expands into the polynomial coefficients `c = (c_0, …, c_{M−1})`
/// via the `JV-SEED` SHAKE256 stream and is also passed to `WHIR.Commit`,
/// which uses the `JV-RZK` stream off the same seed to deterministically
/// derive its internal Prop. 3.19 encoding randomness.
///
/// `SecretKey` deliberately does **not** implement [`std::fmt::Debug`] or
/// [`std::fmt::Display`] to discourage accidental logging. The inner bytes are
/// accessible only through [`SecretKey::to_bytes`] (which clones them) and
/// [`SecretKey::from_bytes`].
///
/// On drop the inner bytes are zeroized via the [`zeroize`] crate (which uses
/// volatile writes internally to defeat compiler dead-store elimination).
;