1use crate::macaulay::{self, Monomial};
16use crate::xl::{eval, Field, Gf256, MQSystem, Poly};
17use logicaffeine_base::gf256;
18use std::collections::BTreeMap;
19
20#[derive(Clone, Copy, Debug)]
22pub struct RainbowParams {
23 pub v1: usize,
24 pub o1: usize,
25 pub o2: usize,
26}
27
28impl RainbowParams {
29 pub fn n(&self) -> usize {
30 self.v1 + self.o1 + self.o2
31 }
32 pub fn m(&self) -> usize {
33 self.o1 + self.o2
34 }
35 fn l1(&self) -> usize {
37 self.v1 + self.o1
38 }
39}
40
41pub struct SecretKey {
42 pub params: RainbowParams,
43 s_inv: Vec<Vec<u8>>,
44 s_vec: Vec<u8>,
45 t_inv: Vec<Vec<u8>>,
46 t_vec: Vec<u8>,
47 central: Vec<Poly<Gf256>>,
48}
49
50pub struct PublicKey {
51 pub params: RainbowParams,
52 pub polys: Vec<Poly<Gf256>>,
54}
55
56fn padd(dst: &mut Poly<Gf256>, m: &Monomial, c: Gf256) {
59 if c.is_zero() {
60 return;
61 }
62 let v = dst.get(m).copied().unwrap_or_else(Gf256::zero).add(c);
63 if v.is_zero() {
64 dst.remove(m);
65 } else {
66 dst.insert(m.clone(), v);
67 }
68}
69
70fn poly_add_into(dst: &mut Poly<Gf256>, src: &Poly<Gf256>) {
71 for (m, &c) in src {
72 padd(dst, m, c);
73 }
74}
75
76fn poly_mul(a: &Poly<Gf256>, b: &Poly<Gf256>) -> Poly<Gf256> {
77 let mut r = BTreeMap::new();
78 for (ma, &ca) in a {
79 for (mb, &cb) in b {
80 padd(&mut r, &macaulay::mul(ma, mb, false), ca.mul(cb));
81 }
82 }
83 r
84}
85
86fn substitute_affine(f: &Poly<Gf256>, subs: &[Poly<Gf256>]) -> Poly<Gf256> {
89 let mut out = BTreeMap::new();
90 for (mono, &c) in f {
91 let mut term: Poly<Gf256> = BTreeMap::new();
92 term.insert(Vec::new(), c); for &v in mono {
94 term = poly_mul(&term, &subs[v as usize]);
95 }
96 poly_add_into(&mut out, &term);
97 }
98 out
99}
100
101fn substitute_values(f: &Poly<Gf256>, fixed: &[Option<Gf256>]) -> Poly<Gf256> {
104 let mut out = BTreeMap::new();
105 for (mono, &c) in f {
106 let mut coeff = c;
107 let mut rem: Monomial = Vec::new();
108 for &v in mono {
109 match fixed[v as usize] {
110 Some(val) => coeff = coeff.mul(val),
111 None => rem.push(v),
112 }
113 }
114 rem.sort_unstable();
115 padd(&mut out, &rem, coeff);
116 }
117 out
118}
119
120struct Rng(u64);
123impl Rng {
124 fn next(&mut self) -> u64 {
125 self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
126 let mut z = self.0;
127 z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
128 z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
129 z ^ (z >> 31)
130 }
131 fn byte(&mut self) -> u8 {
132 self.next() as u8
133 }
134 fn gf(&mut self) -> Gf256 {
135 Gf256(self.byte())
136 }
137}
138
139fn random_invertible(rng: &mut Rng, size: usize) -> (Vec<Vec<u8>>, Vec<Vec<u8>>) {
140 loop {
141 let mat: Vec<Vec<u8>> = (0..size)
142 .map(|_| (0..size).map(|_| rng.byte()).collect())
143 .collect();
144 if let Some(inv) = gf256::invert(&mat) {
145 return (mat, inv);
146 }
147 }
148}
149
150fn gen_central(p: &RainbowParams, rng: &mut Rng) -> Vec<Poly<Gf256>> {
153 let (n, v1, l1) = (p.n(), p.v1, p.l1());
154 let mut central = Vec::with_capacity(p.m());
155 for _ in 0..p.o1 {
157 let mut f = BTreeMap::new();
158 for i in 0..l1 {
159 if i < v1 {
160 for j in i..l1 {
161 padd(&mut f, &vec![i as u32, j as u32], rng.gf());
162 }
163 }
164 }
165 for i in 0..l1 {
166 padd(&mut f, &vec![i as u32], rng.gf());
167 }
168 padd(&mut f, &Vec::new(), rng.gf());
169 central.push(f);
170 }
171 for _ in 0..p.o2 {
173 let mut f = BTreeMap::new();
174 for i in 0..n {
175 if i < l1 {
176 for j in i..n {
177 padd(&mut f, &vec![i as u32, j as u32], rng.gf());
178 }
179 }
180 }
181 for i in 0..n {
182 padd(&mut f, &vec![i as u32], rng.gf());
183 }
184 padd(&mut f, &Vec::new(), rng.gf());
185 central.push(f);
186 }
187 central
188}
189
190pub fn keygen(params: RainbowParams, seed: u64) -> (SecretKey, PublicKey) {
193 let (n, m) = (params.n(), params.m());
194 let mut rng = Rng(seed);
195
196 let (t_mat, t_inv) = random_invertible(&mut rng, n);
197 let t_vec: Vec<u8> = (0..n).map(|_| rng.byte()).collect();
198 let (s_mat, s_inv) = random_invertible(&mut rng, m);
199 let s_vec: Vec<u8> = (0..m).map(|_| rng.byte()).collect();
200 let central = gen_central(¶ms, &mut rng);
201
202 let t_forms: Vec<Poly<Gf256>> = (0..n)
204 .map(|i| {
205 let mut p: Poly<Gf256> = BTreeMap::new();
206 padd(&mut p, &Vec::new(), Gf256(t_vec[i]));
207 for a in 0..n {
208 padd(&mut p, &vec![a as u32], Gf256(t_mat[i][a]));
209 }
210 p
211 })
212 .collect();
213 let f_comp: Vec<Poly<Gf256>> = central
214 .iter()
215 .map(|f| substitute_affine(f, &t_forms))
216 .collect();
217
218 let mut polys = Vec::with_capacity(m);
219 for k in 0..m {
220 let mut pk: Poly<Gf256> = BTreeMap::new();
221 for l in 0..m {
222 let c = Gf256(s_mat[k][l]);
223 if !c.is_zero() {
224 for (mono, &fc) in &f_comp[l] {
225 padd(&mut pk, mono, c.mul(fc));
226 }
227 }
228 }
229 padd(&mut pk, &Vec::new(), Gf256(s_vec[k]));
230 polys.push(pk);
231 }
232
233 (
234 SecretKey {
235 params,
236 s_inv,
237 s_vec,
238 t_inv,
239 t_vec,
240 central,
241 },
242 PublicKey { params, polys },
243 )
244}
245
246fn hash_seed(msg_hash: &[u8]) -> u64 {
247 let mut seed = 0x9E37_79B9_7F4A_7C15u64;
248 for &b in msg_hash {
249 seed = seed.rotate_left(7) ^ (b as u64).wrapping_mul(0x1_0000_0001_B3);
250 }
251 seed
252}
253
254pub fn sign(sk: &SecretKey, msg_hash: &[u8]) -> Option<Vec<u8>> {
257 let u = central_target(sk, msg_hash);
258 for attempt in 0..256u64 {
259 let mut rng = Rng(hash_seed(msg_hash) ^ attempt.wrapping_mul(0xA5A5_A5A5));
260 let vinegars: Vec<u8> = (0..sk.params.v1).map(|_| rng.byte()).collect();
261 if let Some(x) = sign_core(sk, &u, &vinegars) {
262 return Some(x);
263 }
264 }
265 None
266}
267
268pub fn sign_with_vinegars(sk: &SecretKey, msg_hash: &[u8], vinegars: &[u8]) -> Option<Vec<u8>> {
271 sign_core(sk, ¢ral_target(sk, msg_hash), vinegars)
272}
273
274fn central_target(sk: &SecretKey, msg_hash: &[u8]) -> Vec<u8> {
276 let d_minus_s: Vec<u8> = (0..sk.params.m())
277 .map(|k| msg_hash[k] ^ sk.s_vec[k])
278 .collect();
279 gf256::matvec(&sk.s_inv, &d_minus_s)
280}
281
282fn sign_core(sk: &SecretKey, u: &[u8], vinegars: &[u8]) -> Option<Vec<u8>> {
284 let p = sk.params;
285 let (n, v1, o1, o2, l1) = (p.n(), p.v1, p.o1, p.o2, p.l1());
286 let mut fixed: Vec<Option<Gf256>> = vec![None; n];
287 for i in 0..v1 {
288 fixed[i] = Some(Gf256(vinegars[i]));
289 }
290
291 let mut a1 = vec![vec![0u8; o1]; o1];
293 let mut b1 = vec![0u8; o1];
294 for k in 0..o1 {
295 let red = substitute_values(&sk.central[k], &fixed);
296 b1[k] = u[k] ^ red.get(&Vec::new()).copied().unwrap_or_else(Gf256::zero).0;
297 for c in 0..o1 {
298 a1[k][c] = red
299 .get(&vec![(v1 + c) as u32])
300 .copied()
301 .unwrap_or_else(Gf256::zero)
302 .0;
303 }
304 }
305 let sol1 = gf256::solve(&a1, &b1)?;
306 for c in 0..o1 {
307 fixed[v1 + c] = Some(Gf256(sol1[c]));
308 }
309
310 let mut a2 = vec![vec![0u8; o2]; o2];
312 let mut b2 = vec![0u8; o2];
313 for k in 0..o2 {
314 let red = substitute_values(&sk.central[o1 + k], &fixed);
315 b2[k] = u[o1 + k] ^ red.get(&Vec::new()).copied().unwrap_or_else(Gf256::zero).0;
316 for c in 0..o2 {
317 a2[k][c] = red
318 .get(&vec![(l1 + c) as u32])
319 .copied()
320 .unwrap_or_else(Gf256::zero)
321 .0;
322 }
323 }
324 let sol2 = gf256::solve(&a2, &b2)?;
325 for c in 0..o2 {
326 fixed[l1 + c] = Some(Gf256(sol2[c]));
327 }
328
329 let w: Vec<u8> = (0..n).map(|i| fixed[i].unwrap().0).collect();
331 let w_minus_t: Vec<u8> = (0..n).map(|i| w[i] ^ sk.t_vec[i]).collect();
332 Some(gf256::matvec(&sk.t_inv, &w_minus_t))
333}
334
335pub fn verify(pk: &PublicKey, msg_hash: &[u8], sig: &[u8]) -> bool {
337 if sig.len() != pk.params.n() {
338 return false;
339 }
340 let x: Vec<Gf256> = sig.iter().map(|&b| Gf256(b)).collect();
341 (0..pk.params.m()).all(|k| eval(&pk.polys[k], &x).0 == msg_hash[k])
342}
343
344pub fn forge_system(pk: &PublicKey, msg_hash: &[u8]) -> MQSystem<Gf256> {
347 let polys = pk
348 .polys
349 .iter()
350 .enumerate()
351 .map(|(k, p)| {
352 let mut q = p.clone();
353 padd(&mut q, &Vec::new(), Gf256(msg_hash[k])); q
355 })
356 .collect();
357 MQSystem {
358 n: pk.params.n(),
359 polys,
360 }
361}
362
363pub fn flatten_public(pk: &PublicKey) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
367 let (n, m) = (pk.params.n(), pk.params.m());
368 let mut pubq = Vec::new();
369 let mut publin = Vec::new();
370 let mut pubc = Vec::new();
371 for k in 0..m {
372 for i in 0..n {
373 for j in i..n {
374 pubq.push(
375 pk.polys[k]
376 .get(&vec![i as u32, j as u32])
377 .copied()
378 .unwrap_or_else(Gf256::zero)
379 .0,
380 );
381 }
382 }
383 for i in 0..n {
384 publin.push(
385 pk.polys[k]
386 .get(&vec![i as u32])
387 .copied()
388 .unwrap_or_else(Gf256::zero)
389 .0,
390 );
391 }
392 pubc.push(
393 pk.polys[k]
394 .get(&Vec::new())
395 .copied()
396 .unwrap_or_else(Gf256::zero)
397 .0,
398 );
399 }
400 (pubq, publin, pubc)
401}
402
403#[derive(Clone, Debug)]
406pub struct SecretFlat {
407 pub central_q: Vec<u8>,
408 pub central_lin: Vec<u8>,
409 pub central_c: Vec<u8>,
410 pub s_inv: Vec<u8>,
411 pub s_vec: Vec<u8>,
412 pub t_inv: Vec<u8>,
413 pub t_vec: Vec<u8>,
414}
415
416pub fn flatten_secret(sk: &SecretKey) -> SecretFlat {
417 let (n, m) = (sk.params.n(), sk.params.m());
418 let mut central_q = Vec::new();
419 let mut central_lin = Vec::new();
420 let mut central_c = Vec::new();
421 for k in 0..m {
422 for i in 0..n {
423 for j in i..n {
424 central_q.push(
425 sk.central[k]
426 .get(&vec![i as u32, j as u32])
427 .copied()
428 .unwrap_or_else(Gf256::zero)
429 .0,
430 );
431 }
432 }
433 for i in 0..n {
434 central_lin.push(
435 sk.central[k]
436 .get(&vec![i as u32])
437 .copied()
438 .unwrap_or_else(Gf256::zero)
439 .0,
440 );
441 }
442 central_c.push(
443 sk.central[k]
444 .get(&Vec::new())
445 .copied()
446 .unwrap_or_else(Gf256::zero)
447 .0,
448 );
449 }
450 SecretFlat {
451 central_q,
452 central_lin,
453 central_c,
454 s_inv: sk.s_inv.iter().flatten().copied().collect(),
455 s_vec: sk.s_vec.clone(),
456 t_inv: sk.t_inv.iter().flatten().copied().collect(),
457 t_vec: sk.t_vec.clone(),
458 }
459}
460
461#[derive(Clone, Debug)]
465pub struct KeygenInputs {
466 pub t_mat: Vec<u8>,
467 pub t_vec: Vec<u8>,
468 pub s_mat: Vec<u8>,
469 pub s_vec: Vec<u8>,
470 pub central_q: Vec<u8>,
471 pub central_lin: Vec<u8>,
472 pub central_c: Vec<u8>,
473}
474
475fn reshape(flat: &[u8], k: usize) -> Vec<Vec<u8>> {
476 (0..k).map(|r| flat[r * k..(r + 1) * k].to_vec()).collect()
477}
478
479pub fn flatten_keygen(sk: &SecretKey) -> KeygenInputs {
480 let sf = flatten_secret(sk);
481 let (n, m) = (sk.params.n(), sk.params.m());
482 let t_mat = gf256::invert(&reshape(&sf.t_inv, n)).expect("T⁻¹ is invertible");
483 let s_mat = gf256::invert(&reshape(&sf.s_inv, m)).expect("S⁻¹ is invertible");
484 KeygenInputs {
485 t_mat: t_mat.into_iter().flatten().collect(),
486 t_vec: sf.t_vec,
487 s_mat: s_mat.into_iter().flatten().collect(),
488 s_vec: sf.s_vec,
489 central_q: sf.central_q,
490 central_lin: sf.central_lin,
491 central_c: sf.central_c,
492 }
493}
494
495#[cfg(test)]
496#[path = "../../logicaffeine_tests/unit/logicaffeine_proof/rainbow/tests.rs"]
497mod tests;