second-round version of SQIsign

Co-authored-by: Marius A. Aardal <marius.andre.aardal@gmail.com>
Co-authored-by: Gora Adj <gora.adj@tii.ae>
Co-authored-by: Diego F. Aranha <dfaranha@cs.au.dk>
Co-authored-by: Andrea Basso <sqisign@andreabasso.com>
Co-authored-by: Isaac Andrés Canales Martínez <icanalesm0500@gmail.com>
Co-authored-by: Jorge Chávez-Saab <jorgechavezsaab@gmail.com>
Co-authored-by: Maria Corte-Real Santos <mariascrsantos98@gmail.com>
Co-authored-by: Luca De Feo <github@defeo.lu>
Co-authored-by: Max Duparc <max.duparc@epfl.ch>
Co-authored-by: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com>
Co-authored-by: Décio Luiz Gazzoni Filho <decio@decpp.net>
Co-authored-by: Basil Hess <bhe@zurich.ibm.com>
Co-authored-by: Antonin Leroux <antonin.leroux@polytechnique.org>
Co-authored-by: Patrick Longa <plonga@microsoft.com>
Co-authored-by: Luciano Maino <mainoluciano.96@gmail.com>
Co-authored-by: Michael Meyer <michael@random-oracles.org>
Co-authored-by: Hiroshi Onuki <onuki@mist.i.u-tokyo.ac.jp>
Co-authored-by: Lorenz Panny <lorenz@yx7.cc>
Co-authored-by: Giacomo Pope <giacomopope@gmail.com>
Co-authored-by: Krijn Reijnders <reijnderskrijn@gmail.com>
Co-authored-by: Damien Robert <damien.robert@inria.fr>
Co-authored-by: Francisco Rodríguez-Henriquez <francisco.rodriguez@tii.ae>
Co-authored-by: Sina Schaeffler <sschaeffle@student.ethz.ch>
Co-authored-by: Benjamin Wesolowski <benjamin.wesolowski@ens-lyon.fr>
This commit is contained in:
SQIsign team
2025-02-06 00:00:00 +00:00
committed by Lorenz Panny
parent ff34a8cd18
commit 91e9e464fe
481 changed files with 80785 additions and 55963 deletions

View File

@@ -0,0 +1,139 @@
#include <quaternion.h>
#include <rng.h>
#include <stdio.h>
#include "internal.h"
#include "lll_internals.h"
int
quat_lattice_bound_parallelogram(ibz_vec_4_t *box, ibz_mat_4x4_t *U, const ibz_mat_4x4_t *G, const ibz_t *radius)
{
ibz_t denom, rem;
ibz_init(&denom);
ibz_init(&rem);
ibz_mat_4x4_t dualG;
ibz_mat_4x4_init(&dualG);
// Compute the Gram matrix of the dual lattice
#ifndef NDEBUG
int inv_check = ibz_mat_4x4_inv_with_det_as_denom(&dualG, &denom, G);
assert(inv_check);
#else
(void)ibz_mat_4x4_inv_with_det_as_denom(&dualG, &denom, G);
#endif
// Initialize the dual lattice basis to the identity matrix
ibz_mat_4x4_identity(U);
// Reduce the dual lattice
quat_lll_core(&dualG, U);
// Compute the parallelogram's bounds
int trivial = 1;
for (int i = 0; i < 4; i++) {
ibz_mul(&(*box)[i], &dualG[i][i], radius);
ibz_div(&(*box)[i], &rem, &(*box)[i], &denom);
ibz_sqrt_floor(&(*box)[i], &(*box)[i]);
trivial &= ibz_is_zero(&(*box)[i]);
}
// Compute the transpose transformation matrix
#ifndef NDEBUG
int inv = ibz_mat_4x4_inv_with_det_as_denom(U, &denom, U);
#else
(void)ibz_mat_4x4_inv_with_det_as_denom(U, &denom, U);
#endif
// U is unitary, det(U) = ± 1
ibz_mat_4x4_scalar_mul(U, &denom, U);
#ifndef NDEBUG
assert(inv);
ibz_abs(&denom, &denom);
assert(ibz_is_one(&denom));
#endif
ibz_mat_4x4_finalize(&dualG);
ibz_finalize(&denom);
ibz_finalize(&rem);
return !trivial;
}
int
quat_lattice_sample_from_ball(quat_alg_elem_t *res,
const quat_lattice_t *lattice,
const quat_alg_t *alg,
const ibz_t *radius)
{
assert(ibz_cmp(radius, &ibz_const_zero) > 0);
ibz_vec_4_t box;
ibz_vec_4_init(&box);
ibz_mat_4x4_t U, G;
ibz_mat_4x4_init(&U);
ibz_mat_4x4_init(&G);
ibz_vec_4_t x;
ibz_vec_4_init(&x);
ibz_t rad, tmp;
ibz_init(&rad);
ibz_init(&tmp);
// Compute the Gram matrix of the lattice
quat_lattice_gram(&G, lattice, alg);
// Correct ball radius by the denominator
ibz_mul(&rad, radius, &lattice->denom);
ibz_mul(&rad, &rad, &lattice->denom);
// Correct by 2 (Gram matrix corresponds to twice the norm)
ibz_mul(&rad, &rad, &ibz_const_two);
// Compute a bounding parallelogram for the ball, stop if it only
// contains the origin
int ok = quat_lattice_bound_parallelogram(&box, &U, &G, &rad);
if (!ok)
goto err;
// Rejection sampling from the parallelogram
#ifndef NDEBUG
int cnt = 0;
#endif
do {
// Sample vector
for (int i = 0; i < 4; i++) {
if (ibz_is_zero(&box[i])) {
ibz_copy(&x[i], &ibz_const_zero);
} else {
ibz_add(&tmp, &box[i], &box[i]);
ok &= ibz_rand_interval(&x[i], &ibz_const_zero, &tmp);
ibz_sub(&x[i], &x[i], &box[i]);
if (!ok)
goto err;
}
}
// Map to parallelogram
ibz_mat_4x4_eval_t(&x, &x, &U);
// Evaluate quadratic form
quat_qf_eval(&tmp, &G, &x);
#ifndef NDEBUG
cnt++;
if (cnt % 100 == 0)
printf("Lattice sampling rejected %d times", cnt - 1);
#endif
} while (ibz_is_zero(&tmp) || (ibz_cmp(&tmp, &rad) > 0));
// Evaluate linear combination
ibz_mat_4x4_eval(&(res->coord), &(lattice->basis), &x);
ibz_copy(&(res->denom), &(lattice->denom));
quat_alg_normalize(res);
#ifndef NDEBUG
// Check norm is smaller than radius
quat_alg_norm(&tmp, &rad, res, alg);
ibz_mul(&rad, &rad, radius);
assert(ibz_cmp(&tmp, &rad) <= 0);
#endif
err:
ibz_finalize(&rad);
ibz_finalize(&tmp);
ibz_vec_4_finalize(&x);
ibz_mat_4x4_finalize(&U);
ibz_mat_4x4_finalize(&G);
ibz_vec_4_finalize(&box);
return ok;
}