├── .gitattributes ├── LICENSE ├── Module_BFRS ├── Makefile ├── Misc │ ├── Makefile │ ├── multiplicative_order.c │ └── primes.c ├── arithmetic.c ├── arithmetic.h ├── common.h ├── cpucycles.c ├── cpucycles.h ├── crt_trees.c ├── ibe.c ├── ibe.h ├── main_signature.c ├── random.c ├── random.h ├── sage.sage ├── sage.sage.py ├── sampling.c ├── sampling.h ├── script.sage ├── signature.c ├── signature.h └── timing.c ├── README ├── ROM_GPV ├── Makefile ├── Misc │ ├── Makefile │ ├── multiplicative_order.c │ └── primes.c ├── arithmetic.c ├── arithmetic.h ├── common.h ├── cpucycles.c ├── cpucycles.h ├── hash.c ├── hash.h ├── main_signature.c ├── random.c ├── random.h ├── sage.sage.py ├── sampling.c ├── sampling.h ├── sampling_tests.c ├── script.sage ├── signature.c ├── signature.h ├── signature_tests.c ├── timing.c └── zetas.c └── Standard_BFRS ├── Makefile ├── Misc ├── Makefile ├── multiplicative_order.c └── primes.c ├── arithmetic.c ├── arithmetic.h ├── common.h ├── cpucycles.c ├── cpucycles.h ├── crt_trees.c ├── main_signature.c ├── random.c ├── random.h ├── sage.sage ├── sage.sage.py ├── sampling.c ├── sampling.h ├── sampling_tests.c ├── script.sage ├── signature.c ├── signature.h ├── signature_tests.c └── timing.c /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py linguist-vendored 2 | -------------------------------------------------------------------------------- /Module_BFRS/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #CC = gcc 3 | CC = clang 4 | CFLAGS = -Wall -O3 -mtune=native 5 | CVECFLAGS := $(CFLAGS) -mavx2 -ftree-vectorize #-fopt-info-vec-optimized 6 | CFLAGS += -fno-tree-vectorize 7 | NFL_AVX = -DNFL_OPTIMIZED=ON -DNTT_AVX2 8 | 9 | EXEC = signature_tests sampling_tests timing main_signature 10 | 11 | OBJ = arithmetic.o random.o crt_trees.o 12 | 13 | HDR = common.h 14 | 15 | all: sampling_tests signature_tests 16 | 17 | timing: timing.o crt_trees.o ibe.o signature.o sampling.o random.o arithmetic.o cpucycles.o 18 | $(CC) $(CFLAGS) -o $@ $^ -lm 19 | 20 | signature_tests: signature_tests.o ibe.o signature.o sampling.o random.o arithmetic.o crt_trees.o 21 | $(CC) $(CFLAGS) -o $@ $^ -lm 22 | 23 | main_signature: main_signature.o ibe.o signature.o sampling.o random.o $(OBJ) 24 | $(CC) $(CFLAGS) -o $@ $^ -lm 25 | 26 | sampling_tests: sampling_tests.o sampling.o random.o arithmetic.o crt_trees.o 27 | $(CC) $(CFLAGS) -o $@ $^ -lm 28 | 29 | 30 | arithmetic.o: arithmetic.c random.o $(HDR) 31 | $(CC) $(CVECFLAGS) -c -o $@ $< 32 | 33 | sampling.o: sampling.c random.o $(HDR) 34 | $(CC) $(CVECFLAGS) -c -o $@ $< 35 | 36 | random.o: random.c 37 | $(CC) $(CVECFLAGS) -maes -c -o $@ $< 38 | 39 | %.o: %.c $(HDR) 40 | $(CC) $(CFLAGS) -c -o $@ $< 41 | 42 | clean: 43 | rm -f $(EXEC) *.o *.s 44 | -------------------------------------------------------------------------------- /Module_BFRS/Misc/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -g -Wall 3 | 4 | EXEC = multiplicative_order primes 5 | 6 | all: $(EXEC) 7 | 8 | multiplicative_order: multiplicative_order.c 9 | $(CC) $(CFLAGS) -o $@ $^ 10 | 11 | primes: primes.c 12 | $(CC) $(CFLAGS) -o $@ $^ -lgmp 13 | 14 | clean: 15 | rm -f $(EXEC) 16 | -------------------------------------------------------------------------------- /Module_BFRS/Misc/multiplicative_order.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // a^x mod m 6 | uint64_t mod_exp(uint64_t a, uint64_t x, uint64_t m) 7 | { 8 | uint64_t r = 1; 9 | 10 | for(int i=0 ; i < 64 ; i++) 11 | { 12 | if(x & 1) 13 | { 14 | r = (((r * a) % m) + m) % m; 15 | } 16 | a = (((a * a) % m) + m) % m; 17 | x = x >> 1; 18 | } 19 | 20 | return r; 21 | } 22 | 23 | // multiplicative order of a mod 2^e 24 | uint64_t order(uint64_t a, uint64_t e) 25 | { 26 | uint64_t ones = (1 << e) - 1; 27 | 28 | for(int i=0 ; i < e ; i++) 29 | { 30 | if(a == 1) 31 | { 32 | return (1 << i); 33 | } 34 | a = (a * a) & ones; 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | if(argc < 4) 43 | { 44 | fprintf(stderr, "Usage : %s a e d\n", argv[0]); 45 | exit(EXIT_FAILURE); 46 | } 47 | 48 | uint64_t a, e, a_i, d; 49 | 50 | sscanf(argv[1], "%" SCNu64, &a); 51 | sscanf(argv[2], "%" SCNu64, &e); 52 | sscanf(argv[3], "%" SCNu64, &d); 53 | 54 | uint64_t ones = (1 << e) - 1; 55 | 56 | for(int i=1 ; i <= d ; i++) 57 | { 58 | a_i = mod_exp(a, i, (1 << e)); 59 | printf("%" PRIu64 " = %" PRIu64 "^%d has multiplicative order %" PRIu64 " mod 2^%" PRIu64 "\n", a_i, a, i, order(a_i, e), e); 60 | } 61 | 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /Module_BFRS/Misc/primes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | mpz_t N; 9 | uint64_t n; 10 | 11 | mpz_init(N); 12 | 13 | printf("Finding sparse primes congruent to 17 mod 32...\n"); 14 | 15 | printf("Finding primes of the form 2^i + 2^4 + 1...\n"); 16 | for(uint64_t i = 5 ; i < 64 ; i++) 17 | { 18 | n = (((uint64_t) 1)< 5 | #include 6 | 7 | 8 | #include "common.h" 9 | 10 | int get_bit_b(scalar x, scalar i); 11 | 12 | void ntt(uint32_t p[PARAM_N]); 13 | 14 | void invntt_frominvmont(uint32_t p[PARAM_N]); 15 | 16 | void divide_by_2pow32(poly f, int deg); 17 | 18 | void multiply_by_2pow32(poly f, int deg); 19 | 20 | scalar barrett_reduce(double_scalar a); 21 | 22 | scalar csubq(scalar a); 23 | 24 | uint32_t montgomery_reduce(uint64_t a); 25 | 26 | void poly_pointwise_invmontgomery(poly c, const poly a, const poly b); 27 | 28 | void matrix_ntt(poly_matrix A, int l1, int l2); 29 | 30 | void matrix_invntt(poly_matrix A, int l1, int l2); 31 | 32 | scalar reduce_naive(scalar x); 33 | 34 | signed_scalar reduce_signed_double_naive(signed_double_scalar x); 35 | 36 | scalar reduce_signed_double_to_positive_naive(signed_double_scalar x); 37 | 38 | scalar reduce_signed_naive(signed_scalar x); 39 | 40 | scalar reduce_sparse(scalar x); 41 | 42 | scalar reduce_double_naive(double_scalar x); 43 | 44 | scalar reduce_double_sparse(double_scalar x); 45 | 46 | scalar reduce_double_montgomery(double_scalar x); 47 | 48 | signed_scalar signed_scalar_inverse(signed_scalar x); 49 | 50 | void polynomial_division(signed_poly quo, signed_poly rem, signed_poly a, signed_poly b, int deg_a, int deg_b); 51 | 52 | void invert_poly(poly f_inv, poly f, int deg, scalar c); 53 | 54 | void alloc_poly(poly f, int deg); 55 | 56 | void alloc_double_poly(double_poly f, int deg); 57 | 58 | void free_poly(poly f); 59 | 60 | void free_double_poly(double_poly f); 61 | 62 | void print_poly(poly f, int deg); 63 | 64 | void print_double_poly(double_poly f, int deg); 65 | 66 | void print_signed_poly(signed_poly f, int deg); 67 | 68 | void print_signed_double_poly(signed_double_poly f, int deg); 69 | 70 | void print_poly_matrix(poly_matrix A, int l1, int l2); 71 | 72 | void print_signed_poly_matrix(signed_poly_matrix A, int l1, int l2); 73 | 74 | bool equals_poly(poly f, poly g, int deg); 75 | 76 | void print_cplx_poly(cplx_poly f, int deg); 77 | 78 | void print_cplx_poly_matrix(cplx_poly_matrix A, int l1, int l2); 79 | 80 | void print_triangular_cplx_poly_matrix(cplx_poly_matrix A, int l); 81 | 82 | void zero_poly(poly f, int deg); 83 | 84 | bool is_zero_poly(poly f, int deg); 85 | 86 | void freeze_poly(poly f, int deg); 87 | 88 | void freeze_double_poly(poly f, double_poly double_f, int deg); 89 | 90 | void freeze_upper_half_double_poly(double_poly double_f, int deg); 91 | 92 | void freeze_signed_poly(poly f_out, signed_poly f_in, int deg); 93 | 94 | void freeze_signed_double_poly(signed_poly f_out, signed_double_poly f_in, int deg); 95 | 96 | void freeze_signed_double_poly_to_positive(poly f_out, signed_double_poly f_in, int deg); 97 | 98 | void random_poly(poly f, int deg); 99 | 100 | void add_poly(poly h, poly f, poly g, int deg); 101 | 102 | void add_double_poly(double_poly h, double_poly f, double_poly g, int deg); 103 | 104 | void add_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 105 | 106 | void sub_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 107 | 108 | void sub_poly(poly h, poly f, poly g, int deg); 109 | 110 | void mul_full_poly_naive(poly h, poly f, poly g); 111 | 112 | void mul_poly_naive(poly h, poly f, poly g, int deg, scalar c); 113 | 114 | void mul_poly_crt(poly h, poly f, poly g); 115 | 116 | void mul_poly_crt_rec(poly h, poly f, poly g, int depth, int index); 117 | 118 | void mul_poly_crt_with_max_depth(poly h, poly f, poly g, int depth, int index, int max_depth); 119 | 120 | void reduce_poly_mod_sparse(poly h, poly f, int deg, scalar c); 121 | 122 | void modulo_cyclotomic_poly(poly f); 123 | 124 | void modulo_cyclotomic_signed_poly(signed_poly f); 125 | 126 | void modulo_cyclotomic_double_poly(double_poly f); 127 | 128 | void invert_crt(poly f, poly f1, poly f2, int deg, scalar c1, scalar c2, scalar u, scalar v); 129 | 130 | void crt_representation(poly f, int max_depth); 131 | 132 | void coeffs_representation(poly f, int max_depth); 133 | 134 | void mul_crt_poly(double_poly crt_h, poly crt_f, poly crt_g, int depth); 135 | 136 | void reduce_double_crt_poly(poly crt_f, double_poly double_crt_f, int depth); 137 | 138 | 139 | 140 | void mul_poly_schoolbook(double_poly h, poly f, poly g, int deg_f, int deg_g); 141 | 142 | void mul_signed_poly_schoolbook(signed_double_poly h, signed_poly f, signed_poly g, int deg_f, int deg_g); 143 | 144 | void mul_signed_poly_karatsuba(signed_poly h, signed_poly f, signed_poly g, int deg); 145 | 146 | void mul_poly_karatsuba(poly h, poly f, poly g, int deg); 147 | 148 | void modulo_poly(double_poly p, poly f, int deg, scalar c); 149 | 150 | void modulo_double_poly(double_poly f, int deg, scalar c); 151 | 152 | void modulo_signed_poly(signed_double_poly f_out, signed_poly f_in, int deg, scalar c); 153 | 154 | void mul_and_reduce_full_poly_karatsuba(poly h, poly f, poly g); 155 | 156 | void matrix_crt_representation(poly_matrix A, int l1, int l2, int depth); 157 | 158 | void matrix_coeffs_representation(poly_matrix A, int l1, int l2, int depth); 159 | 160 | void mul_crt_poly_matrix(poly_matrix H, poly_matrix F, poly_matrix G, int l1, int l2, int l3, int depth); 161 | 162 | void add_to_poly_matrix(poly_matrix A, poly_matrix B, int l1, int l2); 163 | 164 | void multiply_by_scalar_gadget_vector(scalar *prod, signed_scalar *v); 165 | 166 | void multiply_by_ring_gadget_vector(poly prod, signed_poly_matrix v); 167 | 168 | void multiply_by_module_gadget_matrix(poly_matrix res, signed_poly_matrix v); 169 | 170 | void multiply_by_A(poly_matrix y, poly_matrix A, poly_matrix x); 171 | 172 | void multiply_by_TI(poly_matrix y, poly_matrix T, poly_matrix x); 173 | 174 | void multiply_by_T(poly_matrix y, poly_matrix T, poly_matrix x); 175 | 176 | void construct_A_m(poly_matrix A, scalar *m); 177 | 178 | void deconstruct_A_m(poly_matrix A, scalar *m); 179 | 180 | double_scalar norm_squared(poly_matrix v, int l); 181 | 182 | void zero_cplx_poly(cplx_poly f, int deg); 183 | 184 | void add_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 185 | 186 | void fma_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 187 | 188 | void sub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 189 | 190 | void fmsub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 191 | 192 | void inv_cplx_poly(cplx_poly h, cplx_poly f, int deg); 193 | 194 | void mul_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 195 | 196 | void div_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 197 | 198 | void mul_cplx_poly_by_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 199 | 200 | void mul_cplx_poly_by_own_transpose(cplx_poly h, cplx_poly f, int deg); 201 | 202 | void cplx_fma_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 203 | 204 | void fmsub_transpose_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 205 | 206 | void transpose_cplx_poly(cplx_poly f, int deg); 207 | 208 | void stride(cplx_poly f, int depth); 209 | 210 | void inverse_stride(cplx_poly f, int depth); 211 | 212 | void scalar_stride(signed_scalar *p, int size); 213 | 214 | void reduce_mod_sparse_cplx_poly(cplx_poly f, int deg, cplx c); 215 | 216 | void cplx_crt_representation(cplx_poly f); 217 | 218 | void matrix_cplx_crt_representation(cplx_poly_matrix M, int l1, int l2); 219 | 220 | void construct_T_schur_complement(cplx_poly_matrix sch_comp, cplx_poly_matrix T); 221 | 222 | void construct_schur_complement_and_center(cplx_poly_matrix M, cplx_poly_matrix c, cplx_poly d, cplx_poly x1, int l); 223 | 224 | void construct_schur_complement(cplx_poly_matrix M, int l); 225 | 226 | void construct_new_center(cplx_poly_matrix c, cplx_poly_matrix M, cplx_poly q1, int l); 227 | 228 | void construct_first_center(cplx_poly_matrix c, cplx_poly_matrix T, cplx_poly_matrix p); 229 | 230 | void construct_complex_private_key(cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix T); 231 | 232 | void init_crt_trees(void); 233 | 234 | void init_cplx_roots_of_unity(void); 235 | 236 | #endif 237 | -------------------------------------------------------------------------------- /Module_BFRS/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // ------------------- 9 | // DEFINING PARAMETERS 10 | // ------------------- 11 | 12 | //#define TESTING_ZETA 13 | 14 | /*// q = 1073741441, d = 4, r = 64 15 | #define PARAM_Q 1073741441 // modulus q 16 | #define PARAM_K 30 // size of q 17 | #define PARAM_N 256 // degree of polynomials 18 | #define PARAM_R 64 // number of irreducible factors of x^n + 1 in F_q[x] 19 | #define PARAM_D 4 // rank of the module 20 | #define PARAM_SIGMA 7.00 // Gaussian parameter (generation of the trapdoor) 21 | #define PARAM_ALPHA (48.34) // Gaussian parameter (sampling perturbations) 22 | #define PARAM_ZETA (83832.0) // Gaussian parameter (presampling) 23 | #define PARAM_T 12 // Tailcut 24 | */ 25 | 26 | /*// q = 1073741441, d = 5, r = 64 27 | #define PARAM_Q 1073741441 // modulus q 28 | #define PARAM_K 30 // size of q 29 | #define PARAM_N 256 // degree of polynomials 30 | #define PARAM_R 64 // number of irreducible factors of x^n + 1 in F_q[x] 31 | #define PARAM_D 5 // rank of the module 32 | #define PARAM_SIGMA 5.55 // Gaussian parameter (generation of the trapdoor) 33 | #define PARAM_ALPHA (54.35) // Gaussian parameter (sampling perturbations) 34 | #define PARAM_ZETA (83290.0) // Gaussian parameter (presampling) 35 | #define PARAM_T 14 // Tailcut 36 | #define PARAM_B 2 37 | */ 38 | 39 | // q = 1073740609, d = 6, r = 32 40 | #define PARAM_Q 1073740609 // modulus q 41 | #define PARAM_K 30 // size of q 42 | #define PARAM_N 256 // degree of polynomials 43 | #define PARAM_R 32 // number of irreducible factors of x^n + 1 in F_q[x] 44 | #define PARAM_D 6 // rank of the module 45 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 46 | #define PARAM_ALPHA (60.50) // Gaussian parameter (sampling perturbations) 47 | #define PARAM_ZETA (112522.0) // Gaussian parameter (presampling) 48 | #define PARAM_T 15 // Tailcut 49 | #define PARAM_B 2 50 | #define PARAM_TAU 12 51 | #define PARAM_GAMMA 12 52 | 53 | 54 | /* 55 | #define MONT 4860 56 | #define MONT2 23619600 57 | #define QINV 62745407 58 | #define BARRETT_MULT 4 59 | #define BARRETT_SHIFT 32 60 | */ 61 | 62 | /*// q = 1073739937, d = 4, r = 16 63 | #define PARAM_Q 1073739937 // modulus q 64 | #define PARAM_K 30 // size of q 65 | #define PARAM_N 256 // degree of polynomials 66 | #define PARAM_R 16 // number of irreducible factors of x^n + 1 in F_q[x] 67 | #define PARAM_D 6 // rank of the module 68 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 69 | #define PARAM_ALPHA (60.50) // Gaussian parameter (sampling perturbations) 70 | #define PARAM_ZETA (112522.0) // Gaussian parameter (presampling) 71 | #define PARAM_T 15 // Tailcut 72 | #define PARAM_B 2 73 | */ 74 | /* 75 | #define MONT 7548 76 | #define MONT2 56972304 77 | #define QINV 26743967 78 | #define BARRETT_MULT 4 79 | #define BARRETT_SHIFT 32 80 | */ 81 | 82 | 83 | #define NTT_ALWAYS_REDUCE 84 | 85 | 86 | /*// Test parameter set 87 | //#define PARAM_Q 134218289 // modulus q 88 | //#define PARAM_Q 134221313 89 | #define PARAM_K 28 // size of q 90 | #define PARAM_N 256 // degree of polynomials 91 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 92 | #define PARAM_D 3 // rank of the module 93 | #define PARAM_SIGMA 4.470600 // Gaussian parameter (generation of the trapdoor) 94 | //#define PARAM_ZETA 4569.684701 // C = 0.4 95 | #define PARAM_ZETA 12566.627427 // C = 1.1 96 | //#define PARAM_ZETA 14851.468496 // C = 1.3 97 | //#define PARAM_ZETA 20563.571294 // C = 1.8 98 | #define PARAM_T 11 // Tailcut 99 | #define PARAM_B 2 100 | */ 101 | 102 | 103 | // Test parameter set 104 | // q = 1073740609, d = 6, r = 32 105 | /*#define PARAM_Q 1073740609 // modulus q 106 | #define PARAM_K 19 // size of q 107 | #define PARAM_N 256 // degree of polynomials 108 | #define PARAM_R 32 // number of irreducible factors of x^n + 1 in F_q[x] 109 | #define PARAM_D 6 // rank of the module 110 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 111 | #define PARAM_ALPHA (103.53) // Gaussian parameter (sampling perturbations) 112 | #define PARAM_ZETA (184130.23) // Gaussian parameter (presampling) 113 | #define PARAM_T 15 // Tailcut 114 | #define PARAM_B 3*/ 115 | 116 | /*// Test parameter set 117 | #define PARAM_Q 8388593 // modulus q 118 | #define PARAM_K 23 // size of q 119 | #define PARAM_N 256 // degree of polynomials 120 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 121 | #define PARAM_D 3 // rank of the module 122 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 123 | #define PARAM_ZETA 9129.0 // Gaussian parameter (presampling) 124 | #define PARAM_T 12 // Tailcut 125 | #define PARAM_B 2 126 | */ 127 | 128 | /*// Pauline parameter set, 81-bit classical security 129 | #define PARAM_Q 134218289 // modulus q 130 | #define PARAM_K 28 // size of q 131 | #define PARAM_N 256 // degree of polynomials 132 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 133 | #define PARAM_D 6 // rank of the module 134 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 135 | #define PARAM_ZETA 9129.0 // Gaussian parameter (presampling) 136 | #define PARAM_T 12 // Tailcut 137 | #define PARAM_B 2 138 | */ 139 | 140 | /*// Pauline parameter set, 97-bit classical security 141 | #define PARAM_Q 134218289 // modulus q 142 | #define PARAM_K 28 // size of q 143 | #define PARAM_N 256 // degree of polynomials 144 | #define PARAM_R 7 // number of irreducible factors of x^n + 1 in F_q[x] 145 | #define PARAM_D 6 // rank of the module 146 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 147 | #define PARAM_ZETA 12165.0 // Gaussian parameter (presampling) 148 | #define PARAM_T 12 // Tailcut 149 | #define PARAM_B 2 150 | */ 151 | 152 | // ------------------ 153 | // DERIVED PARAMETERS 154 | // ------------------ 155 | 156 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 157 | #define PARAM_M (PARAM_D * (PARAM_K + 2)) // parameter m ( = d(k+2) for the computational instantiation) 158 | //#define PARAM_ALPHA (3.0 * PARAM_SIGMA) // Gaussian parameter (sampling perturbations) 159 | 160 | /*// Parameters for n = 256, q = 8388593 161 | #define PARAM_Q 8388593 // modulus q 162 | #define PARAM_K 23 // size of q 163 | #define PARAM_N 256 // degree of polynomials 164 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 165 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 166 | */ 167 | 168 | /* 169 | // Parameters for n = 8, q = 8000053 170 | #define PARAM_Q 8000053 // modulus q 171 | #define PARAM_K 23 // size of q 172 | #define PARAM_N 8 // degree of polynomials 173 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 174 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 175 | */ 176 | 177 | /*// Parameters for n = 8, q = 13 178 | #define PARAM_Q 13 // modulus q 179 | #define PARAM_K 4 // size of q 180 | #define PARAM_N 8 // degree of polynomials 181 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 182 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 183 | */ 184 | 185 | /*// Parameters for n = 2, q = 13 186 | #define PARAM_Q 13 // modulus q 187 | #define PARAM_K 4 // size of q 188 | #define PARAM_N 2 // degree of polynomials 189 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 190 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 191 | */ 192 | 193 | /*// Parameters for n = 256, q = 17 194 | #define PARAM_Q 17 // modulus q 195 | #define PARAM_K 5 // size of q 196 | #define PARAM_N 256 // degree of polynomials 197 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 198 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 199 | */ 200 | 201 | /*// Parameters for n = 256, q = 7681 202 | #define PARAM_Q 7681 // modulus q 203 | #define PARAM_K 13 // size of q 204 | #define PARAM_N 256 // degree of polynomials 205 | #define PARAM_R 256 // number of irreducible factors of x^n + 1 in F_q[x] 206 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 207 | */ 208 | 209 | /*// Parameters for n = 256, q = 1032193 210 | #define PARAM_Q 1032193 // modulus q 211 | #define PARAM_K 20 // size of q 212 | #define PARAM_N 256 // degree of polynomials 213 | #define PARAM_R 256 // number of irreducible factors of x^n + 1 in F_q[x] 214 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 215 | */ 216 | 217 | 218 | // LOG_N = base 2 log of n, defines the depth of the complex factorisation tree 219 | #if (PARAM_N == 256) 220 | #define LOG_N 8 221 | #elif (PARAM_N == 512) 222 | #define LOG_N 9 223 | #elif (PARAM_N == 8) 224 | #define LOG_N 3 225 | #else 226 | #error "LOG_N is not defined for this value of PARAM_N" 227 | #endif 228 | 229 | // LOG_R = base 2 log of r, defines the depth of the factorisation tree 230 | #if (PARAM_R == 64) 231 | #define LOG_R 6 232 | #elif (PARAM_R == 32) 233 | #define LOG_R 5 234 | #elif (PARAM_R == 16) 235 | #define LOG_R 4 236 | #elif (PARAM_R == 8) 237 | #define LOG_R 3 238 | #elif (PARAM_R == 2) 239 | #define LOG_R 1 240 | #else 241 | #error "LOG_R is not defined for this value of PARAM_R" 242 | #endif 243 | 244 | #if ((1 << LOG_N) != PARAM_N) 245 | #error "LOG_N is not base 2 log of PARAM_N" 246 | #endif 247 | 248 | #if ((1 << LOG_R) != PARAM_R) 249 | #error "LOG_R is not base 2 log of PARAM_R" 250 | #endif 251 | 252 | /*#if ((1 << PARAM_K) < PARAM_Q) || ((1 << (PARAM_K - 1)) >= PARAM_Q) 253 | #error "PARAM_K is not base 2 log of PARAM_Q" 254 | #endif*/ 255 | 256 | #if (PARAM_K < 2) 257 | #error "PARAM_K < 2, not enough space in cplx_p_coeffs (sample_perturb)" 258 | #endif 259 | 260 | //#define GET_BIT(x, i) (((x) >> (i)) & 1) 261 | 262 | 263 | #define GET_BIT(x, i) get_bit_b(x, i) 264 | #define Q_BIT(i) get_bit_b(PARAM_Q, i) 265 | 266 | //#define DOUBLE_ZERO (((double_scalar) PARAM_Q) << (8*sizeof(double_scalar) - PARAM_K - 1)) // a double_scalar that is 0 mod q, such that there will be no underflow nor overflow during computations 267 | #define DOUBLE_ZERO (((double_scalar) PARAM_Q) * PARAM_Q) // a double_scalar that is 0 mod q, such that there will be no underflow nor overflow during computations 268 | #define SIGNED_DOUBLE_ZERO (((double_scalar) PARAM_Q) << (8*sizeof(double_scalar) - PARAM_K - 2)) 269 | 270 | typedef uint32_t scalar; 271 | typedef uint64_t double_scalar; 272 | typedef int32_t signed_scalar; 273 | typedef int64_t signed_double_scalar; 274 | 275 | typedef double complex cplx; 276 | typedef cplx *cplx_poly; 277 | typedef cplx *cplx_poly_matrix; 278 | 279 | #if (PARAM_Q > 0x7FFFFFFF) 280 | #error "Modulus PARAM_Q does not fit in 31 bits" 281 | #endif 282 | 283 | /* 284 | #if (LOG_N - LOG_R + 2 * PARAM_K) >= 63 285 | #error "(n/r)*q^2 >= 2^63, there might be overflow in polynomial multiplication" 286 | #endif 287 | */ 288 | // Polynomial in standard (coefficients) representation 289 | typedef scalar *poly; 290 | 291 | // Non-normalized polynomial with double_scalar coefficients 292 | typedef double_scalar *double_poly; 293 | 294 | // Polynomial with signed coefficients (used in Karatsuba) 295 | typedef signed_scalar *signed_poly; 296 | 297 | // Polynomial with signed_double_scalar coefficients (used in Karatsuba) 298 | typedef signed_double_scalar *signed_double_poly; 299 | 300 | // Matrix of polynomials (single pointer on scalars, everything is accessed through macros) 301 | typedef scalar *poly_matrix; 302 | 303 | // Matrix of signed polynomials, used when sampling since Gaussian values are signed 304 | typedef signed_scalar *signed_poly_matrix; 305 | 306 | #define poly_matrix_element(M, nb_col, i, j) (&M[(PARAM_N)*(((i)*(nb_col)) + (j))]) 307 | 308 | #define crt_poly_component(f, deg, i) (&(f)[(i)*(deg)]) 309 | 310 | #define triangular_poly_matrix_element(M, i, j) (&M[(PARAM_N) * ((i)*((i)+1)/2 + (j))]) 311 | 312 | extern scalar cyclotomic_factorisation_array[2*PARAM_R - 1]; 313 | extern scalar *cyclotomic_factorisation_tree[LOG_R + 1]; 314 | extern scalar bezout_coefficients_array[2*PARAM_R - 1]; 315 | extern scalar *bezout_coefficients_tree[LOG_R + 1]; 316 | extern cplx cplx_roots_of_unity[2*PARAM_N - 1]; 317 | 318 | //#define cplx_root_of_unity_of_order(k, i) (cplx_roots_of_unity[(2 * (PARAM_N) / (k) * (i))]) 319 | 320 | #define cplx_cyclotomic_factorisation_tree(i, j) (cplx_roots_of_unity[(1 << (i)) + (j) - 1]) 321 | 322 | /* 323 | Stuff for Gaussian sampling 324 | */ 325 | typedef long double RR_t; 326 | typedef double real; 327 | #define LDRMX ((RR_t) RAND_MAX) 328 | #define LOG_2 0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202357581305570326707516L 329 | #define SIGMA_1 0.84932180028801904272150283410288961971514109378435394286159953238339383120795466719298223538163406787061691601172910413284884326532697308797136114023L //sqrt(1/(2*log(2))) 330 | 331 | #endif 332 | -------------------------------------------------------------------------------- /Module_BFRS/cpucycles.c: -------------------------------------------------------------------------------- 1 | #include "cpucycles.h" 2 | 3 | unsigned long long cpucycles_overhead(void) { 4 | unsigned long long t0, t1, overhead = -1; 5 | unsigned int i; 6 | 7 | for(i = 0; i < 100000; ++i) { 8 | t0 = cpucycles_start(); 9 | asm volatile(""); 10 | t1 = cpucycles_stop(); 11 | if(t1 - t0 < overhead) 12 | overhead = t1 - t0; 13 | } 14 | 15 | return overhead; 16 | } 17 | -------------------------------------------------------------------------------- /Module_BFRS/cpucycles.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUCYCLES_H 2 | #define CPUCYCLES_H 3 | 4 | #ifdef DBENCH 5 | #define DBENCH_START() unsigned long long time = cpucycles_start() 6 | #define DBENCH_STOP(t) t += cpucycles_stop() - time - timing_overhead 7 | #else 8 | #define DBENCH_START() 9 | #define DBENCH_STOP(t) 10 | #endif 11 | 12 | #ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ 13 | #ifdef SERIALIZE_RDC 14 | 15 | static inline unsigned long long cpucycles_start(void) { 16 | const unsigned int ecx = (1U << 30) + 1; 17 | unsigned long long result; 18 | 19 | asm volatile("cpuid; movl %1,%%ecx; rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 20 | : "=&a" (result) : "r" (ecx) : "rbx", "rcx", "rdx"); 21 | 22 | return result; 23 | } 24 | 25 | static inline unsigned long long cpucycles_stop(void) { 26 | const unsigned int ecx = (1U << 30) + 1; 27 | unsigned long long result, dummy; 28 | 29 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax; movq %%rax,%0; cpuid" 30 | : "=&r" (result), "=c" (dummy) : "c" (ecx) : "rax", "rbx", "rdx"); 31 | 32 | return result; 33 | } 34 | 35 | #else 36 | 37 | static inline unsigned long long cpucycles_start(void) { 38 | const unsigned int ecx = (1U << 30) + 1; 39 | unsigned long long result; 40 | 41 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 42 | : "=a" (result) : "c" (ecx) : "rdx"); 43 | 44 | return result; 45 | } 46 | 47 | static inline unsigned long long cpucycles_stop(void) { 48 | const unsigned int ecx = (1U << 30) + 1; 49 | unsigned long long result; 50 | 51 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 52 | : "=a" (result) : "c" (ecx) : "rdx"); 53 | 54 | return result; 55 | } 56 | 57 | #endif 58 | #else 59 | #ifdef SERIALIZE_RDC 60 | 61 | static inline unsigned long long cpucycles_start(void) { 62 | unsigned long long result; 63 | 64 | asm volatile("cpuid; rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 65 | : "=a" (result) : : "%rbx", "%rcx", "%rdx"); 66 | 67 | return result; 68 | } 69 | 70 | static inline unsigned long long cpucycles_stop(void) { 71 | unsigned long long result; 72 | 73 | asm volatile("rdtscp; shlq $32,%%rdx; orq %%rdx,%%rax; mov %%rax,%0; cpuid" 74 | : "=r" (result) : : "%rax", "%rbx", "%rcx", "%rdx"); 75 | 76 | return result; 77 | } 78 | 79 | #else 80 | 81 | static inline unsigned long long cpucycles_start(void) { 82 | unsigned long long result; 83 | 84 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 85 | : "=a" (result) : : "%rdx"); 86 | 87 | return result; 88 | } 89 | 90 | static inline unsigned long long cpucycles_stop(void) { 91 | unsigned long long result; 92 | 93 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 94 | : "=a" (result) : : "%rdx"); 95 | 96 | return result; 97 | } 98 | 99 | #endif 100 | #endif 101 | 102 | unsigned long long cpucycles_overhead(void); 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /Module_BFRS/ibe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "arithmetic.h" 10 | #include "sampling.h" 11 | 12 | 13 | 14 | 15 | 16 | 17 | /* 18 | Generates the master public key (A,u) and the master secret key (T, cplx_T, sch_comp). 19 | */ 20 | void Setup(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix u) 21 | { 22 | 23 | // scalar A_hat_coeffs[PARAM_D * PARAM_D * PARAM_N], AprimeT_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N]; 24 | 25 | scalar *A_hat_coeffs = malloc(PARAM_D * PARAM_D * PARAM_N * sizeof(scalar)), *AprimeT_coeffs = malloc(PARAM_D * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 26 | poly_matrix A_hat = A_hat_coeffs, AprimeT = AprimeT_coeffs; 27 | 28 | // A_hat <- U(R_q^{d,d}) is considered to be in the CRT domain 29 | random_poly(A_hat, PARAM_N * PARAM_D * PARAM_D - 1); 30 | 31 | // T <- D_{R^{2d,dk},sigma} 32 | SampleR_matrix_centered((signed_poly_matrix) T, 2*PARAM_D, PARAM_D * PARAM_K, PARAM_SIGMA); 33 | 34 | // Compute the Schur complements (that are necessary to the Gaussian preimage sampling operation) + cplx_T 35 | construct_complex_private_key(cplx_T, sch_comp, T); 36 | 37 | // Add q to each component of T (so that T's coeffs are positive) and put it in the CRT domain 38 | for(int i = 0 ; i < PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K ; ++i) 39 | { 40 | T[i] += PARAM_Q; 41 | } 42 | 43 | matrix_crt_representation(T, 2*PARAM_D, PARAM_D * PARAM_K, LOG_R); 44 | 45 | // AprimeT = A_hat * T2 + T1, where T1 and T2 are the upper and lower half of T 46 | poly_matrix T1 = T, T2 = poly_matrix_element(T, PARAM_D * PARAM_K, PARAM_D, 0); 47 | 48 | mul_crt_poly_matrix(AprimeT, A_hat, T2, PARAM_D, PARAM_D, PARAM_D * PARAM_K, LOG_R); 49 | add_to_poly_matrix(AprimeT, T1, PARAM_D, PARAM_D * PARAM_K); 50 | 51 | // A = (A_hat | -A'T) ( = (I | A_hat | -A'T) implicitly) 52 | for(int i = 0 ; i < PARAM_D ; ++i) 53 | { 54 | poly_matrix A_i0 = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 55 | poly_matrix A_hat_i = poly_matrix_element(A_hat, PARAM_D, i, 0); 56 | 57 | memcpy(A_i0, A_hat_i, PARAM_D * PARAM_N * sizeof(scalar)); 58 | } 59 | for(int i = 0 ; i < PARAM_D ; ++i) 60 | { 61 | poly_matrix A_i1 = poly_matrix_element(A, PARAM_M - PARAM_D, i, PARAM_D); 62 | poly_matrix AprimeT_i = poly_matrix_element(AprimeT, PARAM_D * PARAM_K, i, 0); 63 | for(int j = 0 ; j < PARAM_D * PARAM_K * PARAM_N ; ++j) 64 | { 65 | A_i1[j] = 2*PARAM_Q - AprimeT_i[j]; 66 | } 67 | } 68 | 69 | // Reduce A's coefficients mod q 70 | freeze_poly(A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) - 1); 71 | 72 | 73 | random_poly(u, PARAM_N * PARAM_D - 1); 74 | 75 | 76 | free(A_hat); 77 | free(AprimeT); 78 | } 79 | 80 | 81 | 82 | 83 | 84 | 85 | /* 86 | Generate the secret key of an identity id using the master secret key (T, cplx_T, sch_comp) and the master public key (A,u). 87 | */ 88 | void Extract(poly_matrix x, poly_matrix A, poly_matrix u, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *id) 89 | { 90 | // Compute id's inverse and put it in the CRT domain 91 | scalar id_inv_coeffs[PARAM_N]; 92 | poly id_inv = id_inv_coeffs; 93 | 94 | invert_poly(id_inv, id, PARAM_N, 1); 95 | crt_representation(id_inv, LOG_R); 96 | 97 | // Use id to construct A_id 98 | construct_A_m(A, id); 99 | 100 | // Sample x 101 | // Use of sample_pre_target, which is sample_pre with a target u (needs id_inv as an argument) 102 | sample_pre_target(x, A, T, cplx_T, sch_comp, id_inv, u); 103 | 104 | // Deconstruct A_m 105 | deconstruct_A_m(A, id); 106 | } 107 | 108 | 109 | 110 | 111 | /* 112 | Description de la fonction à compléter. 113 | */ 114 | void Encrypt(poly_matrix A, poly_matrix u, scalar *id, poly M, poly_matrix b, poly c) 115 | { 116 | 117 | // Use id to construct A_id 118 | construct_A_m(A, id); 119 | 120 | 121 | scalar *s_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 122 | poly_matrix s = s_coeffs; 123 | 124 | signed_scalar *e_0_coeffs = malloc((PARAM_M - PARAM_K) * PARAM_N * sizeof(signed_scalar)); 125 | signed_scalar *e_1_coeffs = malloc(PARAM_K * PARAM_N * sizeof(signed_scalar)); 126 | signed_scalar *e_prime_coeffs = malloc(PARAM_N * sizeof(signed_scalar)); 127 | 128 | signed_poly_matrix e_0 = e_0_coeffs, e_1 = e_1_coeffs; 129 | signed_poly e_prime = e_prime_coeffs; 130 | 131 | // Sampling of s 132 | random_poly(s, PARAM_N * PARAM_D - 1); 133 | 134 | // Sampling of the errors 135 | 136 | // e_0 <- D_{R^{m-k,1},tau} 137 | SampleR_matrix_centered(e_0, PARAM_M - PARAM_K, 1, PARAM_TAU); 138 | 139 | // e_1 <- D_{R^{k,1},gamma} 140 | SampleR_matrix_centered(e_1, PARAM_K, 1, PARAM_GAMMA); 141 | 142 | // e_prime <- D_{R,tau} 143 | SampleR_centered(e_prime, PARAM_TAU); 144 | 145 | 146 | 147 | 148 | memset(b, 0, PARAM_M * PARAM_N * sizeof(scalar)); 149 | 150 | signed_scalar *factor1_coeffs = malloc(PARAM_M * PARAM_N * sizeof(signed_scalar)); 151 | signed_scalar *factor1_t_coeffs = malloc(PARAM_M * PARAM_N * sizeof(signed_scalar)); 152 | signed_scalar *s_t_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 153 | signed_scalar *e_0_t_coeffs = malloc((PARAM_M - PARAM_K) * PARAM_N * sizeof(signed_scalar)); 154 | signed_scalar *e_1_t_coeffs = malloc(PARAM_K * PARAM_N * sizeof(signed_scalar)); 155 | 156 | 157 | signed_poly_matrix factor1 = factor1_coeffs, factor1_t = factor1_t_coeffs, s_t = s_t_coeffs, e_0_t = e_0_t_coeffs, e_1_t = e_1_t_coeffs; 158 | 159 | transpose_signed_scalar_matrix2(s_t, s, PARAM_D, 1); 160 | transpose_signed_scalar_matrix(e_0_t, e_0, PARAM_M - PARAM_K, 1); 161 | transpose_signed_scalar_matrix(e_1_t, e_1, PARAM_K, 1); 162 | 163 | matrix_crt_representation((poly_matrix) s_t, 1, PARAM_D, LOG_R); 164 | mul_crt_poly_matrix((poly_matrix) factor1, (poly_matrix) s_t, A, 1, PARAM_D, PARAM_M, LOG_R); 165 | transpose_signed_scalar_matrix(factor1_t, factor1, 1, PARAM_M); 166 | 167 | 168 | scalar *factor2_coeffs = malloc(PARAM_M * PARAM_N * sizeof(scalar)); 169 | scalar *factor2_t_coeffs = malloc(PARAM_M * PARAM_N * sizeof(scalar)); 170 | poly_matrix factor2 = factor2_coeffs, factor2_t = factor2_t_coeffs; 171 | 172 | for (int k = 0 ; k < PARAM_M - PARAM_K ; k++) 173 | { 174 | poly_matrix factor2_k = poly_matrix_element(factor2, PARAM_M, 0, k); 175 | poly_matrix e_0_t_k = (poly_matrix) poly_matrix_element(e_0_t, PARAM_M - PARAM_K, 0, k); 176 | 177 | factor2_k = e_0_t_k; 178 | } 179 | 180 | 181 | for (int k = PARAM_M - PARAM_K ; k < PARAM_M ; k++) 182 | { 183 | poly_matrix factor2_k = poly_matrix_element(factor2, PARAM_M, 0, k); 184 | poly_matrix e_1_t_k = (poly_matrix) poly_matrix_element(e_1_t, PARAM_K, 0, k); 185 | 186 | factor2_k = e_1_t_k; 187 | } 188 | 189 | transpose_signed_scalar_matrix((signed_scalar *) factor2_t, (signed_scalar *) factor2, 1, PARAM_M); 190 | 191 | add_to_poly_matrix(b, (poly_matrix) factor1_t, 1, PARAM_M); 192 | add_to_poly_matrix(b, factor2_t, 1, PARAM_M); 193 | 194 | 195 | scalar *prod_coeffs = malloc(PARAM_N * sizeof(scalar)); 196 | poly_matrix prod = prod_coeffs; 197 | mul_crt_poly_matrix(prod, (poly_matrix) s_t, u, 1, PARAM_D, 1, LOG_R); 198 | 199 | c = poly_matrix_element(prod, 1,0,0); 200 | add_poly(c, c, (poly) e_prime, PARAM_N-1); 201 | 202 | for (int i=0 ; i <= PARAM_N ; i++) 203 | { 204 | M[i] = floor(PARAM_Q /2) * M[i]; 205 | } 206 | 207 | add_poly(c, c, M, PARAM_N-1); 208 | 209 | free(s); 210 | free(e_0_t); 211 | free(e_1_t); 212 | free(e_prime); 213 | free(prod); 214 | 215 | 216 | } 217 | 218 | 219 | 220 | void Decrypt(poly_matrix x, poly_matrix b, poly c, poly M) 221 | { 222 | scalar *res_coeffs = malloc(PARAM_N * sizeof(scalar)); 223 | poly res = res_coeffs; 224 | 225 | scalar *b_t_coeffs = malloc(PARAM_N * PARAM_M * sizeof(scalar)); 226 | poly_matrix b_t = b_t_coeffs; 227 | transpose_scalar_matrix(b_t, b, PARAM_M, 1); 228 | 229 | scalar *factor_coeffs = malloc(PARAM_N * sizeof(scalar)); 230 | poly_matrix factor = factor_coeffs; 231 | 232 | matrix_crt_representation(b_t, 1, PARAM_M, LOG_R); 233 | 234 | for (int i = 0 ; i < PARAM_N * PARAM_M ; i++) 235 | { 236 | x[i] += PARAM_Q; 237 | } 238 | matrix_crt_representation(x, 1, PARAM_M, LOG_R); 239 | 240 | mul_crt_poly_matrix(factor, b_t, x, 1, PARAM_M, 1, LOG_R); 241 | 242 | matrix_coeffs_representation(factor, 1, 1, LOG_R); 243 | 244 | 245 | 246 | for (int i = 0 ; i < PARAM_N ; i++) 247 | { 248 | factor[i] = 2*PARAM_Q + (c[i] - factor[i]); 249 | } 250 | 251 | freeze_poly(factor, PARAM_N-1); 252 | 253 | res = factor; 254 | 255 | 256 | for (int i = 0 ; i < PARAM_N ; i++) 257 | { 258 | if (res[i] < floor(PARAM_Q/2)){ 259 | M[i] = 1; 260 | } 261 | 262 | else { 263 | M[i] = 0; 264 | } 265 | } 266 | 267 | } 268 | 269 | 270 | /*bool Verify_target(poly_matrix nu, poly_matrix A, scalar *m, poly_matrix u) 271 | { 272 | // Verify that A * nu = u mod q 273 | scalar prod_coeffs[PARAM_N * PARAM_D]; 274 | poly_matrix prod = prod_coeffs; 275 | 276 | construct_A_m(A, m); 277 | multiply_by_A(prod, A, (poly_matrix) nu); 278 | deconstruct_A_m(A, m); 279 | 280 | sub_poly(prod, prod, u, PARAM_N * PARAM_D - 1); // vérif. parameters 281 | 282 | 283 | if(!is_zero_poly(prod, PARAM_N * PARAM_D - 1)) 284 | { 285 | 286 | printf("prod (CRT)\n"); 287 | print_poly_matrix(prod, PARAM_D, 1); 288 | 289 | return false; 290 | } 291 | 292 | 293 | // Verify that nu has a small norm 294 | // matrix_coeffs_representation(nu, PARAM_M, 1, LOG_R); 295 | 296 | // double_scalar norm_nu_squared = norm_squared((poly_matrix) nu, PARAM_M); 297 | // double bound_squared = PARAM_T * PARAM_T * PARAM_ZETA * PARAM_ZETA * PARAM_N * PARAM_M; 298 | 299 | // matrix_crt_representation(nu, PARAM_M, 1, LOG_R); 300 | 301 | // if(norm_nu_squared >= bound_squared) 302 | // { 303 | // printf("norm^2 = %" PRIu64 " %c bound^2 = %f\n", norm_nu_squared, (norm_nu_squared < bound_squared)?'<':'>', bound_squared); 304 | 305 | // return false; 306 | // } 307 | 308 | return true; 309 | }*/ -------------------------------------------------------------------------------- /Module_BFRS/ibe.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void Setup(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix u); 6 | 7 | void Extract(poly_matrix x, poly_matrix A, poly_matrix u, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *id); 8 | 9 | void Encrypt(poly_matrix A, poly_matrix u, scalar *id, poly M, poly_matrix b, poly c); 10 | 11 | void Decrypt(poly_matrix x, poly_matrix b, poly c, poly M); 12 | -------------------------------------------------------------------------------- /Module_BFRS/main_signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "arithmetic.h" 9 | #include "sampling.h" 10 | #include "signature.h" 11 | #include "ibe.h" 12 | 13 | void check_trapgen(void) 14 | { 15 | scalar A_coeffs[PARAM_D * (PARAM_M - PARAM_D) * PARAM_N], TI_coeffs[PARAM_M * PARAM_D * PARAM_K * PARAM_N], prod_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N], AwithI_coeffs[PARAM_D * PARAM_M * PARAM_N]; 16 | poly_matrix A = A_coeffs, T = TI_coeffs, TI = TI_coeffs, Idk = poly_matrix_element(TI, PARAM_D * PARAM_K, 2*PARAM_D, 0), prod = prod_coeffs, AwithI = AwithI_coeffs; 17 | 18 | // Generate A and T 19 | TrapGen(A, T); 20 | 21 | // Generate Idk (in the CRT domain) and append it to T vertically 22 | memset(Idk, 0, PARAM_D * PARAM_K * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 23 | for(int i = 0 ; i < PARAM_D * PARAM_K ; ++i) 24 | { 25 | poly p_i = poly_matrix_element(Idk, PARAM_D * PARAM_K, i, i); 26 | for(int j = 0 ; j < PARAM_R ; ++j) 27 | { 28 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 29 | p_ij[0] = 1; 30 | } 31 | } 32 | 33 | // Prepend Id (in the CRT domain) to A horizontally 34 | for(int i = 0 ; i < PARAM_D ; ++i) 35 | { 36 | poly_matrix AwithI_i = poly_matrix_element(AwithI, PARAM_M, i, 0); 37 | poly_matrix A_i = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 38 | 39 | // build Id 40 | memset(AwithI_i, 0, PARAM_D * PARAM_N * sizeof(scalar)); 41 | poly p_i = poly_matrix_element(AwithI, PARAM_M, i, i); 42 | for(int j = 0 ; j < PARAM_R ; ++j) 43 | { 44 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 45 | p_ij[0] = 1; 46 | } 47 | 48 | // copy A 49 | memcpy(poly_matrix_element(AwithI_i, PARAM_M, 0, PARAM_D), A_i, (PARAM_M - PARAM_D) * PARAM_N * sizeof(scalar)); 50 | } 51 | 52 | 53 | // prod = AwithI * TI 54 | mul_crt_poly_matrix(prod, AwithI, TI, PARAM_D, PARAM_M, PARAM_D * PARAM_K, LOG_R); 55 | 56 | 57 | 58 | for(int i = 0 ; i < PARAM_D * PARAM_D * PARAM_K * PARAM_N ; ++i) 59 | { 60 | if(prod[i] != 0) 61 | { 62 | printf("%d : %" PRIu32 "\n", i, prod[i]); 63 | } 64 | else 65 | { 66 | } 67 | } 68 | } 69 | 70 | int main(int argc, char **argv) 71 | { 72 | init_crt_trees(); 73 | init_D_lattice_coeffs(); 74 | init_cplx_roots_of_unity(); 75 | 76 | srand48(0); 77 | srand(0); 78 | 79 | 80 | check_trapgen(); 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /Module_BFRS/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "random.h" 10 | 11 | /* 12 | Returns an integer sampled from the uniform distribution over [0, n] 13 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 14 | */ 15 | uint32_t uniform_int_distribution(uint32_t n) 16 | { 17 | uint32_t scaling = (UINT32_MAX) / (n + 1); 18 | uint32_t past = (n + 1) * scaling; 19 | uint32_t r_data[4]; 20 | 21 | while(true) 22 | { 23 | random_bytes((uint8_t *) r_data); 24 | 25 | for(int i = 0 ; i < 4 ; ++i) 26 | { 27 | uint32_t r = r_data[i]; 28 | 29 | if(r < past) 30 | { 31 | return r / scaling; 32 | } 33 | } 34 | } 35 | } 36 | 37 | /* 38 | Returns an integer sampled from the uniform distribution over [0, q-1] 39 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 40 | */ 41 | scalar uniform_mod_q(void) 42 | { 43 | uint32_t scaling = (UINT32_MAX) / PARAM_Q; 44 | uint32_t past = PARAM_Q * scaling; 45 | uint32_t r_data[4]; 46 | 47 | while(true) 48 | { 49 | random_bytes((uint8_t *) r_data); 50 | 51 | for(int i = 0 ; i < 4 ; ++i) 52 | { 53 | uint32_t r = r_data[i]; 54 | 55 | if(r < past) 56 | { 57 | return r / scaling; 58 | } 59 | } 60 | } 61 | } 62 | 63 | /* 64 | Code from random_aesni.c 65 | */ 66 | 67 | //macros 68 | #define DO_ENC_BLOCK(m,k) \ 69 | do{\ 70 | m = _mm_xor_si128 (m, k[ 0]); \ 71 | m = _mm_aesenc_si128 (m, k[ 1]); \ 72 | m = _mm_aesenc_si128 (m, k[ 2]); \ 73 | m = _mm_aesenc_si128 (m, k[ 3]); \ 74 | m = _mm_aesenc_si128 (m, k[ 4]); \ 75 | m = _mm_aesenc_si128 (m, k[ 5]); \ 76 | __auto_type m5 = m;\ 77 | m = _mm_aesenc_si128 (m, k[ 6]); \ 78 | m = _mm_aesenc_si128 (m, k[ 7]); \ 79 | m = _mm_aesenc_si128 (m, k[ 8]); \ 80 | m = _mm_aesenc_si128 (m, k[ 9]); \ 81 | m = _mm_aesenclast_si128(m, k[10]);\ 82 | m = _mm_xor_si128(m, m5);\ 83 | }while(0) 84 | 85 | #define DO_DEC_BLOCK(m,k) \ 86 | do{\ 87 | m = _mm_xor_si128 (m, k[10+0]); \ 88 | m = _mm_aesdec_si128 (m, k[10+1]); \ 89 | m = _mm_aesdec_si128 (m, k[10+2]); \ 90 | m = _mm_aesdec_si128 (m, k[10+3]); \ 91 | m = _mm_aesdec_si128 (m, k[10+4]); \ 92 | m = _mm_aesdec_si128 (m, k[10+5]); \ 93 | m = _mm_aesdec_si128 (m, k[10+6]); \ 94 | m = _mm_aesdec_si128 (m, k[10+7]); \ 95 | m = _mm_aesdec_si128 (m, k[10+8]); \ 96 | m = _mm_aesdec_si128 (m, k[10+9]); \ 97 | m = _mm_aesdeclast_si128(m, k[0]);\ 98 | }while(0) 99 | 100 | #define AES_128_key_exp(k, rcon) aes_128_key_expansion(k, _mm_aeskeygenassist_si128(k, rcon)) 101 | 102 | //the expanded key 103 | static __m128i key_schedule[20]; 104 | static uint64_t ctr = 0; 105 | 106 | static __m128i aes_128_key_expansion(__m128i key, __m128i keygened){ 107 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3)); 108 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 109 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 110 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 111 | return _mm_xor_si128(key, keygened); 112 | } 113 | 114 | static void aes128_load_key(const int8_t * enc_key){ 115 | key_schedule[0] = _mm_loadu_si128((const __m128i*) enc_key); 116 | key_schedule[1] = AES_128_key_exp(key_schedule[0], 0x01); 117 | key_schedule[2] = AES_128_key_exp(key_schedule[1], 0x02); 118 | key_schedule[3] = AES_128_key_exp(key_schedule[2], 0x04); 119 | key_schedule[4] = AES_128_key_exp(key_schedule[3], 0x08); 120 | key_schedule[5] = AES_128_key_exp(key_schedule[4], 0x10); 121 | key_schedule[6] = AES_128_key_exp(key_schedule[5], 0x20); 122 | key_schedule[7] = AES_128_key_exp(key_schedule[6], 0x40); 123 | key_schedule[8] = AES_128_key_exp(key_schedule[7], 0x80); 124 | key_schedule[9] = AES_128_key_exp(key_schedule[8], 0x1B); 125 | key_schedule[10] = AES_128_key_exp(key_schedule[9], 0x36); 126 | 127 | // generate decryption keys in reverse order. 128 | // k[10] is shared by last encryption and first decryption rounds 129 | // k[0] is shared by first encryption round and last decryption round (and is the original user key) 130 | // For some implementation reasons, decryption key schedule is NOT the encryption key schedule in reverse order 131 | key_schedule[11] = _mm_aesimc_si128(key_schedule[9]); 132 | key_schedule[12] = _mm_aesimc_si128(key_schedule[8]); 133 | key_schedule[13] = _mm_aesimc_si128(key_schedule[7]); 134 | key_schedule[14] = _mm_aesimc_si128(key_schedule[6]); 135 | key_schedule[15] = _mm_aesimc_si128(key_schedule[5]); 136 | key_schedule[16] = _mm_aesimc_si128(key_schedule[4]); 137 | key_schedule[17] = _mm_aesimc_si128(key_schedule[3]); 138 | key_schedule[18] = _mm_aesimc_si128(key_schedule[2]); 139 | key_schedule[19] = _mm_aesimc_si128(key_schedule[1]); 140 | } 141 | 142 | static void aes128_enc(const int8_t * restrict plainText, int8_t * restrict cipherText){ 143 | __m128i m = _mm_loadu_si128((__m128i *) plainText); 144 | 145 | DO_ENC_BLOCK(m,key_schedule); 146 | 147 | _mm_storeu_si128((__m128i *) cipherText, m); 148 | } 149 | 150 | 151 | //public API 152 | void random_bytes_init(void) { 153 | // Open random file 154 | int randomData = open("/dev/urandom", O_RDONLY); 155 | 156 | // Seed the AES key 157 | uint8_t seed[16]; 158 | read(randomData, seed, sizeof(uint8_t)*16); 159 | aes128_load_key((int8_t *) seed); // don't know why the AES key is signed but whatever 160 | ctr = 0; 161 | 162 | // Don't forget to close the file !!! 163 | close(randomData); 164 | } 165 | 166 | void random_bytes(uint8_t * restrict data) { 167 | uint8_t plaintext[16] = {0}; 168 | *((uint64_t *) plaintext) = ctr++; 169 | aes128_enc((int8_t *) plaintext, (int8_t *) data); // let's cast them to signed because why not 170 | } 171 | 172 | /* 173 | Code from exp_aes.cpp 174 | */ 175 | 176 | double algorithm_EA(uint64_t * n) { 177 | const double ln2 = 0.6931471805599453; // log(2); 178 | const double a = 5.713363152645423; //(4+3*sqrt(2))*log(2); 179 | const double b = 3.414213562373095; // 2+sqrt(2); 180 | const double c = -1.6734053240284923; // -(1+sqrt(2))*log(2); 181 | const double p = 0.9802581434685472; //sqrt(2)*log(2); 182 | const double A = 5.6005707569738075; //a*p; 183 | const double B = 3.3468106480569846; // b*p; 184 | //const double z = c + 2; // unused ? 185 | //const double r = 1.010089582001449; // 8*exp(-z)*b*(b-1)*log(2)/(a*a); // unused ? 186 | //const double h = r - p; // unused ? 187 | const double D = 0.08578643762690495; // 1/(b*b); 188 | const double H = 0.0026106723602095233;// h*D/p; 189 | 190 | uint8_t data[16]; 191 | random_bytes(data); 192 | 193 | const unsigned long long int II = *((uint64_t *) data); 194 | const int j = __builtin_ctzll(II); 195 | const double G = c + j*ln2; 196 | 197 | const double U = *((uint16_t *) (data + 8)) / (UINT16_MAX*1.0); 198 | random_bytes(data); 199 | 200 | (*n)++; 201 | if (U <= p) { 202 | return G + A/(B - U); 203 | } 204 | //unsigned long long k = 0; // unused ? 205 | while(true) { 206 | for(unsigned i = 0; i < 4; i++) { 207 | (*n)++; 208 | const double U1 = *((uint16_t *) (data + i*2)) / (UINT16_MAX*1.0); 209 | const double U2 = *((uint16_t *) (data + i*2 + 8)) / (UINT16_MAX*1.0); 210 | 211 | const double bU1 = b - U1; 212 | const double Y = a/bU1; 213 | const double L = (U2*H + D)*(bU1)*(bU1); 214 | const double Z = Y + c; 215 | 216 | const double LZ = L - 1 + Z; 217 | const double ZZ = Z*Z; 218 | const bool cond1 = LZ <= 0; 219 | const bool cond2 = LZ - ZZ/2 + ZZ*Z/6 <= 0; 220 | const bool cond3 = LZ - ZZ <= 0; 221 | 222 | if (cond1 || cond2 || (cond3 && (L <= exp(-Z)))) { 223 | return G + Y; 224 | } 225 | // if(!cond1 && !cond2 && cond3) { 226 | // (*n)++; 227 | // } 228 | } 229 | random_bytes(data); 230 | } 231 | } 232 | 233 | /* 234 | Code from algoF_aes.cpp 235 | */ 236 | 237 | int algorithmF(double mu, double sigma) { 238 | const double sigma_floor = floor(sigma); 239 | const unsigned sigma_max = (unsigned) (((sigma_floor == sigma) && (sigma_floor != 0)) ? sigma - 1 : (sigma_floor)); 240 | 241 | 242 | uint8_t randomData[16]; 243 | random_bytes(randomData); 244 | while(true) { 245 | for(unsigned i = 0; i < 16; i++) { 246 | uint64_t n = 0; 247 | unsigned k = (unsigned) ceil(2*algorithm_EA(&n)) - 1; 248 | 249 | int s = (randomData[i] > 127) ? -1 : 1; 250 | //printf("\ts = %d\n", s); 251 | unsigned j = uniform_int_distribution(sigma_max); 252 | 253 | int i0 = ceil(sigma*k + s*mu); 254 | double x0 = (i0 - (sigma*k + s*mu))/sigma; 255 | double x = x0 + j/sigma; 256 | 257 | unsigned k1 = (unsigned) ceil(2*algorithm_EA(&n)) - 1; 258 | double z = algorithm_EA(&n); 259 | 260 | bool cond1 = k1 >= k*(k-1); 261 | bool cond2 = x < 1; 262 | bool cond3a = x != 0; 263 | bool cond3b = k != 0; 264 | bool cond3c = s == 1; 265 | bool cond3 = cond3a || cond3b || cond3c; 266 | bool cond4 = z > 0.5*x*(2*k+x); 267 | 268 | if (cond1 && cond2 && cond3 && cond4) { 269 | return s*(i0 + j); 270 | } 271 | } 272 | random_bytes(randomData); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /Module_BFRS/random.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | 6 | uint32_t uniform_int_distribution(uint32_t n); 7 | 8 | scalar uniform_mod_q(void); 9 | 10 | /* 11 | Code from random_aesni.c 12 | */ 13 | 14 | //public API 15 | void random_bytes_init(void); 16 | 17 | void random_bytes(uint8_t * restrict data); 18 | 19 | /* 20 | Code from exp_aes.cpp 21 | */ 22 | 23 | double algorithm_EA(uint64_t * n); 24 | 25 | /* 26 | Code from algoF_aes.cpp 27 | */ 28 | 29 | int algorithmF(double mu, double sigma); 30 | -------------------------------------------------------------------------------- /Module_BFRS/sage.sage: -------------------------------------------------------------------------------- 1 | #q = 7681 2 | #q = 8388593 3 | #q = 8000033 4 | #q = 1073741969 5 | #q = 1032193 6 | #q = 17 7 | #q = 134218289 8 | #q = 33554641 9 | #q = 13 10 | #q = 1073740609 11 | #q = 1073739937 12 | #q = 1073740609 13 | q = 1073741441 14 | n = 256 15 | #n = 512 16 | #r = 16 17 | #r = 32 18 | r = 64 19 | log_r = ceil(log(r, 2)) 20 | K = ceil(log(q, 2)) 21 | d = 2 22 | m = d * (K + 2) 23 | 24 | ZZx. = ZZ[] 25 | GFq = GF(q) 26 | R. = GF(q)[] 27 | Rq. = R.quotient_ring((xx^(n) + 1)) 28 | 29 | def my_ext_euclid(f, g): 30 | (r0, r1, v0, v1) = (g, f, R(0), R(1)) 31 | while r0.degree() != 0: 32 | (q, r) = r0.quo_rem(r1) 33 | (v0, v1) = (v1, v0 - q*v1) 34 | (r0, r1) = (r1, r0 - q*r1) 35 | print "q\n", q, "\nr\n", r, "\nv0\n", v0, "\nv1\n", v1, "\nr0\n", r0, "\nr1\n", r1, "\n" 36 | 37 | def cyclotomic_factorisation_tree(n): 38 | tree = [[GFq(1)]] 39 | i = 1 40 | for i in range(1, n): 41 | primitive_roots = [] 42 | for r in tree[i-1]: 43 | primitive_roots += (-r).square_root(extend=False, all=True) 44 | tree.append(primitive_roots) 45 | return tree 46 | 47 | def bezout_coefficients_tree(c_tree): 48 | b_tree = [[0]] 49 | for i in range(1, len(c_tree)): 50 | b_tree.append(2**i*[0]) 51 | for j in range(2**(i-1)): 52 | #inv1 = (c_tree[i][2*j] - c_tree[i][2*j+1]).inverse_of_unit() 53 | inv1 = GFq((ZZ(c_tree[i][2*j] - c_tree[i][2*j+1])).inverse_mod(q)) 54 | b_tree[i][2*j] = inv1 55 | b_tree[i][2*j+1] = -inv1 56 | return b_tree 57 | 58 | def flatten_tree(tree): 59 | l = [] 60 | for list in tree: 61 | l += list 62 | return l 63 | 64 | def ext_euclid(f, nb): 65 | (r0, r1, v0, v1) = (xx^n + 1, f, R(0), R(1)) 66 | for i in range(nb): 67 | (quo, rem) = r0.quo_rem(r1) 68 | (r0, r1) = (r1, rem) 69 | (v0, v1) = (v1, v0 - quo * v1) 70 | return (r0, r1, quo, v0, v1) 71 | 72 | def crt(f): 73 | crt_f = [R(f.list()).quo_rem(c_f)[1].list() for c_f in cyclo_factors] 74 | return [crt_f_i if crt_f_i != [] else [0] for crt_f_i in crt_f] 75 | 76 | def my_norm(v): 77 | coeffs = [ZZ(v_ij) for v_i in v.list() for v_ij in v_i] 78 | centered_v = vector(ZZ, [v_ij if v_ij < q/2 else (v_ij - q) for v_ij in coeffs]) 79 | return centered_v.norm() 80 | 81 | c_tree = cyclotomic_factorisation_tree(log_r + 1) 82 | b_tree = bezout_coefficients_tree(c_tree) 83 | 84 | print flatten_tree(c_tree) 85 | print flatten_tree(b_tree) 86 | 87 | cyclo_factors = [xx^(n/r) + c for c in c_tree[-1]] 88 | 89 | Rx. = RLF[] 90 | Rr. = Rx.quotient_ring((xxr^n + 1)) 91 | Cx. = CIF[] 92 | Rc. = Cx.quotient_ring((xxc^n + 1)) 93 | 94 | if(n == 8): 95 | cplx_prim_roots = [-e^(I*k*pi/n) for k in [3, 11, 15, 7, 13, 5, 1, 9]] 96 | cplx_roots = [[1], [I, -I], [-e^(I*k*pi/4) for k in [7, 3, 1, 5]], cplx_prim_roots] 97 | 98 | def stride(f): 99 | return Cx([f[i] for i in range(0, len(f.list()), 2)]), Cx([f[i] for i in range(1, len(f.list()), 2)]) 100 | 101 | def inv_cplx_crt(f): 102 | return Cx.lagrange_polynomial(zip(cplx_prim_roots, f)) 103 | 104 | def is_almost_real(f): 105 | return max([abs(f_i.imag()) for f_i in f]) 106 | 107 | def cplx_crt(f): 108 | return Rc([Cx(f.list())(w) for w in cplx_prim_roots]) 109 | 110 | def matrix_cplx_crt(A): 111 | return A.apply_map(cplx_crt) 112 | 113 | def extend_matrix(A): 114 | return block_matrix([[a.matrix().T for a in r] for r in A.rows()]) 115 | 116 | def poly_matrix(A): 117 | return matrix(Rr, [[A[i:i+n, j].list() for j in range(0, A.ncols(), n)] for i in range(0, A.nrows(), n)]) 118 | 119 | stored_A = matrix(Rq) 120 | 121 | 122 | T = matrix(Rc) 123 | 124 | p = matrix() 125 | 126 | h_m = Rq() 127 | 128 | if stored_A.dimensions() != (d, m-d): 129 | print "wrong dimensions for A" 130 | exit 131 | 132 | if T.dimensions() != (2*d, d*K): 133 | print "wrong dimensions for T" 134 | exit 135 | 136 | A = block_matrix([[1, stored_A]]) 137 | TI = block_matrix([[T], [1]]) 138 | 139 | g = matrix(Rq, [2**i for i in range(K)]) 140 | G = block_diagonal_matrix([g for i in range(d)]) 141 | 142 | def construct_A_m(A, h_m): 143 | zero_matrix = matrix(Rq, d, 2*d, 0) 144 | return A + block_matrix([[zero_matrix, h_m * G]]) 145 | 146 | -------------------------------------------------------------------------------- /Module_BFRS/sage.sage.py: -------------------------------------------------------------------------------- 1 | 2 | # This file was *autogenerated* from the file sage.sage 3 | from sage.all_cmdline import * # import sage library 4 | 5 | _sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_7 = Integer(7); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4); _sage_const_256 = Integer(256); _sage_const_8 = Integer(8); _sage_const_13 = Integer(13); _sage_const_11 = Integer(11); _sage_const_1073741969 = Integer(1073741969); _sage_const_15 = Integer(15); _sage_const_9 = Integer(9)#q = 7681 6 | #q = 8388593 7 | #q = 8000033 8 | q = _sage_const_1073741969 9 | #q = 1032193 10 | #q = 17 11 | #q = 134218289 12 | #q = 33554641 13 | #q = 13 14 | n = _sage_const_256 15 | #n = 512 16 | r = _sage_const_8 17 | log_r = _sage_const_3 18 | K = ceil(log(q, _sage_const_2 )) 19 | d = _sage_const_2 20 | m = d * (K + _sage_const_2 ) 21 | 22 | ZZx = ZZ['xz']; (xz,) = ZZx._first_ngens(1) 23 | GFq = GF(q) 24 | R = GF(q)['xx']; (xx,) = R._first_ngens(1) 25 | Rq = R.quotient_ring((xx**(n) + _sage_const_1 ), names=('x',)); (x,) = Rq._first_ngens(1) 26 | 27 | def my_ext_euclid(f, g): 28 | (r0, r1, v0, v1) = (g, f, R(_sage_const_0 ), R(_sage_const_1 )) 29 | while r0.degree() != _sage_const_0 : 30 | (q, r) = r0.quo_rem(r1) 31 | (v0, v1) = (v1, v0 - q*v1) 32 | (r0, r1) = (r1, r0 - q*r1) 33 | print "q\n", q, "\nr\n", r, "\nv0\n", v0, "\nv1\n", v1, "\nr0\n", r0, "\nr1\n", r1, "\n" 34 | 35 | def cyclotomic_factorisation_tree(n): 36 | tree = [[GFq(_sage_const_1 )]] 37 | i = _sage_const_1 38 | for i in range(_sage_const_1 , n): 39 | primitive_roots = [] 40 | for r in tree[i-_sage_const_1 ]: 41 | primitive_roots += (-r).square_root(extend=False, all=True) 42 | tree.append(primitive_roots) 43 | return tree 44 | 45 | def bezout_coefficients_tree(c_tree): 46 | b_tree = [[_sage_const_0 ]] 47 | for i in range(_sage_const_1 , len(c_tree)): 48 | b_tree.append(_sage_const_2 **i*[_sage_const_0 ]) 49 | for j in range(_sage_const_2 **(i-_sage_const_1 )): 50 | #inv1 = (c_tree[i][2*j] - c_tree[i][2*j+1]).inverse_of_unit() 51 | inv1 = GFq((ZZ(c_tree[i][_sage_const_2 *j] - c_tree[i][_sage_const_2 *j+_sage_const_1 ])).inverse_mod(q)) 52 | b_tree[i][_sage_const_2 *j] = inv1 53 | b_tree[i][_sage_const_2 *j+_sage_const_1 ] = -inv1 54 | return b_tree 55 | 56 | def flatten_tree(tree): 57 | l = [] 58 | for list in tree: 59 | l += list 60 | return l 61 | 62 | def ext_euclid(f, nb): 63 | (r0, r1, v0, v1) = (xx**n + _sage_const_1 , f, R(_sage_const_0 ), R(_sage_const_1 )) 64 | for i in range(nb): 65 | (quo, rem) = r0.quo_rem(r1) 66 | (r0, r1) = (r1, rem) 67 | (v0, v1) = (v1, v0 - quo * v1) 68 | return (r0, r1, quo, v0, v1) 69 | 70 | def crt(f): 71 | crt_f = [R(f.list()).quo_rem(c_f)[_sage_const_1 ].list() for c_f in cyclo_factors] 72 | return [crt_f_i if crt_f_i != [] else [_sage_const_0 ] for crt_f_i in crt_f] 73 | 74 | def my_norm(v): 75 | coeffs = [ZZ(v_ij) for v_i in v.list() for v_ij in v_i] 76 | centered_v = vector(ZZ, [v_ij if v_ij < q/_sage_const_2 else (v_ij - q) for v_ij in coeffs]) 77 | return centered_v.norm() 78 | 79 | c_tree = cyclotomic_factorisation_tree(log_r + _sage_const_1 ) 80 | b_tree = bezout_coefficients_tree(c_tree) 81 | 82 | print flatten_tree(c_tree) 83 | print flatten_tree(b_tree) 84 | 85 | cyclo_factors = [xx**(n/r) + c for c in c_tree[-_sage_const_1 ]] 86 | 87 | Rx = RLF['xxr']; (xxr,) = Rx._first_ngens(1) 88 | Rr = Rx.quotient_ring((xxr**n + _sage_const_1 ), names=('xr',)); (xr,) = Rr._first_ngens(1) 89 | Cx = CIF['xxc']; (xxc,) = Cx._first_ngens(1) 90 | Rc = Cx.quotient_ring((xxc**n + _sage_const_1 ), names=('xc',)); (xc,) = Rc._first_ngens(1) 91 | 92 | if(n == _sage_const_8 ): 93 | cplx_prim_roots = [-e**(I*k*pi/n) for k in [_sage_const_3 , _sage_const_11 , _sage_const_15 , _sage_const_7 , _sage_const_13 , _sage_const_5 , _sage_const_1 , _sage_const_9 ]] 94 | cplx_roots = [[_sage_const_1 ], [I, -I], [-e**(I*k*pi/_sage_const_4 ) for k in [_sage_const_7 , _sage_const_3 , _sage_const_1 , _sage_const_5 ]], cplx_prim_roots] 95 | 96 | def stride(f): 97 | return Cx([f[i] for i in range(_sage_const_0 , len(f.list()), _sage_const_2 )]), Cx([f[i] for i in range(_sage_const_1 , len(f.list()), _sage_const_2 )]) 98 | 99 | def inv_cplx_crt(f): 100 | return Cx.lagrange_polynomial(zip(cplx_prim_roots, f)) 101 | 102 | def is_almost_real(f): 103 | return max([abs(f_i.imag()) for f_i in f]) 104 | 105 | def cplx_crt(f): 106 | return Rc([Cx(f.list())(w) for w in cplx_prim_roots]) 107 | 108 | def matrix_cplx_crt(A): 109 | return A.apply_map(cplx_crt) 110 | 111 | def extend_matrix(A): 112 | return block_matrix([[a.matrix().T for a in r] for r in A.rows()]) 113 | 114 | def poly_matrix(A): 115 | return matrix(Rr, [[A[i:i+n, j].list() for j in range(_sage_const_0 , A.ncols(), n)] for i in range(_sage_const_0 , A.nrows(), n)]) 116 | 117 | stored_A = matrix(Rq) 118 | 119 | 120 | T = matrix(Rc) 121 | 122 | p = matrix() 123 | 124 | h_m = Rq() 125 | 126 | if stored_A.dimensions() != (d, m-d): 127 | print "wrong dimensions for A" 128 | exit 129 | 130 | if T.dimensions() != (_sage_const_2 *d, d*K): 131 | print "wrong dimensions for T" 132 | exit 133 | 134 | A = block_matrix([[_sage_const_1 , stored_A]]) 135 | TI = block_matrix([[T], [_sage_const_1 ]]) 136 | 137 | g = matrix(Rq, [_sage_const_2 **i for i in range(K)]) 138 | G = block_diagonal_matrix([g for i in range(d)]) 139 | 140 | def construct_A_m(A, h_m): 141 | zero_matrix = matrix(Rq, d, _sage_const_2 *d, _sage_const_0 ) 142 | return A + block_matrix([[zero_matrix, h_m * G]]) 143 | 144 | 145 | -------------------------------------------------------------------------------- /Module_BFRS/sampling.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void TrapGen(poly_matrix A, poly_matrix T); 6 | 7 | //============================================================================== 8 | // Samples from distribution D_{c,sigma}, ie 9 | // Samples an element in Z with probability proportionnal to e^{-(c-x)^2/2*(sigma^2)} 10 | //============================================================================== 11 | signed int SampleZ(RR_t c, RR_t sigma); 12 | 13 | void SampleR_centered(signed_poly f, RR_t sigma); 14 | 15 | void SampleR_matrix_centered(signed_poly_matrix A, int l1, int l2, RR_t sigma); 16 | 17 | void init_D_lattice_coeffs(void); 18 | 19 | void sample_D(signed_scalar *z, real *c, real sigma); 20 | 21 | void sample_G_perturb(real *p, real sigma); 22 | 23 | void scalar_sample_G(signed_scalar *t, scalar u); 24 | 25 | void ring_sample_G(signed_poly_matrix t, poly u); 26 | 27 | void transpose_scalar_matrix(scalar *A_T, scalar *A, int l0, int l1); 28 | 29 | void transpose_signed_scalar_matrix(signed_scalar *A_T, signed_scalar *A, int l0, int l1); 30 | 31 | void transpose_signed_scalar_matrix2(signed_scalar *A_T, scalar *A, int l0, int l1); 32 | 33 | void module_sample_G(signed_poly_matrix t, poly_matrix u); 34 | 35 | void sample_2z(signed_scalar *q, cplx_poly cplx_q, cplx_poly a, cplx_poly b, cplx_poly d, cplx *c, int deg); 36 | 37 | void sample_fz(signed_scalar *p, cplx_poly cplx_p, cplx_poly f, cplx *c, int deg); 38 | 39 | void sample_perturb(signed_poly_matrix p, cplx_poly_matrix T, cplx_poly_matrix sch_comp); 40 | 41 | void sample_pre(poly_matrix x, poly_matrix A_m, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly h_inv); 42 | 43 | void sample_pre_target(poly_matrix x, poly_matrix A_m, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly h_inv, poly_matrix u); 44 | 45 | extern real d_coeffs[PARAM_K]; 46 | extern real l_coeffs[PARAM_K]; 47 | extern real h_coeffs[PARAM_K]; 48 | -------------------------------------------------------------------------------- /Module_BFRS/script.sage: -------------------------------------------------------------------------------- 1 | #q = 1073740609 2 | #q = 1073739937 3 | q = 1073740609 4 | n = 256 5 | r = 32 6 | #r = 16 7 | 8 | GFq = GF(q) 9 | root = GFq.zeta(2*r) 10 | 11 | def flatten_tree(tree): 12 | l = [] 13 | for list in tree: 14 | l += list 15 | return l 16 | 17 | def montgomery_list(l): 18 | return [l_i * 2^32 for l_i in l] 19 | 20 | def brv(a): 21 | return sum([a_i * 2^i for i, a_i in enumerate(reversed(a.bits()))]) 22 | 23 | def precompute_zetas(root): 24 | assert root.multiplicative_order() == 2*r 25 | 26 | zetas = [] 27 | 28 | k = r // 2 29 | while k > 0: 30 | zetas = [root^brv(k+i) for i in range(k)] + zetas 31 | root = zetas[0]^2 32 | k = k // 2 33 | 34 | zetas = [0] + zetas 35 | zetas_inv = [-zeta for zeta in reversed(zetas)] 36 | 37 | return zetas, zetas_inv 38 | 39 | def list_order(l): 40 | return [l_i.multiplicative_order() if l_i.is_unit() else 0 for l_i in l] 41 | 42 | mont = mod(2^32, q) 43 | mont2 = mod(2^64, q) 44 | q_inv = - mod(q, 2^32)^(-1) 45 | barrett_mult = floor(2^32 / q) 46 | barrett_shift = 32 47 | double_barrett_mult = floor(2^34 / q) 48 | double_barrett_shift = 34 49 | 50 | print "===== common.h =====\n" 51 | print "#define MONT", mont 52 | print "#define MONT2", mont2 53 | print "#define QINV", q_inv 54 | print "#define BARRETT_MULT", barrett_mult 55 | print "#define BARRETT_SHIFT", barrett_shift 56 | print "#define DOUBLE_BARRETT_MULT", double_barrett_mult 57 | print "#define DOUBLE_BARRETT_SHIFT", double_barrett_shift 58 | print "\n" 59 | 60 | zetas, zetas_inv = precompute_zetas(root) 61 | montgomery_zetas = montgomery_list(zetas) 62 | montgomery_zetas_inv = montgomery_list(zetas_inv) 63 | 64 | m_z_str = "{" + ", ".join(map(str, montgomery_zetas)) + "}" 65 | m_z_i_str = "{" + ", ".join(map(str, montgomery_zetas_inv)) + "}" 66 | 67 | print "===== arithmetic.c =====\n" 68 | print "static const scalar zetas[PARAM_R] = " + m_z_str + ";\n" 69 | print "static const scalar zetas_inv[PARAM_R] = " + m_z_i_str + ";\n" 70 | -------------------------------------------------------------------------------- /Module_BFRS/signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "arithmetic.h" 10 | #include "sampling.h" 11 | 12 | /* 13 | Generates a signing key (T, cplx_T, sch_comp) and an associated verification key A 14 | */ 15 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp) 16 | { 17 | 18 | //scalar A_hat_coeffs[PARAM_D * PARAM_D * PARAM_N], AprimeT_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N]; 19 | 20 | // A_hat_coeffs est bien de taille d*d dans l'algo TrapGen + chacun de ses éléménents est un polynôme à n variables 21 | // AprimeT_coeffs désigne A'*T qui est bien de taille d*dk dans l'algo TrapGen. 22 | // Le début de cet algorithme KeyGen ressemble à celui de l'algo TrapGen. Pourquoi n'ont ils pas repris la fonction qu'ils avaient écrit ? 23 | 24 | scalar *A_hat_coeffs = malloc(PARAM_D * PARAM_D * PARAM_N * sizeof(scalar)), *AprimeT_coeffs = malloc(PARAM_D * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 25 | poly_matrix A_hat = A_hat_coeffs, AprimeT = AprimeT_coeffs; 26 | 27 | // A_hat <- U(R_q^{d,d}) is considered to be in the CRT domain 28 | random_poly(A_hat, PARAM_N * PARAM_D * PARAM_D - 1); 29 | 30 | // T <- D_{R^{2d,dk},sigma} 31 | SampleR_matrix_centered((signed_poly_matrix) T, 2*PARAM_D, PARAM_D * PARAM_K, PARAM_SIGMA); 32 | 33 | // Compute the Schur complements 34 | construct_complex_private_key(cplx_T, sch_comp, T); 35 | 36 | // Add q to each component of T and put it in the CRT domain 37 | for(int i = 0 ; i < PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K ; ++i) 38 | { 39 | T[i] += PARAM_Q; 40 | } 41 | 42 | matrix_crt_representation(T, 2*PARAM_D, PARAM_D * PARAM_K, LOG_R); 43 | 44 | // AprimeT = A_hat * T2 + T1, where T1 and T2 are the upper and lower half of T 45 | poly_matrix T1 = T, T2 = poly_matrix_element(T, PARAM_D * PARAM_K, PARAM_D, 0); 46 | 47 | mul_crt_poly_matrix(AprimeT, A_hat, T2, PARAM_D, PARAM_D, PARAM_D * PARAM_K, LOG_R); 48 | add_to_poly_matrix(AprimeT, T1, PARAM_D, PARAM_D * PARAM_K); 49 | 50 | // A = (A_hat | -A'T) ( = (I | A_hat | -A'T) implicitly) 51 | for(int i = 0 ; i < PARAM_D ; ++i) 52 | { 53 | poly_matrix A_i0 = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 54 | poly_matrix A_hat_i = poly_matrix_element(A_hat, PARAM_D, i, 0); 55 | 56 | memcpy(A_i0, A_hat_i, PARAM_D * PARAM_N * sizeof(scalar)); 57 | } 58 | for(int i = 0 ; i < PARAM_D ; ++i) 59 | { 60 | poly_matrix A_i1 = poly_matrix_element(A, PARAM_M - PARAM_D, i, PARAM_D); 61 | poly_matrix AprimeT_i = poly_matrix_element(AprimeT, PARAM_D * PARAM_K, i, 0); 62 | for(int j = 0 ; j < PARAM_D * PARAM_K * PARAM_N ; ++j) 63 | { 64 | A_i1[j] = 2*PARAM_Q - AprimeT_i[j]; 65 | } 66 | } 67 | 68 | // Reduce A's coefficients mod q 69 | freeze_poly(A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) - 1); 70 | 71 | free(A_hat); 72 | free(AprimeT); 73 | } 74 | 75 | /* 76 | Signs a message m using the signing key (T, cplx_T, sch_comp) and the verification key A 77 | */ 78 | void Sign(poly_matrix nu, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *m) 79 | { 80 | // Compute m's inverse and put it in the CRT domain 81 | scalar m_inv_coeffs[PARAM_N]; 82 | poly m_inv = m_inv_coeffs; 83 | 84 | invert_poly(m_inv, m, PARAM_N, 1); 85 | crt_representation(m_inv, LOG_R); 86 | 87 | // Use m to construct A_m 88 | construct_A_m(A, m); 89 | 90 | // Sample nu 91 | sample_pre(nu, A, T, cplx_T, sch_comp, m_inv); 92 | 93 | // Deconstruct A_m 94 | deconstruct_A_m(A, m); 95 | } 96 | 97 | /* 98 | Checks is the signature nu is valid for the message m, given the verification key A 99 | */ 100 | bool Verify(poly_matrix nu, poly_matrix A, scalar *m) 101 | { 102 | // Verify that A * nu = m mod q 103 | scalar prod_coeffs[PARAM_N * PARAM_D]; 104 | poly_matrix prod = prod_coeffs; 105 | 106 | construct_A_m(A, m); 107 | multiply_by_A(prod, A, (poly_matrix) nu); 108 | deconstruct_A_m(A, m); 109 | 110 | 111 | if(!is_zero_poly(prod, PARAM_N * PARAM_D - 1)) 112 | { 113 | 114 | printf("prod (CRT)\n"); 115 | print_poly_matrix(prod, PARAM_D, 1); 116 | 117 | return false; 118 | } 119 | 120 | 121 | // Verify that nu has a small norm 122 | matrix_coeffs_representation(nu, PARAM_M, 1, LOG_R); 123 | 124 | double_scalar norm_nu_squared = norm_squared((poly_matrix) nu, PARAM_M); 125 | double bound_squared = PARAM_T * PARAM_T * PARAM_ZETA * PARAM_ZETA * PARAM_N * PARAM_M; 126 | 127 | matrix_crt_representation(nu, PARAM_M, 1, LOG_R); 128 | 129 | if(norm_nu_squared >= bound_squared) 130 | { 131 | printf("norm^2 = %" PRIu64 " %c bound^2 = %f\n", norm_nu_squared, (norm_nu_squared < bound_squared)?'<':'>', bound_squared); 132 | 133 | return false; 134 | } 135 | 136 | return true; 137 | } 138 | -------------------------------------------------------------------------------- /Module_BFRS/signature.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp); 6 | 7 | void Sign(poly_matrix nu, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *m); 8 | 9 | bool Verify(poly_matrix nu, poly_matrix A, scalar *m); 10 | -------------------------------------------------------------------------------- /Module_BFRS/timing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "random.h" 7 | #include "sampling.h" 8 | #include "signature.h" 9 | #include "ibe.h" 10 | #include "arithmetic.h" 11 | 12 | #include "cpucycles.h" 13 | 14 | #define MESSAGE_BYTES 512 // keep it divisible by 16 15 | #define NTESTS 100 16 | #define CPU_CYCLES (1.9 * 1000000000.0) 17 | 18 | unsigned long long timing_overhead; 19 | unsigned long long timing_sampleZ_G = 0; 20 | unsigned long long timing_sampleZ_P = 0; 21 | unsigned long long timing_sampleG = 0; 22 | unsigned long long timing_samplePerturb = 0; 23 | unsigned long long timing_sampleArith = 0; 24 | 25 | unsigned long long timing_extract = 0; 26 | unsigned long long timing_encrypt = 0; 27 | unsigned long long timing_decrypt = 0; 28 | 29 | unsigned long long timing_sampleZ_Setup = 0; 30 | unsigned long long timing_precomp_Setup = 0; 31 | unsigned long long timing_arith_Setup = 0; 32 | unsigned long long timing_setup = 0; 33 | 34 | void time_setup(void) 35 | { 36 | timing_overhead = cpucycles_overhead(); 37 | unsigned long long begin_timing = 0; 38 | unsigned long long end_timing = 0; 39 | 40 | 41 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 42 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 43 | scalar *u_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 44 | poly_matrix A = A_coeffs, T = T_coeffs, u = u_coeffs; 45 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 46 | 47 | 48 | 49 | for(unsigned i = 0; i < NTESTS; ++i) { 50 | 51 | begin_timing = cpucycles_start(); 52 | 53 | // Generate Keys 54 | Setup(A, T, cplx_T, sch_comp, u); 55 | 56 | end_timing = cpucycles_stop(); 57 | timing_setup += (end_timing - begin_timing); 58 | } 59 | 60 | timing_sampleZ_Setup = timing_sampleZ_Setup/NTESTS - timing_overhead; 61 | timing_precomp_Setup = timing_precomp_Setup/NTESTS - timing_overhead; 62 | timing_arith_Setup = timing_arith_Setup/NTESTS - timing_overhead; 63 | double timing_total = timing_sampleZ_Setup + timing_precomp_Setup + timing_arith_Setup; 64 | 65 | 66 | printf("----------- Setup -----------\n"); 67 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of Setup)\n", timing_sampleZ_Setup, (timing_sampleZ_Setup*1000)/CPU_CYCLES, (timing_sampleZ_Setup/timing_total)*100.0); 68 | printf("Precomp : %lld cycles (%.2lf ms) (%.2lf %% of Setup)\n", timing_precomp_Setup, (timing_precomp_Setup*1000)/CPU_CYCLES, (timing_precomp_Setup/timing_total)*100.0); 69 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of Setup)\n", timing_arith_Setup, (timing_arith_Setup*1000)/CPU_CYCLES, (timing_arith_Setup/timing_total)*100.0); 70 | printf("-----\n"); 71 | 72 | timing_setup = timing_setup/NTESTS - timing_overhead; 73 | printf("Total: %lld cycles (%.2lf ms)\n", timing_setup, (timing_setup*1000)/CPU_CYCLES); 74 | 75 | printf("\n\n"); 76 | 77 | free(A); 78 | free(T); 79 | free(sch_comp); 80 | free(cplx_T); 81 | free(u); 82 | } 83 | 84 | void time_extract(void) 85 | { 86 | timing_overhead = cpucycles_overhead(); 87 | unsigned long long begin_timing = 0; 88 | unsigned long long end_timing = 0; 89 | 90 | 91 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 92 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 93 | scalar *u_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 94 | poly_matrix A = A_coeffs, T = T_coeffs, u = u_coeffs; 95 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 96 | 97 | // Generate Keys 98 | Setup(A, T, cplx_T, sch_comp, u); 99 | 100 | 101 | 102 | for(unsigned i = 0; i < NTESTS; ++i) { 103 | // Generate an identity 104 | scalar id_coeffs[PARAM_N] = {0}; 105 | poly id = id_coeffs; 106 | 107 | random_poly(id, SMALL_DEGREE - 1); 108 | 109 | // Compute a signature (nu) 110 | scalar nu_coeffs[PARAM_N * PARAM_M]; 111 | poly_matrix nu = nu_coeffs; 112 | 113 | begin_timing = cpucycles_start(); 114 | Extract(nu, A, u, T, cplx_T, sch_comp, id); 115 | end_timing = cpucycles_stop(); 116 | timing_extract += (end_timing - begin_timing); 117 | } 118 | 119 | timing_sampleZ_G = timing_sampleZ_G/NTESTS - timing_overhead; 120 | timing_sampleZ_P = timing_sampleZ_P/NTESTS - timing_overhead; 121 | unsigned long long timing_sampleZ = timing_sampleZ_G + timing_sampleZ_P; 122 | 123 | timing_sampleG = timing_sampleG/NTESTS - timing_overhead; 124 | timing_samplePerturb = timing_samplePerturb/NTESTS - timing_overhead; 125 | timing_sampleArith = timing_sampleArith/NTESTS - timing_overhead; 126 | double timing_samplePre = timing_sampleG + timing_samplePerturb + timing_sampleArith; 127 | 128 | 129 | printf("----------- SampleZ -----------\n"); 130 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleG)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, ((double) timing_sampleZ_G/timing_sampleG)*100.0); 131 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleP)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, ((double) timing_sampleZ_P/timing_samplePerturb)*100.0); 132 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ, (timing_sampleZ*1000)/CPU_CYCLES, ((double) timing_sampleZ/timing_samplePre)*100.0); 133 | 134 | 135 | printf("\n----------- SamplePre -----------\n"); 136 | printf("SampleG : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG, (timing_sampleG*1000)/CPU_CYCLES, (timing_sampleG/timing_samplePre)*100.0); 137 | printf("G-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, (timing_sampleZ_G/timing_samplePre)*100.0); 138 | printf("G-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG - timing_sampleZ_G, ((timing_sampleG - timing_sampleZ_G)*1000)/CPU_CYCLES, ((timing_sampleG - timing_sampleZ_G)/timing_samplePre)*100.0); 139 | printf("-----\n"); 140 | 141 | printf("SamplePerturb: %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb, (timing_samplePerturb*1000)/CPU_CYCLES, (timing_samplePerturb/timing_samplePre)*100.0); 142 | printf("P-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, (timing_sampleZ_P/timing_samplePre)*100.0); 143 | printf("P-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb - timing_sampleZ_P, ((timing_samplePerturb - timing_sampleZ_P)*1000)/CPU_CYCLES, ((timing_samplePerturb - timing_sampleZ_P)/timing_samplePre)*100.0); 144 | printf("-----\n"); 145 | 146 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleArith, (timing_sampleArith*1000)/CPU_CYCLES, (timing_sampleArith/timing_samplePre)*100.0); 147 | 148 | printf("\n----------- Extract -----------\n"); 149 | timing_extract = timing_extract/NTESTS - timing_overhead; 150 | printf("Extract: %lld cycles (%.2lf ms)\n", timing_extract, (timing_extract*1000)/CPU_CYCLES); 151 | 152 | printf("\n\n"); 153 | 154 | free(A); 155 | free(T); 156 | free(sch_comp); 157 | free(cplx_T); 158 | free(u); 159 | } 160 | 161 | void time_encrypt(void) 162 | { 163 | timing_overhead = cpucycles_overhead(); 164 | unsigned long long begin_timing = 0; 165 | unsigned long long end_timing = 0; 166 | 167 | 168 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 169 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 170 | scalar *u_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 171 | poly_matrix A = A_coeffs, T = T_coeffs, u = u_coeffs; 172 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 173 | 174 | // Generate Keys 175 | Setup(A, T, cplx_T, sch_comp, u); 176 | 177 | for(unsigned i = 0; i < NTESTS; ++i) { 178 | 179 | // Generate a message 180 | scalar m_coeffs[PARAM_N] = {0}; 181 | poly m = m_coeffs; 182 | 183 | random_poly(m, SMALL_DEGREE - 1); 184 | 185 | // Generate an identity 186 | scalar id_coeffs[PARAM_N] = {0}; 187 | poly id = id_coeffs; 188 | 189 | random_poly(m, SMALL_DEGREE - 1); 190 | 191 | // Compute b and c 192 | scalar *b_coeffs = malloc(PARAM_N * PARAM_M * sizeof(scalar)); 193 | scalar *c_coeffs = malloc(PARAM_N * sizeof(scalar)); 194 | 195 | poly_matrix b = b_coeffs; 196 | poly c = c_coeffs; 197 | 198 | 199 | begin_timing = cpucycles_start(); 200 | Encrypt(A, u, id, m, b, c); 201 | end_timing = cpucycles_stop(); 202 | timing_encrypt += (end_timing - begin_timing); 203 | } 204 | 205 | timing_sampleZ_G = timing_sampleZ_G/NTESTS - timing_overhead; 206 | timing_sampleZ_P = timing_sampleZ_P/NTESTS - timing_overhead; 207 | unsigned long long timing_sampleZ = timing_sampleZ_G + timing_sampleZ_P; 208 | 209 | timing_sampleG = timing_sampleG/NTESTS - timing_overhead; 210 | timing_samplePerturb = timing_samplePerturb/NTESTS - timing_overhead; 211 | timing_sampleArith = timing_sampleArith/NTESTS - timing_overhead; 212 | double timing_samplePre = timing_sampleG + timing_samplePerturb + timing_sampleArith; 213 | 214 | 215 | printf("----------- SampleZ -----------\n"); 216 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleG)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, ((double) timing_sampleZ_G/timing_sampleG)*100.0); 217 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleP)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, ((double) timing_sampleZ_P/timing_samplePerturb)*100.0); 218 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ, (timing_sampleZ*1000)/CPU_CYCLES, ((double) timing_sampleZ/timing_samplePre)*100.0); 219 | 220 | 221 | printf("\n----------- SamplePre -----------\n"); 222 | printf("SampleG : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG, (timing_sampleG*1000)/CPU_CYCLES, (timing_sampleG/timing_samplePre)*100.0); 223 | printf("G-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, (timing_sampleZ_G/timing_samplePre)*100.0); 224 | printf("G-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG - timing_sampleZ_G, ((timing_sampleG - timing_sampleZ_G)*1000)/CPU_CYCLES, ((timing_sampleG - timing_sampleZ_G)/timing_samplePre)*100.0); 225 | printf("-----\n"); 226 | 227 | printf("SamplePerturb: %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb, (timing_samplePerturb*1000)/CPU_CYCLES, (timing_samplePerturb/timing_samplePre)*100.0); 228 | printf("P-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, (timing_sampleZ_P/timing_samplePre)*100.0); 229 | printf("P-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb - timing_sampleZ_P, ((timing_samplePerturb - timing_sampleZ_P)*1000)/CPU_CYCLES, ((timing_samplePerturb - timing_sampleZ_P)/timing_samplePre)*100.0); 230 | printf("-----\n"); 231 | 232 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleArith, (timing_sampleArith*1000)/CPU_CYCLES, (timing_sampleArith/timing_samplePre)*100.0); 233 | 234 | printf("\n----------- Encrypt -----------\n"); 235 | timing_encrypt = timing_encrypt/NTESTS - timing_overhead; 236 | printf("Encrypt: %lld cycles (%.2lf ms)\n", timing_encrypt, (timing_encrypt*1000)/CPU_CYCLES); 237 | 238 | printf("\n\n"); 239 | 240 | free(A); 241 | free(T); 242 | free(sch_comp); 243 | free(cplx_T); 244 | free(u); 245 | } 246 | 247 | void time_decrypt(void) 248 | { 249 | timing_overhead = cpucycles_overhead(); 250 | unsigned long long begin_timing = 0; 251 | unsigned long long end_timing = 0; 252 | 253 | 254 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 255 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 256 | scalar *u_coeffs = malloc(PARAM_D * PARAM_N * sizeof(scalar)); 257 | poly_matrix A = A_coeffs, T = T_coeffs, u = u_coeffs; 258 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 259 | 260 | // Generate Keys 261 | Setup(A, T, cplx_T, sch_comp, u); 262 | 263 | 264 | 265 | // Generate a message 266 | scalar m_coeffs[PARAM_N] = {0}; 267 | poly m = m_coeffs; 268 | 269 | random_poly(m, SMALL_DEGREE - 1); 270 | 271 | // Generate an identity 272 | scalar id_coeffs[PARAM_N] = {0}; 273 | poly id = id_coeffs; 274 | 275 | random_poly(id, SMALL_DEGREE - 1); 276 | 277 | // Generate nu = sk_id 278 | scalar nu_coeffs[PARAM_N * PARAM_M]; 279 | poly_matrix nu = nu_coeffs; 280 | 281 | 282 | Extract(nu, A, u, T, cplx_T, sch_comp, id); 283 | 284 | // Compute b and c 285 | scalar *b_coeffs = malloc(PARAM_N * PARAM_M * sizeof(scalar)); 286 | scalar *c_coeffs = malloc(PARAM_N * sizeof(scalar)); 287 | 288 | poly_matrix b = b_coeffs; 289 | poly c = c_coeffs; 290 | 291 | 292 | 293 | Encrypt(A, u, id, m, b, c); 294 | 295 | 296 | scalar *M_coeffs = malloc(PARAM_N * sizeof(scalar)); 297 | poly M = M_coeffs; 298 | 299 | for(unsigned i = 0; i < NTESTS; ++i) { 300 | 301 | 302 | begin_timing = cpucycles_start(); 303 | 304 | Decrypt(nu, b, c, M); 305 | 306 | end_timing = cpucycles_stop(); 307 | timing_decrypt += (end_timing - begin_timing); 308 | } 309 | 310 | 311 | printf("----------- Decrypt -----------\n"); 312 | 313 | timing_decrypt = timing_decrypt/NTESTS - timing_overhead; 314 | printf("Total: %lld cycles (%.2lf ms)\n\n\n", timing_decrypt, (timing_decrypt*1000)/CPU_CYCLES); 315 | 316 | printf("\n\n"); 317 | 318 | free(A); 319 | free(T); 320 | free(sch_comp); 321 | free(cplx_T); 322 | free(u); 323 | free(b); 324 | free(c); 325 | free(M); 326 | } 327 | 328 | 329 | 330 | int main(void) { 331 | 332 | init_crt_trees(); 333 | init_D_lattice_coeffs(); 334 | init_cplx_roots_of_unity(); 335 | 336 | time_setup(); 337 | 338 | time_extract(); 339 | 340 | time_encrypt(); 341 | 342 | time_decrypt(); 343 | 344 | 345 | return 0; 346 | } 347 | 348 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ## To build, just use the different Makefiles. 2 | Our benchemarks were built using the command "make timing". 3 | 4 | ## The different parameters are in the common.h file. 5 | -------------------------------------------------------------------------------- /ROM_GPV/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #CC = gcc 3 | CC = clang 4 | CFLAGS = -Wall -O3 -march=native -mtune=native -fomit-frame-pointer -ftree-vectorize -funsafe-math-optimizations -mfpmath=sse 5 | CVECFLAGS := $(CFLAGS) -mavx2 -ftree-vectorize #-fopt-info-vec-optimized 6 | 7 | 8 | 9 | EXEC = signature_tests sampling_tests timing main_signature 10 | OBJ = arithmetic.o random.o 11 | HDR = common.h 12 | 13 | 14 | all: signature_tests timing 15 | 16 | timing: timing.o hash.o signature.o sampling.o random.o arithmetic.o cpucycles.o 17 | $(CC) $(CFLAGS) -o $@ $^ -lm 18 | 19 | signature_tests: signature_tests.o hash.o signature.o sampling.o random.o arithmetic.o 20 | $(CC) $(CFLAGS) -o $@ $^ -lm 21 | 22 | main_signature: main_signature.o signature.o sampling.o random.o $(OBJ) 23 | $(CC) $(CFLAGS) -o $@ $^ -lm 24 | 25 | sampling_tests: sampling_tests.o sampling.o random.o arithmetic.o 26 | $(CC) $(CFLAGS) -o $@ $^ -lm 27 | 28 | arithmetic.o: arithmetic.c random.o $(HDR) 29 | $(CC) $(CVECFLAGS) -c -o $@ $< 30 | 31 | sampling.o: sampling.c random.o $(HDR) 32 | $(CC) $(CVECFLAGS) -c -o $@ $< 33 | 34 | random.o: random.c $(HDR) 35 | $(CC) $(CVECFLAGS) -maes -c -o $@ $< 36 | 37 | timing.o : timing.c common.h 38 | $(CC) $(CFLAGS) -c -o $@ $< 39 | 40 | %.o: %.c $(HDR) 41 | $(CC) $(CFLAGS) -c -o $@ $< 42 | 43 | clean: 44 | rm -f $(EXEC) *.o *.s 45 | -------------------------------------------------------------------------------- /ROM_GPV/Misc/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -g -Wall 3 | 4 | EXEC = multiplicative_order primes 5 | 6 | all: $(EXEC) 7 | 8 | multiplicative_order: multiplicative_order.c 9 | $(CC) $(CFLAGS) -o $@ $^ 10 | 11 | primes: primes.c 12 | $(CC) $(CFLAGS) -o $@ $^ -lgmp 13 | 14 | clean: 15 | rm -f $(EXEC) 16 | -------------------------------------------------------------------------------- /ROM_GPV/Misc/multiplicative_order.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // a^x mod m 6 | uint64_t mod_exp(uint64_t a, uint64_t x, uint64_t m) 7 | { 8 | uint64_t r = 1; 9 | 10 | for(int i=0 ; i < 64 ; i++) 11 | { 12 | if(x & 1) 13 | { 14 | r = (((r * a) % m) + m) % m; 15 | } 16 | a = (((a * a) % m) + m) % m; 17 | x = x >> 1; 18 | } 19 | 20 | return r; 21 | } 22 | 23 | // multiplicative order of a mod 2^e 24 | uint64_t order(uint64_t a, uint64_t e) 25 | { 26 | uint64_t ones = (1 << e) - 1; 27 | 28 | for(int i=0 ; i < e ; i++) 29 | { 30 | if(a == 1) 31 | { 32 | return (1 << i); 33 | } 34 | a = (a * a) & ones; 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | if(argc < 4) 43 | { 44 | fprintf(stderr, "Usage : %s a e d\n", argv[0]); 45 | exit(EXIT_FAILURE); 46 | } 47 | 48 | uint64_t a, e, a_i, d; 49 | 50 | sscanf(argv[1], "%" SCNu64, &a); 51 | sscanf(argv[2], "%" SCNu64, &e); 52 | sscanf(argv[3], "%" SCNu64, &d); 53 | 54 | uint64_t ones = (1 << e) - 1; 55 | 56 | for(int i=1 ; i <= d ; i++) 57 | { 58 | a_i = mod_exp(a, i, (1 << e)); 59 | printf("%" PRIu64 " = %" PRIu64 "^%d has multiplicative order %" PRIu64 " mod 2^%" PRIu64 "\n", a_i, a, i, order(a_i, e), e); 60 | } 61 | 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /ROM_GPV/Misc/primes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | mpz_t N; 9 | uint64_t n; 10 | 11 | mpz_init(N); 12 | 13 | printf("Finding sparse primes congruent to 17 mod 32...\n"); 14 | 15 | printf("Finding primes of the form 2^i + 2^4 + 1...\n"); 16 | for(uint64_t i = 5 ; i < 64 ; i++) 17 | { 18 | n = (((uint64_t) 1)< 5 | #include 6 | 7 | 8 | #include "common.h" 9 | 10 | void ntt(uint32_t p[PARAM_N]); 11 | 12 | void invntt_frominvmont(uint32_t p[PARAM_N]); 13 | 14 | void invntt_without_mont(scalar p[PARAM_N]); 15 | 16 | scalar barrett_reduce(double_scalar a); 17 | 18 | uint32_t csubq(uint32_t a); 19 | 20 | uint32_t montgomery_reduce(uint64_t a); 21 | 22 | void poly_pointwise_invmontgomery(poly c, const poly a, const poly b); 23 | 24 | void matrix_ntt(poly_matrix A, int l1, int l2); 25 | 26 | void matrix_invntt(poly_matrix A, int l1, int l2); 27 | 28 | void matrix_invntt_without_mont(poly_matrix A, int l1, int l2); 29 | 30 | void multiply_by_one(poly f, int deg); 31 | 32 | void divide_by_2pow32(poly f, int deg); 33 | 34 | void multiply_by_2pow32(poly f, int deg); 35 | 36 | void mul_crt_poly_matrix(poly_matrix C, poly_matrix A, poly_matrix B, int l1, int l2, int l3); 37 | 38 | scalar reduce_naive(scalar x); 39 | 40 | signed_scalar reduce_signed_double_naive(signed_double_scalar x); 41 | 42 | scalar reduce_signed_double_to_positive_naive(signed_double_scalar x); 43 | 44 | scalar reduce_signed_naive(signed_scalar x); 45 | 46 | scalar reduce_sparse(scalar x); 47 | 48 | scalar reduce_double_naive(double_scalar x); 49 | 50 | scalar reduce_double_sparse(double_scalar x); 51 | 52 | scalar reduce_double_montgomery(double_scalar x); 53 | 54 | void alloc_poly(poly f, int deg); 55 | 56 | void alloc_double_poly(double_poly f, int deg); 57 | 58 | void free_poly(poly f); 59 | 60 | void free_double_poly(double_poly f); 61 | 62 | void print_poly(poly f, int deg); 63 | 64 | void print_double_poly(double_poly f, int deg); 65 | 66 | void print_signed_poly(signed_poly f, int deg); 67 | 68 | void print_signed_double_poly(signed_double_poly f, int deg); 69 | 70 | void print_poly_matrix(poly_matrix A, int l1, int l2); 71 | 72 | void print_signed_poly_matrix(signed_poly_matrix A, int l1, int l2); 73 | 74 | bool equals_poly(poly f, poly g, int deg); 75 | 76 | void print_cplx_poly(cplx_poly f, int deg); 77 | 78 | void print_cplx_poly_matrix(cplx_poly_matrix A, int l1, int l2); 79 | 80 | void print_triangular_cplx_poly_matrix(cplx_poly_matrix A, int l); 81 | 82 | void zero_poly(poly f, int deg); 83 | 84 | bool is_zero_poly(poly f, int deg); 85 | 86 | void freeze_poly(poly f, int deg); 87 | 88 | void freeze_double_poly(poly f, double_poly double_f, int deg); 89 | 90 | void freeze_upper_half_double_poly(double_poly double_f, int deg); 91 | 92 | void freeze_signed_poly(poly f_out, signed_poly f_in, int deg); 93 | 94 | void freeze_signed_double_poly(signed_poly f_out, signed_double_poly f_in, int deg); 95 | 96 | void freeze_signed_double_poly_to_positive(poly f_out, signed_double_poly f_in, int deg); 97 | 98 | void random_poly(poly f, int deg); 99 | 100 | void add_poly(poly h, poly f, poly g, int deg); 101 | 102 | void add_double_poly(double_poly h, double_poly f, double_poly g, int deg); 103 | 104 | void add_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 105 | 106 | void sub_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 107 | 108 | void sub_poly(poly h, poly f, poly g, int deg); 109 | 110 | void add_to_poly_matrix(poly_matrix A, poly_matrix B, int l1, int l2); 111 | 112 | void multiply_by_scalar_gadget_vector(scalar *prod, signed_scalar *v); 113 | 114 | void multiply_by_ring_gadget_vector(poly prod, signed_poly_matrix v); 115 | 116 | void multiply_by_module_gadget_matrix(poly_matrix res, signed_poly_matrix v); 117 | 118 | void add_ring_gadget_vector(poly_matrix v); 119 | 120 | void multiply_by_A(poly_matrix y, poly_matrix A, poly_matrix x); 121 | 122 | void multiply_by_TI(poly_matrix y, poly_matrix T, poly_matrix x); 123 | 124 | void multiply_by_T(poly_matrix y, poly_matrix T, poly_matrix x); 125 | 126 | double_scalar norm_squared(poly_matrix v, int l); 127 | 128 | void zero_cplx_poly(cplx_poly f, int deg); 129 | 130 | void add_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 131 | 132 | void fma_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 133 | 134 | void sub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 135 | 136 | void fmsub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 137 | 138 | void inv_cplx_poly(cplx_poly h, cplx_poly f, int deg); 139 | 140 | void mul_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 141 | 142 | void div_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 143 | 144 | void mul_cplx_poly_by_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 145 | 146 | void mul_cplx_poly_by_own_transpose(cplx_poly h, cplx_poly f, int deg); 147 | 148 | void cplx_fma_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 149 | 150 | void fmsub_transpose_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 151 | 152 | void transpose_cplx_poly(cplx_poly f, int deg); 153 | 154 | void stride(cplx_poly f, int depth); 155 | 156 | void inverse_stride(cplx_poly f, int depth); 157 | 158 | void scalar_stride(signed_scalar *p, int size); 159 | 160 | void reduce_mod_sparse_cplx_poly(cplx_poly f, int deg, cplx c); 161 | 162 | void cplx_crt_representation(cplx_poly f); 163 | 164 | void matrix_cplx_crt_representation(cplx_poly_matrix M, int l1, int l2); 165 | 166 | void construct_T_schur_complement(cplx_poly_matrix sch_comp, cplx_poly_matrix T); 167 | 168 | void construct_schur_complement_and_center(cplx_poly_matrix M, cplx_poly_matrix c, cplx_poly d, cplx_poly x1, int l); 169 | 170 | void construct_schur_complement(cplx_poly_matrix M, int l); 171 | 172 | void construct_new_center(cplx_poly_matrix c, cplx_poly_matrix M, cplx_poly q1, int l); 173 | 174 | void construct_first_center(cplx_poly_matrix c, cplx_poly_matrix T, cplx_poly_matrix p); 175 | 176 | void construct_complex_private_key(cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix T); 177 | 178 | void init_cplx_roots_of_unity(void); 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /ROM_GPV/cpucycles.c: -------------------------------------------------------------------------------- 1 | #include "cpucycles.h" 2 | 3 | unsigned long long cpucycles_overhead(void) { 4 | unsigned long long t0, t1, overhead = -1; 5 | unsigned int i; 6 | 7 | for(i = 0; i < 100000; ++i) { 8 | t0 = cpucycles_start(); 9 | asm volatile(""); 10 | t1 = cpucycles_stop(); 11 | if(t1 - t0 < overhead) 12 | overhead = t1 - t0; 13 | } 14 | 15 | return overhead; 16 | } 17 | -------------------------------------------------------------------------------- /ROM_GPV/cpucycles.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUCYCLES_H 2 | #define CPUCYCLES_H 3 | 4 | #ifdef DBENCH 5 | #define DBENCH_START() unsigned long long time = cpucycles_start() 6 | #define DBENCH_STOP(t) t += cpucycles_stop() - time - timing_overhead 7 | #else 8 | #define DBENCH_START() 9 | #define DBENCH_STOP(t) 10 | #endif 11 | 12 | #ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ 13 | #ifdef SERIALIZE_RDC 14 | 15 | static inline unsigned long long cpucycles_start(void) { 16 | const unsigned int ecx = (1U << 30) + 1; 17 | unsigned long long result; 18 | 19 | asm volatile("cpuid; movl %1,%%ecx; rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 20 | : "=&a" (result) : "r" (ecx) : "rbx", "rcx", "rdx"); 21 | 22 | return result; 23 | } 24 | 25 | static inline unsigned long long cpucycles_stop(void) { 26 | const unsigned int ecx = (1U << 30) + 1; 27 | unsigned long long result, dummy; 28 | 29 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax; movq %%rax,%0; cpuid" 30 | : "=&r" (result), "=c" (dummy) : "c" (ecx) : "rax", "rbx", "rdx"); 31 | 32 | return result; 33 | } 34 | 35 | #else 36 | 37 | static inline unsigned long long cpucycles_start(void) { 38 | const unsigned int ecx = (1U << 30) + 1; 39 | unsigned long long result; 40 | 41 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 42 | : "=a" (result) : "c" (ecx) : "rdx"); 43 | 44 | return result; 45 | } 46 | 47 | static inline unsigned long long cpucycles_stop(void) { 48 | const unsigned int ecx = (1U << 30) + 1; 49 | unsigned long long result; 50 | 51 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 52 | : "=a" (result) : "c" (ecx) : "rdx"); 53 | 54 | return result; 55 | } 56 | 57 | #endif 58 | #else 59 | #ifdef SERIALIZE_RDC 60 | 61 | static inline unsigned long long cpucycles_start(void) { 62 | unsigned long long result; 63 | 64 | asm volatile("cpuid; rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 65 | : "=a" (result) : : "%rbx", "%rcx", "%rdx"); 66 | 67 | return result; 68 | } 69 | 70 | static inline unsigned long long cpucycles_stop(void) { 71 | unsigned long long result; 72 | 73 | asm volatile("rdtscp; shlq $32,%%rdx; orq %%rdx,%%rax; mov %%rax,%0; cpuid" 74 | : "=r" (result) : : "%rax", "%rbx", "%rcx", "%rdx"); 75 | 76 | return result; 77 | } 78 | 79 | #else 80 | 81 | static inline unsigned long long cpucycles_start(void) { 82 | unsigned long long result; 83 | 84 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 85 | : "=a" (result) : : "%rdx"); 86 | 87 | return result; 88 | } 89 | 90 | static inline unsigned long long cpucycles_stop(void) { 91 | unsigned long long result; 92 | 93 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 94 | : "=a" (result) : : "%rdx"); 95 | 96 | return result; 97 | } 98 | 99 | #endif 100 | #endif 101 | 102 | unsigned long long cpucycles_overhead(void); 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /ROM_GPV/hash.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | #define SHAKE128_RATE 168 6 | #define SHAKE256_RATE 136 7 | 8 | void shake128_absorb(uint64_t *s, 9 | const unsigned char *input, 10 | unsigned long long inlen); 11 | 12 | void shake128_squeezeblocks(unsigned char *output, 13 | unsigned long nblocks, 14 | uint64_t *s); 15 | 16 | void shake256_absorb(uint64_t *s, 17 | const unsigned char *input, 18 | unsigned long long inlen); 19 | 20 | void shake256_squeezeblocks(unsigned char *output, 21 | unsigned long nblocks, 22 | uint64_t *s); 23 | 24 | void shake128(unsigned char *output, 25 | unsigned long long outlen, 26 | const unsigned char *input, 27 | unsigned long long inlen); 28 | 29 | void shake256(unsigned char *output, 30 | unsigned long long outlen, 31 | const unsigned char *input, 32 | unsigned long long inlen); 33 | 34 | void uniform_poly_from_bytes(poly f, uint8_t *r_in, int deg); 35 | 36 | void H(poly t, uint8_t *m, int m_len, uint8_t *r); 37 | -------------------------------------------------------------------------------- /ROM_GPV/main_signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "arithmetic.h" 9 | #include "sampling.h" 10 | #include "signature.h" 11 | 12 | void check_trapgen(void) 13 | { 14 | scalar A_coeffs[PARAM_D * (PARAM_M - PARAM_D) * PARAM_N], TI_coeffs[PARAM_M * PARAM_D * PARAM_K * PARAM_N], prod_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N], AwithI_coeffs[PARAM_D * PARAM_M * PARAM_N]; 15 | poly_matrix A = A_coeffs, T = TI_coeffs, TI = TI_coeffs, Idk = poly_matrix_element(TI, PARAM_D * PARAM_K, 2*PARAM_D, 0), prod = prod_coeffs, AwithI = AwithI_coeffs; 16 | 17 | // Generate A and T 18 | TrapGen(A, T); 19 | 20 | // Generate Idk (in the CRT domain) and append it to T vertically 21 | memset(Idk, 0, PARAM_D * PARAM_K * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 22 | for(int i = 0 ; i < PARAM_D * PARAM_K ; ++i) 23 | { 24 | poly p_i = poly_matrix_element(Idk, PARAM_D * PARAM_K, i, i); 25 | for(int j = 0 ; j < PARAM_R ; ++j) 26 | { 27 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 28 | p_ij[0] = 1; 29 | } 30 | } 31 | 32 | // Prepend Id (in the CRT domain) to A horizontally 33 | for(int i = 0 ; i < PARAM_D ; ++i) 34 | { 35 | poly_matrix AwithI_i = poly_matrix_element(AwithI, PARAM_M, i, 0); 36 | poly_matrix A_i = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 37 | 38 | // build Id 39 | memset(AwithI_i, 0, PARAM_D * PARAM_N * sizeof(scalar)); 40 | poly p_i = poly_matrix_element(AwithI, PARAM_M, i, i); 41 | for(int j = 0 ; j < PARAM_R ; ++j) 42 | { 43 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 44 | p_ij[0] = 1; 45 | } 46 | 47 | // copy A 48 | memcpy(poly_matrix_element(AwithI_i, PARAM_M, 0, PARAM_D), A_i, (PARAM_M - PARAM_D) * PARAM_N * sizeof(scalar)); 49 | } 50 | 51 | 52 | // prod = AwithI * TI 53 | mul_crt_poly_matrix(prod, AwithI, TI, PARAM_D, PARAM_M, PARAM_D * PARAM_K, LOG_R); 54 | 55 | 56 | for(int i = 0 ; i < PARAM_D * PARAM_D * PARAM_K * PARAM_N ; ++i) 57 | { 58 | if(prod[i] != 0) 59 | { 60 | printf("%d : %" PRIu32 "\n", i, prod[i]); 61 | } 62 | else 63 | { 64 | //printf("yay\n"); 65 | } 66 | } 67 | } 68 | 69 | int main(int argc, char **argv) 70 | { 71 | init_crt_trees(); 72 | init_D_lattice_coeffs(); 73 | init_cplx_roots_of_unity(); 74 | 75 | srand48(0); 76 | srand(0); 77 | 78 | check_trapgen(); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /ROM_GPV/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "random.h" 10 | 11 | /* 12 | Returns an integer sampled from the uniform distribution over [0, n] 13 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 14 | */ 15 | uint32_t uniform_int_distribution(uint32_t n) 16 | { 17 | uint32_t scaling = (UINT32_MAX) / (n + 1); 18 | uint32_t past = (n + 1) * scaling; 19 | uint32_t r_data[4]; 20 | 21 | while(true) 22 | { 23 | random_bytes((uint8_t *) r_data); 24 | 25 | for(int i = 0 ; i < 4 ; ++i) 26 | { 27 | uint32_t r = r_data[i]; 28 | 29 | if(r < past) 30 | { 31 | return r / scaling; 32 | } 33 | } 34 | } 35 | } 36 | 37 | /* 38 | Returns an integer sampled from the uniform distribution over [0, q-1] 39 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 40 | */ 41 | scalar uniform_mod_q(void) 42 | { 43 | uint32_t scaling = (UINT32_MAX) / PARAM_Q; 44 | uint32_t past = PARAM_Q * scaling; 45 | uint32_t r_data[4]; 46 | 47 | while(true) 48 | { 49 | random_bytes((uint8_t *) r_data); 50 | 51 | for(int i = 0 ; i < 4 ; ++i) 52 | { 53 | uint32_t r = r_data[i]; 54 | 55 | if(r < past) 56 | { 57 | return r / scaling; 58 | } 59 | } 60 | } 61 | } 62 | 63 | #define AES_128_key_exp(k, rcon) aes_128_key_expansion(k, _mm_aeskeygenassist_si128(k, rcon)) 64 | #define DO_ENC_BLOCK(m,k) \ 65 | do {\ 66 | m = _mm_xor_si128 (m, k[ 0]); \ 67 | m = _mm_aesenc_si128 (m, k[ 1]); \ 68 | m = _mm_aesenc_si128 (m, k[ 2]); \ 69 | m = _mm_aesenc_si128 (m, k[ 3]); \ 70 | m = _mm_aesenc_si128 (m, k[ 4]); \ 71 | m = _mm_aesenc_si128 (m, k[ 5]); \ 72 | __auto_type m5 = m;\ 73 | m = _mm_aesenc_si128 (m, k[ 6]); \ 74 | m = _mm_aesenc_si128 (m, k[ 7]); \ 75 | m = _mm_aesenc_si128 (m, k[ 8]); \ 76 | m = _mm_aesenc_si128 (m, k[ 9]); \ 77 | m = _mm_aesenclast_si128(m, k[10]);\ 78 | m = _mm_xor_si128(m, m5);\ 79 | } while(0) 80 | 81 | //the expanded key 82 | static __m128i key_schedule[11]; 83 | static uint64_t ctr = 0; 84 | 85 | 86 | static __m128i aes_128_key_expansion(__m128i key, __m128i keygened) { 87 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3)); 88 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 89 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 90 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 91 | return _mm_xor_si128(key, keygened); 92 | } 93 | 94 | static void aes128_load_key(const int8_t * enc_key){ 95 | key_schedule[0] = _mm_loadu_si128((const __m128i*) enc_key); 96 | key_schedule[1] = AES_128_key_exp(key_schedule[0], 0x01); 97 | key_schedule[2] = AES_128_key_exp(key_schedule[1], 0x02); 98 | key_schedule[3] = AES_128_key_exp(key_schedule[2], 0x04); 99 | key_schedule[4] = AES_128_key_exp(key_schedule[3], 0x08); 100 | key_schedule[5] = AES_128_key_exp(key_schedule[4], 0x10); 101 | key_schedule[6] = AES_128_key_exp(key_schedule[5], 0x20); 102 | key_schedule[7] = AES_128_key_exp(key_schedule[6], 0x40); 103 | key_schedule[8] = AES_128_key_exp(key_schedule[7], 0x80); 104 | key_schedule[9] = AES_128_key_exp(key_schedule[8], 0x1B); 105 | key_schedule[10] = AES_128_key_exp(key_schedule[9], 0x36); 106 | } 107 | 108 | void random_bytes_init(void) { 109 | int8_t seed[16] = {0x01, 0x05, 0x07, 0x09, 0x0F, 0xFF}; 110 | int randomData = open("/dev/urandom", O_RDONLY); 111 | read(randomData, seed, sizeof(int8_t)*16); 112 | // _rdseed64_step((unsigned long long * ) seed); 113 | // _rdseed64_step((unsigned long long * ) (seed + 8)); 114 | aes128_load_key(seed); 115 | ctr = 0; 116 | } 117 | 118 | void random_bytes(uint8_t * restrict data) { 119 | __m128i m = _mm_setr_epi32(0, 1, 2, ctr++); 120 | DO_ENC_BLOCK(m, key_schedule); 121 | 122 | uint8_t * x = (uint8_t *) __builtin_assume_aligned(data, 16); 123 | _mm_storeu_si128((__m128i *) x, m); 124 | } 125 | 126 | static const double ln2 = 0.6931471805599453; // log(2); 127 | static const double a = 5.713363152645423; //(4+3*sqrt(2))*log(2); 128 | static const double b = 3.414213562373095; // 2+sqrt(2); 129 | static const double c = -1.6734053240284923; // -(1+sqrt(2))*log(2); 130 | static const double p = 0.9802581434685472; //sqrt(2)*log(2); 131 | static const double A = 5.6005707569738075; //a*p; 132 | static const double B = 3.3468106480569846; // b*p; 133 | static const double D = 0.08578643762690495; // 1/(b*b); 134 | static const double H = 0.0026106723602095233;// h*D/p; 135 | int algorithmF(const double mu, const double sigma) { 136 | static uint32_t randomData[8]; 137 | static unsigned randomDataIndex = 8; 138 | 139 | static uint8_t randomExpSecond[32]; 140 | static unsigned randomExpSecondIndex = 8; 141 | 142 | const double _sigma_floor_ = (unsigned) sigma; 143 | const unsigned sigma_floor = (unsigned) (((_sigma_floor_ == sigma) && (_sigma_floor_ != 0)) ? sigma - 1 : (_sigma_floor_)); 144 | 145 | const uint32_t scaling = UINT32_MAX / (sigma_floor + 1); 146 | const uint32_t past = (sigma_floor + 1) * scaling; 147 | 148 | while(true) { 149 | do { 150 | if(randomDataIndex == 8) { 151 | randomDataIndex = 0; 152 | random_bytes((uint8_t *) randomData); 153 | random_bytes((uint8_t *) (randomData + 4)); 154 | } 155 | 156 | } while(randomData[randomDataIndex++] >= past); 157 | 158 | 159 | // compute j and s 160 | const unsigned j = randomData[randomDataIndex - 1] / scaling; 161 | const int s = ((randomData[randomDataIndex - 1] & 0x01) == 0) ? -1 : 1; 162 | 163 | 164 | // Exp 165 | double expVariate[3]; 166 | double expG[3]; 167 | unsigned expVariateIndex = 0; 168 | 169 | // First try (high probability) 170 | uint8_t randomExpFirst[32]; 171 | random_bytes(randomExpFirst); 172 | random_bytes(randomExpFirst + 16); 173 | 174 | const double U_1 = *((uint16_t *) randomExpFirst) / (UINT16_MAX*1.0); 175 | { 176 | const unsigned long long int I_i = *((uint64_t *) (randomExpFirst + 2)); 177 | const int j_i = __builtin_ctzll(I_i); 178 | expG[expVariateIndex] = c + j_i*ln2; 179 | } 180 | if (U_1 <= p) { 181 | expVariate[expVariateIndex] = expG[expVariateIndex] + A/(B - U_1); 182 | expVariateIndex++; 183 | } 184 | 185 | const double U_2 = *((uint16_t *) (randomExpFirst + 10)) / (UINT16_MAX*1.0); 186 | { 187 | const unsigned long long int I_i = *((uint64_t *) (randomExpFirst + 12)); 188 | const int j_i = __builtin_ctzll(I_i); 189 | expG[expVariateIndex] = c + j_i*ln2; 190 | } 191 | 192 | if (U_2 <= p) { 193 | expVariate[expVariateIndex] = expG[expVariateIndex] + A/(B - U_2); 194 | expVariateIndex++; 195 | } 196 | 197 | const double U_3 = *((uint16_t *) (randomExpFirst + 20)) / (UINT16_MAX*1.0); 198 | { 199 | const unsigned long long int I_i = *((uint64_t *) (randomExpFirst + 22)); 200 | const int j_i = __builtin_ctzll(I_i); 201 | expG[expVariateIndex] = c + j_i*ln2; 202 | } 203 | if (U_3 <= p) { 204 | expVariate[expVariateIndex] = expG[expVariateIndex] + A/(B - U_3); 205 | expVariateIndex++; 206 | } 207 | 208 | 209 | for(; expVariateIndex < 3;) { 210 | for(; randomExpSecondIndex < 8; randomExpSecondIndex++) { 211 | const double U1 = *((uint16_t *) (randomExpSecond + randomExpSecondIndex*2)) / (UINT16_MAX*1.0); 212 | const double U2 = *((uint16_t *) (randomExpSecond + randomExpSecondIndex*2 + 8)) / (UINT16_MAX*1.0); 213 | const double bU1 = b - U1; 214 | const double Y = a/bU1; 215 | const double L = (U2*H + D)*(bU1)*(bU1); 216 | const double Z = Y + c; 217 | 218 | const double LZ = L - 1 + Z; 219 | const double ZZ = Z*Z; 220 | const bool cond1 = LZ <= 0; 221 | const bool cond2 = LZ - ZZ/2 + ZZ*Z/6 <= 0; 222 | const bool cond3 = LZ - ZZ <= 0; 223 | 224 | 225 | if (cond1 || cond2 || (cond3 && (L <= exp(-Z)))) { 226 | expVariate[expVariateIndex] = expG[expVariateIndex] + Y; 227 | expVariateIndex++; 228 | break; 229 | } 230 | } 231 | if(randomExpSecondIndex == 8) { 232 | randomExpSecondIndex = 0; 233 | random_bytes(randomExpSecond); 234 | random_bytes(randomExpSecond + 16); 235 | } 236 | } 237 | 238 | unsigned k = ((unsigned) (2*expVariate[0])); 239 | int i0 = ((unsigned) (sigma*k + s*mu)) + 1; 240 | double x0 = (i0 - (sigma*k + s*mu))/sigma; 241 | double x = x0 + j/sigma; 242 | 243 | unsigned k1 = ((unsigned) (2*expVariate[1])); 244 | double z = expVariate[2]; 245 | 246 | bool cond1 = k1 >= k*(k-1); 247 | bool cond2 = x < 1; 248 | bool cond3a = x != 0; 249 | bool cond3b = k != 0; 250 | bool cond3c = s == 1; 251 | bool cond3 = cond3a || cond3b || cond3c; 252 | bool cond4 = z > 0.5*x*(2*k + x); 253 | 254 | if (cond1 && cond2 && cond3 && cond4) { 255 | return s*(i0 + j); 256 | } 257 | } 258 | } 259 | 260 | /* 261 | Generates a random salt r of size SALT_BYTES 262 | */ 263 | void salt(uint8_t *r) 264 | { 265 | for(int i = 0 ; i < NEEDED_AES_FOR_SALT ; ++i) 266 | { 267 | random_bytes(&r[16*i]); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /ROM_GPV/random.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | 6 | uint32_t uniform_int_distribution(uint32_t n); 7 | 8 | scalar uniform_mod_q(void); 9 | 10 | /* 11 | Code from random_aesni.c 12 | */ 13 | 14 | //public API 15 | void random_bytes_init(void); 16 | 17 | void random_bytes(uint8_t * restrict data); 18 | 19 | /* 20 | Code from exp_aes.cpp 21 | */ 22 | 23 | double algorithm_EA(uint64_t * n); 24 | 25 | /* 26 | Code from algoF_aes.cpp 27 | */ 28 | 29 | int algorithmF(const double mu, const double sigma); 30 | 31 | void salt(uint8_t *r); 32 | -------------------------------------------------------------------------------- /ROM_GPV/sampling.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void TrapGen(poly_matrix A, poly_matrix T); 6 | 7 | //============================================================================== 8 | // Samples from distribution D_{c,sigma}, ie 9 | // Samples an element in Z with probability proportionnal to e^{-(c-x)^2/2*(sigma^2)} 10 | //============================================================================== 11 | signed int SampleZ(RR_t c, RR_t sigma); 12 | 13 | void SampleR_centered(signed_poly f, RR_t sigma); 14 | 15 | void SampleR_matrix_centered(signed_poly_matrix A, int l1, int l2, RR_t sigma); 16 | 17 | void init_D_lattice_coeffs(void); 18 | 19 | void sample_D(signed_scalar *z, real *c, real sigma); 20 | 21 | void sample_G_perturb(real *p, real sigma); 22 | 23 | void scalar_sample_G(signed_scalar *t, scalar u); 24 | 25 | void ring_sample_G(signed_poly_matrix t, poly u); 26 | 27 | void transpose_scalar_matrix(scalar *A_T, scalar *A, int l0, int l1); 28 | 29 | void module_sample_G(signed_poly_matrix t, poly_matrix u); 30 | 31 | void sample_2z(signed_scalar *q, cplx_poly cplx_q, cplx_poly a, cplx_poly b, cplx_poly d, cplx *c, int deg); 32 | 33 | void sample_fz(signed_scalar *p, cplx_poly cplx_p, cplx_poly f, cplx *c, int deg); 34 | 35 | void sample_perturb(signed_poly_matrix p, cplx_poly_matrix T, cplx_poly_matrix sch_comp); 36 | 37 | void sample_pre(poly_matrix x, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix u); 38 | 39 | extern real d_coeffs[PARAM_K]; 40 | extern real l_coeffs[PARAM_K]; 41 | extern real h_coeffs[PARAM_K]; 42 | -------------------------------------------------------------------------------- /ROM_GPV/sampling_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "random.h" 9 | #include "sampling.h" 10 | #include "arithmetic.h" 11 | 12 | void test_random_bytes(int n) 13 | { 14 | uint8_t r[16]; 15 | 16 | for(int i = 0 ; i < n ; ++i) 17 | { 18 | random_bytes(r); 19 | for(int j = 0 ; j < 16 ; ++j) 20 | { 21 | printf("%d ", r[j]); 22 | } 23 | printf("\n"); 24 | } 25 | } 26 | 27 | void time_SampleZ(int n) 28 | { 29 | clock_t t0, t1; 30 | real c = 0.5, sigma = PARAM_SIGMA; 31 | 32 | printf("Sampling from the discrete Gaussian over Z with center %f and parameter %f...\n", c, sigma); 33 | 34 | t0 = clock(); 35 | for(int i = 0 ; i < n ; ++i) 36 | { 37 | SampleZ(c, sigma); 38 | } 39 | t1 = clock() - t0; 40 | 41 | printf("Done : %ld\n", t1); 42 | } 43 | 44 | void test_SampleZ(int n) 45 | { 46 | real c = -10, sigma = PARAM_SIGMA; 47 | 48 | printf("Sampling from the discrete Gaussian over Z with center %f and parameter %f...\n", c, sigma); 49 | 50 | for(int i = 0 ; i < n ; ++i) 51 | { 52 | printf("%d\n", SampleZ(c, sigma)); 53 | } 54 | } 55 | 56 | void test_sample_D(int n) 57 | { 58 | signed_scalar z[PARAM_K]; 59 | real c[PARAM_K], sigma = PARAM_ALPHA / 3; 60 | 61 | for(int i = 0 ; i < PARAM_K ; ++i) 62 | { 63 | c[i] = 0; 64 | } 65 | 66 | for(int i = 0 ; i < n ; ++i) 67 | { 68 | sample_D(z, c, sigma); 69 | print_signed_poly(z, PARAM_K - 1); 70 | printf("\n"); 71 | } 72 | } 73 | 74 | void test_scalar_sample_G(int n) 75 | { 76 | signed_scalar z[PARAM_K]; 77 | scalar u, prod; 78 | 79 | for(int i = 0 ; i < n ; ++i) 80 | { 81 | random_poly(&u, 0); 82 | scalar_sample_G(z, u); 83 | 84 | //printf("\n"); 85 | print_signed_poly(z, PARAM_K - 1); 86 | 87 | multiply_by_scalar_gadget_vector(&prod, z); 88 | 89 | printf("(%" PRIu32 ", %" PRIu32 ")\n", u, prod); 90 | } 91 | } 92 | 93 | void test_ring_sample_G(int n) 94 | { 95 | signed_scalar z_coeffs[PARAM_K * PARAM_N]; 96 | scalar prod_coeffs[PARAM_N], u_coeffs[PARAM_N]; 97 | signed_poly_matrix z = z_coeffs; 98 | poly prod = prod_coeffs, u = u_coeffs; 99 | 100 | for(int i = 0 ; i < n ; ++i) 101 | { 102 | random_poly(u, PARAM_N - 1); 103 | // Sample z such that = 0 mod q 104 | ring_sample_G(z, u); 105 | 106 | 107 | // Check that = u mod q 108 | multiply_by_ring_gadget_vector(prod, z); 109 | for(int j = 0 ; j < PARAM_N ; ++j) 110 | { 111 | if(prod[j] != u[j]) 112 | { 113 | printf("%d %d : %" PRIu32 "\n", i, j, prod[j]); 114 | } 115 | } 116 | } 117 | } 118 | 119 | void test_module_sample_G(int n) 120 | { 121 | signed_scalar z_coeffs[PARAM_D * PARAM_K * PARAM_N]; 122 | scalar prod_coeffs[PARAM_D * PARAM_N], u_coeffs[PARAM_D * PARAM_N]; 123 | signed_poly_matrix z = z_coeffs; 124 | poly_matrix prod = prod_coeffs, u = u_coeffs; 125 | 126 | for(int i = 0 ; i < n ; ++i) 127 | { 128 | random_poly(u, PARAM_D * PARAM_N - 1); 129 | // Sample z such that Gz = 0 mod q 130 | module_sample_G(z, u); 131 | 132 | // Check that Gz = u mod q 133 | multiply_by_module_gadget_matrix(prod, z); 134 | for(int j = 0 ; j < PARAM_D * PARAM_N ; ++j) 135 | { 136 | if(prod[j] != u[j]) 137 | { 138 | printf("%d %d : %" PRIu32 "\n", i, j, prod[j]); 139 | } 140 | } 141 | 142 | } 143 | } 144 | 145 | void time_module_sample_G(int n) 146 | { 147 | signed_scalar z_coeffs[PARAM_D * PARAM_K * PARAM_N]; 148 | signed_poly_matrix z = z_coeffs; 149 | 150 | printf("Presampling from the module gadget lattice... (not really)"); 151 | fflush(stdout); 152 | 153 | clock_t t0 = clock(); 154 | for(int i = 0 ; i < n ; ++i) 155 | { 156 | // Sample z such that Gz = 0 mod q 157 | //module_sample_G(z); 158 | } 159 | clock_t t1 = clock() - t0; 160 | 161 | printf("Done : %ld\n", t1); 162 | } 163 | 164 | 165 | /* 166 | Checks whether the l by l triangular matrix M has only positive coefficients on its diagonal 167 | */ 168 | bool is_diagonally_positive(cplx_poly_matrix M, int l) 169 | { 170 | bool diag_pos = true; 171 | 172 | for(int i = 0 ; i < l ; ++i) 173 | { 174 | cplx_poly M_ii = triangular_poly_matrix_element(M, i, i); 175 | 176 | for(int j = 0 ; j < PARAM_N ; ++j) 177 | { 178 | if((fabs(cimag(M_ii[j])) != 0.0) || (creal(M_ii[j]) <= 0.0)) 179 | { 180 | printf("M[%d,%d][%d] = %f %+f * I\n", i, i, j, creal(M_ii[j]), cimag(M_ii[j])); 181 | diag_pos = false; 182 | } 183 | } 184 | } 185 | 186 | return diag_pos; 187 | } 188 | 189 | void test_sch_comp_computations(void) 190 | { 191 | scalar *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 192 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 193 | 194 | poly_matrix T = T_coeffs; 195 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 196 | 197 | // Generate T 198 | printf("Generating gaussian T...\n"); 199 | 200 | SampleR_matrix_centered((signed_poly_matrix) T, 2*PARAM_D, PARAM_D * PARAM_K, PARAM_SIGMA); 201 | 202 | printf("Done\n"); 203 | 204 | // Compute cplx_T (CRT domain) 205 | printf("Computing cplx_T in the CRT domain...\n"); 206 | 207 | for(int i = 0 ; i < PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K ; ++i) 208 | { 209 | cplx_T[i] = (signed_scalar) T[i]; 210 | } 211 | 212 | matrix_cplx_crt_representation(cplx_T, 2 * PARAM_D, PARAM_D * PARAM_K); 213 | 214 | printf("Done\n"); 215 | 216 | // Compute the Schur complements and check if they are diagonally positive 217 | printf("Computing the Schur complements...\n"); 218 | 219 | construct_T_schur_complement(sch_comp, cplx_T); 220 | 221 | printf("first sch_comp done\n"); 222 | 223 | if(!is_diagonally_positive(sch_comp, 2 * PARAM_D)) 224 | { 225 | print_triangular_cplx_poly_matrix(sch_comp, 2 * PARAM_D); 226 | return; 227 | } 228 | 229 | for(int i = 2 * PARAM_D - 1 ; i > 1 ; --i) 230 | { 231 | construct_schur_complement(sch_comp, i); 232 | 233 | printf("sch_comp %d done\n", i); 234 | 235 | if(!is_diagonally_positive(sch_comp, i)) 236 | { 237 | print_triangular_cplx_poly_matrix(sch_comp, i); 238 | return; 239 | } 240 | } 241 | } 242 | 243 | int main(int argc, char **argv) 244 | { 245 | if(argc < 2) 246 | { 247 | fprintf(stderr, "Usage : %s n\n", argv[0]); 248 | exit(EXIT_FAILURE); 249 | } 250 | 251 | int n = atoi(argv[1]); 252 | 253 | init_crt_trees(); 254 | init_D_lattice_coeffs(); 255 | init_cplx_roots_of_unity(); 256 | 257 | random_bytes_init(); 258 | 259 | time_sample_pre_subroutines(n); 260 | 261 | return 0; 262 | } 263 | -------------------------------------------------------------------------------- /ROM_GPV/script.sage: -------------------------------------------------------------------------------- 1 | #q = 8380417 2 | #q = 32257 3 | #q = 268432897 4 | #q = 1073738753 5 | #q = 2147483137 6 | #q = 1073707009 7 | #q = 12289 8 | q = 13313 9 | #q = 7681 10 | 11 | #n = 1024 12 | n = 512 13 | #n = 256 14 | 15 | GFq = GF(q) 16 | r = GFq.zeta(2*n) 17 | 18 | def flatten_tree(tree): 19 | l = [] 20 | for list in tree: 21 | l += list 22 | return l 23 | 24 | def montgomery_list(l): 25 | return [l_i * 2^32 for l_i in l] 26 | 27 | def brv(a): 28 | return sum([a_i * 2^i for i, a_i in enumerate(reversed(a.bits()))]) 29 | 30 | def precompute_zetas(r): 31 | assert r.multiplicative_order() == 2*n 32 | 33 | zetas = [] 34 | 35 | k = n // 2 36 | while k > 0: 37 | zetas = [r^brv(k+i) for i in range(k)] + zetas 38 | r = zetas[0]^2 39 | k = k // 2 40 | 41 | zetas = [0] + zetas 42 | zetas_inv = [-zeta for zeta in reversed(zetas)] 43 | 44 | return zetas, zetas_inv 45 | 46 | def list_order(l): 47 | return [l_i.multiplicative_order() if l_i.is_unit() else 0 for l_i in l] 48 | 49 | mont = mod(2^32, q) 50 | mont2 = mod(2^64, q) 51 | q_inv = - mod(q, 2^32)^(-1) 52 | barrett_mult = floor(2^32 / q) 53 | barrett_shift = 32 54 | double_barrett_mult = floor(2^34 / q) 55 | double_barrett_shift = 34 56 | 57 | print "===== common.h =====\n" 58 | print "#define MONT", mont 59 | print "#define MONT2", mont2 60 | print "#define QINV", q_inv 61 | print "#define BARRETT_MULT", barrett_mult 62 | print "#define BARRETT_SHIFT", barrett_shift 63 | print "#define DOUBLE_BARRETT_MULT", double_barrett_mult 64 | print "#define DOUBLE_BARRETT_SHIFT", double_barrett_shift 65 | print "\n" 66 | 67 | zetas, zetas_inv = precompute_zetas(r) 68 | montgomery_zetas = montgomery_list(zetas) 69 | montgomery_zetas_inv = montgomery_list(zetas_inv) 70 | 71 | m_z_str = "{" + ", ".join(map(str, montgomery_zetas)) + "}" 72 | m_z_i_str = "{" + ", ".join(map(str, montgomery_zetas_inv)) + "}" 73 | 74 | print "===== arithmetic.c =====\n" 75 | print "static const scalar zetas[PARAM_N] = " + m_z_str + ";\n" 76 | print "static const scalar zetas_inv[PARAM_N] = " + m_z_i_str + ";\n" 77 | -------------------------------------------------------------------------------- /ROM_GPV/signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "arithmetic.h" 10 | #include "sampling.h" 11 | #include "random.h" 12 | #include "hash.h" 13 | 14 | #include "cpucycles.h" 15 | 16 | 17 | extern unsigned long long timing_sampleZ_KG; 18 | extern unsigned long long timing_precomp_KG; 19 | extern unsigned long long timing_arith_KG; 20 | 21 | /* 22 | Generates a signing key (T, cplx_T, sch_comp) and an associated verification key A 23 | */ 24 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp) 25 | { 26 | unsigned long long begin_timing = 0; 27 | unsigned long long end_timing = 0; 28 | 29 | //scalar A_hat_coeffs[PARAM_D * PARAM_D * PARAM_N], AprimeT_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N]; 30 | scalar *A_hat_coeffs = malloc(PARAM_D * PARAM_D * PARAM_N * sizeof(scalar)), *AprimeT_coeffs = malloc(PARAM_D * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 31 | poly_matrix A_hat = A_hat_coeffs, AprimeT = AprimeT_coeffs; 32 | 33 | // A_hat <- U(R_q^{d,d}) is considered to be in the NTT_op domain 34 | random_poly(A_hat, PARAM_N * PARAM_D * PARAM_D - 1); 35 | 36 | 37 | // T <- D_{R^{2d,dk},sigma} 38 | begin_timing = cpucycles_start(); 39 | 40 | SampleR_matrix_centered((signed_poly_matrix) T, 2*PARAM_D, PARAM_D * PARAM_K, PARAM_SIGMA); 41 | 42 | end_timing = cpucycles_stop(); 43 | timing_sampleZ_KG += (end_timing - begin_timing); 44 | 45 | // Compute the Schur complements 46 | begin_timing = cpucycles_start(); 47 | 48 | construct_complex_private_key(cplx_T, sch_comp, T); 49 | 50 | end_timing = cpucycles_stop(); 51 | timing_precomp_KG += (end_timing - begin_timing); 52 | 53 | 54 | begin_timing = cpucycles_start(); 55 | 56 | // Add q to each component of T and put it in the CRT domain 57 | for(int i = 0 ; i < PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K ; ++i) 58 | { 59 | T[i] += PARAM_Q; 60 | } 61 | 62 | matrix_ntt(T, 2*PARAM_D, PARAM_D * PARAM_K); 63 | freeze_poly(T, PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K - 1); 64 | 65 | // T1 and T2 are the upper and lower half of T 66 | poly_matrix T1 = T, T2 = poly_matrix_element(T, PARAM_D * PARAM_K, PARAM_D, 0); 67 | 68 | // AprimeT <- A_hat * T2 69 | mul_crt_poly_matrix(AprimeT, A_hat, T2, PARAM_D, PARAM_D, PARAM_D * PARAM_K); 70 | 71 | // Convert AprimeT from the NTT_res domain into the NTT_op domain 72 | multiply_by_2pow32(AprimeT, PARAM_N * PARAM_D * PARAM_D * PARAM_K - 1); 73 | 74 | // AprimeT <- AprimeT + T1 75 | add_to_poly_matrix(AprimeT, T1, PARAM_D, PARAM_D * PARAM_K); 76 | 77 | freeze_poly(AprimeT, PARAM_N * PARAM_D * PARAM_D * PARAM_K - 1); 78 | 79 | 80 | // AprimeT <- - AprimeT 81 | for(int i = 0 ; i < PARAM_N * PARAM_D * PARAM_D * PARAM_K ; ++i) 82 | { 83 | AprimeT[i] = 2 * PARAM_Q - AprimeT[i]; 84 | } 85 | 86 | 87 | // AprimeT <- AprimeT + G 88 | for(int i = 0 ; i < PARAM_D ; ++i) 89 | { 90 | poly_matrix AprimeT_iik = poly_matrix_element(AprimeT, PARAM_D * PARAM_K, i, i * PARAM_K); 91 | 92 | add_ring_gadget_vector(AprimeT_iik); 93 | } 94 | 95 | 96 | // A = (A_hat | -A'T) ( = (I | A_hat | -A'T) implicitly) 97 | for(int i = 0 ; i < PARAM_D ; ++i) 98 | { 99 | poly_matrix A_i0 = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 100 | poly_matrix A_hat_i = poly_matrix_element(A_hat, PARAM_D, i, 0); 101 | 102 | memcpy(A_i0, A_hat_i, PARAM_D * PARAM_N * sizeof(scalar)); 103 | } 104 | for(int i = 0 ; i < PARAM_D ; ++i) 105 | { 106 | poly_matrix A_id = poly_matrix_element(A, PARAM_M - PARAM_D, i, PARAM_D); 107 | poly_matrix AprimeT_i = poly_matrix_element(AprimeT, PARAM_D * PARAM_K, i, 0); 108 | 109 | memcpy(A_id, AprimeT_i, PARAM_N * PARAM_D * PARAM_K * sizeof(scalar)); 110 | } 111 | 112 | // Reduce A's coefficients mod q 113 | freeze_poly(A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) - 1); 114 | 115 | 116 | end_timing = cpucycles_stop(); 117 | timing_arith_KG += (end_timing - begin_timing); 118 | free(A_hat); 119 | free(AprimeT); 120 | } 121 | 122 | /* 123 | Signs a message m of length m_len using the signing key (T, cplx_T, sch_comp) and the verification key A 124 | */ 125 | void Sign(poly_matrix nu, uint8_t *r, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, uint8_t *m, int m_len) 126 | { 127 | // Generate a random salt 128 | salt(r); 129 | 130 | // Construct a target u using the message and the salt 131 | scalar u_coeffs[PARAM_D * PARAM_N]; 132 | poly_matrix u = u_coeffs; 133 | 134 | H(u, m, m_len, r); 135 | 136 | 137 | // Sample nu 138 | sample_pre(nu, A, T, cplx_T, sch_comp, u); 139 | } 140 | 141 | /* 142 | Checks is the signature nu is valid for the message m, given the verification key A 143 | */ 144 | bool Verify(poly_matrix nu, uint8_t *r, poly_matrix A, uint8_t *m, int m_len) 145 | { 146 | // Construct a target u using the message and the salt 147 | scalar u_coeffs[PARAM_D * PARAM_N]; 148 | poly_matrix u = u_coeffs; 149 | 150 | H(u, m, m_len, r); 151 | 152 | 153 | // Verify that A * nu = u mod q 154 | scalar prod_coeffs[PARAM_N * PARAM_D]; 155 | poly_matrix prod = prod_coeffs; 156 | 157 | multiply_by_A(prod, A, (poly_matrix) nu); 158 | 159 | 160 | 161 | // Verify that nu has a small norm 162 | divide_by_2pow32(nu, PARAM_N * PARAM_M - 1); 163 | matrix_invntt(nu, PARAM_M, 1); 164 | freeze_poly(nu, PARAM_N * PARAM_M - 1); 165 | 166 | double_scalar norm_nu_squared = norm_squared((poly_matrix) nu, PARAM_M); 167 | double bound_squared = PARAM_T * PARAM_T * PARAM_ZETA * PARAM_ZETA * PARAM_N * PARAM_M; 168 | 169 | 170 | matrix_ntt(nu, PARAM_M, 1); 171 | 172 | if(!equals_poly(prod, u, PARAM_N * PARAM_D - 1) || (norm_nu_squared >= bound_squared)) 173 | { 174 | return false; 175 | } 176 | 177 | return true; 178 | } 179 | -------------------------------------------------------------------------------- /ROM_GPV/signature.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp); 6 | 7 | void Sign(poly_matrix nu, uint8_t *r, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, uint8_t *m, int m_len); 8 | 9 | bool Verify(poly_matrix nu, uint8_t *r, poly_matrix A, uint8_t *m, int m_len); 10 | -------------------------------------------------------------------------------- /ROM_GPV/timing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "random.h" 7 | #include "sampling.h" 8 | #include "signature.h" 9 | #include "arithmetic.h" 10 | #include "hash.h" 11 | 12 | #include "cpucycles.h" 13 | 14 | #define MESSAGE_BYTES 512 // keep it divisible by 16 15 | #define NTESTS 100 16 | #define CPU_CYCLES (1.9 * 1000000000.0) 17 | 18 | unsigned long long timing_overhead; 19 | unsigned long long timing_sampleZ_G = 0; 20 | unsigned long long timing_sampleZ_P = 0; 21 | unsigned long long timing_sampleG = 0; 22 | unsigned long long timing_samplePerturb = 0; 23 | unsigned long long timing_sampleArith = 0; 24 | 25 | unsigned long long timing_sign = 0; 26 | 27 | unsigned long long timing_sampleZ_KG = 0; 28 | unsigned long long timing_precomp_KG = 0; 29 | unsigned long long timing_arith_KG = 0; 30 | unsigned long long timing_keygen = 0; 31 | 32 | unsigned long long timing_verify = 0; 33 | 34 | void time_keygen(void) 35 | { 36 | timing_overhead = cpucycles_overhead(); 37 | unsigned long long begin_timing = 0; 38 | unsigned long long end_timing = 0; 39 | 40 | 41 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 42 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 43 | poly_matrix A = A_coeffs, T = T_coeffs; 44 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 45 | 46 | 47 | 48 | for(unsigned i = 0; i < NTESTS; ++i) { 49 | 50 | begin_timing = cpucycles_start(); 51 | 52 | // Generate Keys 53 | KeyGen(A, T, cplx_T, sch_comp); 54 | 55 | end_timing = cpucycles_stop(); 56 | timing_keygen += (end_timing - begin_timing); 57 | } 58 | 59 | timing_sampleZ_KG = timing_sampleZ_KG/NTESTS - timing_overhead; 60 | timing_precomp_KG = timing_precomp_KG/NTESTS - timing_overhead; 61 | timing_arith_KG = timing_arith_KG/NTESTS - timing_overhead; 62 | double timing_total = timing_sampleZ_KG + timing_precomp_KG + timing_arith_KG; 63 | 64 | 65 | printf("----------- KeyGen -----------\n"); 66 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_sampleZ_KG, (timing_sampleZ_KG*1000)/CPU_CYCLES, (timing_sampleZ_KG/timing_total)*100.0); 67 | printf("Precomp : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_precomp_KG, (timing_precomp_KG*1000)/CPU_CYCLES, (timing_precomp_KG/timing_total)*100.0); 68 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_arith_KG, (timing_arith_KG*1000)/CPU_CYCLES, (timing_arith_KG/timing_total)*100.0); 69 | printf("-----\n"); 70 | 71 | timing_keygen = timing_keygen/NTESTS - timing_overhead; 72 | printf("Total: %lld cycles (%.2lf ms)\n", timing_keygen, (timing_keygen*1000)/CPU_CYCLES); 73 | 74 | printf("\n\n"); 75 | 76 | free(A); 77 | free(T); 78 | free(sch_comp); 79 | free(cplx_T); 80 | } 81 | 82 | void time_sign(void) 83 | { 84 | timing_overhead = cpucycles_overhead(); 85 | unsigned long long begin_timing = 0; 86 | unsigned long long end_timing = 0; 87 | 88 | 89 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 90 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 91 | poly_matrix A = A_coeffs, T = T_coeffs; 92 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 93 | 94 | // Generate Keys 95 | KeyGen(A, T, cplx_T, sch_comp); 96 | 97 | 98 | 99 | for(unsigned i = 0; i < NTESTS; ++i) { 100 | // Generate a message 101 | uint8_t m[MESSAGE_BYTES]; 102 | for(int i = 0 ; i < MESSAGE_BYTES / 16 ; ++i) { 103 | random_bytes(&m[16 * i]); 104 | } 105 | 106 | // Compute a signature (nu, r) 107 | uint8_t r[SALT_BYTES]; 108 | scalar nu_coeffs[PARAM_N * PARAM_M]; 109 | poly_matrix nu = nu_coeffs; 110 | 111 | begin_timing = cpucycles_start(); 112 | Sign(nu, r, A, T, cplx_T, sch_comp, m, MESSAGE_BYTES); 113 | end_timing = cpucycles_stop(); 114 | timing_sign += (end_timing - begin_timing); 115 | } 116 | 117 | timing_sampleZ_G = timing_sampleZ_G/NTESTS - timing_overhead; 118 | timing_sampleZ_P = timing_sampleZ_P/NTESTS - timing_overhead; 119 | unsigned long long timing_sampleZ = timing_sampleZ_G + timing_sampleZ_P; 120 | 121 | timing_sampleG = timing_sampleG/NTESTS - timing_overhead; 122 | timing_samplePerturb = timing_samplePerturb/NTESTS - timing_overhead; 123 | timing_sampleArith = timing_sampleArith/NTESTS - timing_overhead; 124 | double timing_samplePre = timing_sampleG + timing_samplePerturb + timing_sampleArith; 125 | 126 | 127 | printf("----------- SampleZ -----------\n"); 128 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleG)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, ((double) timing_sampleZ_G/timing_sampleG)*100.0); 129 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleP)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, ((double) timing_sampleZ_P/timing_samplePerturb)*100.0); 130 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ, (timing_sampleZ*1000)/CPU_CYCLES, ((double) timing_sampleZ/timing_samplePre)*100.0); 131 | 132 | 133 | printf("\n----------- SamplePre -----------\n"); 134 | printf("SampleG : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG, (timing_sampleG*1000)/CPU_CYCLES, (timing_sampleG/timing_samplePre)*100.0); 135 | printf("G-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, (timing_sampleZ_G/timing_samplePre)*100.0); 136 | printf("G-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG - timing_sampleZ_G, ((timing_sampleG - timing_sampleZ_G)*1000)/CPU_CYCLES, ((timing_sampleG - timing_sampleZ_G)/timing_samplePre)*100.0); 137 | printf("-----\n"); 138 | 139 | printf("SamplePerturb: %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb, (timing_samplePerturb*1000)/CPU_CYCLES, (timing_samplePerturb/timing_samplePre)*100.0); 140 | printf("P-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, (timing_sampleZ_P/timing_samplePre)*100.0); 141 | printf("P-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb - timing_sampleZ_P, ((timing_samplePerturb - timing_sampleZ_P)*1000)/CPU_CYCLES, ((timing_samplePerturb - timing_sampleZ_P)/timing_samplePre)*100.0); 142 | printf("-----\n"); 143 | 144 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleArith, (timing_sampleArith*1000)/CPU_CYCLES, (timing_sampleArith/timing_samplePre)*100.0); 145 | 146 | printf("\n----------- Signature -----------\n"); 147 | timing_sign = timing_sign/NTESTS - timing_overhead; 148 | printf("Signature: %lld cycles (%.2lf ms)\n", timing_sign, (timing_sign*1000)/CPU_CYCLES); 149 | 150 | printf("\n\n"); 151 | 152 | free(A); 153 | free(T); 154 | free(sch_comp); 155 | free(cplx_T); 156 | } 157 | 158 | void time_verify(void) 159 | { 160 | timing_overhead = cpucycles_overhead(); 161 | unsigned long long begin_timing = 0; 162 | unsigned long long end_timing = 0; 163 | 164 | 165 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 166 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 167 | poly_matrix A = A_coeffs, T = T_coeffs; 168 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 169 | 170 | 171 | // Generate Keys 172 | KeyGen(A, T, cplx_T, sch_comp); 173 | 174 | // Generate a message 175 | uint8_t m[MESSAGE_BYTES]; 176 | for(int i = 0 ; i < MESSAGE_BYTES / 16 ; ++i) { 177 | random_bytes(&m[16 * i]); 178 | } 179 | 180 | // Compute a signature (nu, r) 181 | uint8_t r[SALT_BYTES]; 182 | scalar nu_coeffs[PARAM_N * PARAM_M]; 183 | poly_matrix nu = nu_coeffs; 184 | 185 | Sign(nu, r, A, T, cplx_T, sch_comp, m, MESSAGE_BYTES); 186 | 187 | for(unsigned i = 0; i < NTESTS; ++i) { 188 | 189 | begin_timing = cpucycles_start(); 190 | 191 | Verify(nu, r, A, m, MESSAGE_BYTES); 192 | 193 | end_timing = cpucycles_stop(); 194 | timing_verify += (end_timing - begin_timing); 195 | } 196 | 197 | 198 | printf("----------- Verify -----------\n"); 199 | 200 | timing_verify = timing_verify/NTESTS - timing_overhead; 201 | printf("Total: %lld cycles (%.2lf ms)\n", timing_verify, (timing_verify*1000)/CPU_CYCLES); 202 | 203 | printf("\n\n"); 204 | 205 | free(A); 206 | free(T); 207 | free(sch_comp); 208 | free(cplx_T); 209 | } 210 | 211 | int main(void) { 212 | 213 | init_D_lattice_coeffs(); 214 | init_cplx_roots_of_unity(); 215 | 216 | time_keygen(); 217 | 218 | time_sign(); 219 | 220 | time_verify(); 221 | 222 | 223 | return 0; 224 | } 225 | 226 | -------------------------------------------------------------------------------- /Standard_BFRS/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #CC = gcc 3 | CC = clang 4 | CFLAGS = -Wall -O3 -mtune=native 5 | CVECFLAGS := $(CFLAGS) -mavx2 -ftree-vectorize #-fopt-info-vec-optimized 6 | CFLAGS += -fno-tree-vectorize 7 | NFL_AVX = -DNFL_OPTIMIZED=ON -DNTT_AVX2 8 | 9 | EXEC = signature_tests sampling_tests timing main_signature 10 | 11 | OBJ = arithmetic.o random.o crt_trees.o 12 | 13 | HDR = common.h 14 | 15 | all: sampling_tests signature_tests 16 | 17 | timing: timing.o crt_trees.o signature.o sampling.o random.o arithmetic.o cpucycles.o 18 | $(CC) $(CFLAGS) -o $@ $^ -lm 19 | 20 | signature_tests: signature_tests.o signature.o sampling.o random.o arithmetic.o crt_trees.o 21 | $(CC) $(CFLAGS) -o $@ $^ -lm 22 | 23 | main_signature: main_signature.o signature.o sampling.o random.o $(OBJ) 24 | $(CC) $(CFLAGS) -o $@ $^ -lm 25 | 26 | sampling_tests: sampling_tests.o sampling.o random.o arithmetic.o crt_trees.o 27 | $(CC) $(CFLAGS) -o $@ $^ -lm 28 | 29 | 30 | arithmetic.o: arithmetic.c random.o $(HDR) 31 | $(CC) $(CVECFLAGS) -c -o $@ $< 32 | 33 | sampling.o: sampling.c random.o $(HDR) 34 | $(CC) $(CVECFLAGS) -c -o $@ $< 35 | 36 | random.o: random.c 37 | $(CC) $(CVECFLAGS) -maes -c -o $@ $< 38 | 39 | %.o: %.c $(HDR) 40 | $(CC) $(CFLAGS) -c -o $@ $< 41 | 42 | clean: 43 | rm -f $(EXEC) *.o *.s 44 | -------------------------------------------------------------------------------- /Standard_BFRS/Misc/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -g -Wall 3 | 4 | EXEC = multiplicative_order primes 5 | 6 | all: $(EXEC) 7 | 8 | multiplicative_order: multiplicative_order.c 9 | $(CC) $(CFLAGS) -o $@ $^ 10 | 11 | primes: primes.c 12 | $(CC) $(CFLAGS) -o $@ $^ -lgmp 13 | 14 | clean: 15 | rm -f $(EXEC) 16 | -------------------------------------------------------------------------------- /Standard_BFRS/Misc/multiplicative_order.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // a^x mod m 6 | uint64_t mod_exp(uint64_t a, uint64_t x, uint64_t m) 7 | { 8 | uint64_t r = 1; 9 | 10 | for(int i=0 ; i < 64 ; i++) 11 | { 12 | if(x & 1) 13 | { 14 | r = (((r * a) % m) + m) % m; 15 | } 16 | a = (((a * a) % m) + m) % m; 17 | x = x >> 1; 18 | } 19 | 20 | return r; 21 | } 22 | 23 | // multiplicative order of a mod 2^e 24 | uint64_t order(uint64_t a, uint64_t e) 25 | { 26 | uint64_t ones = (1 << e) - 1; 27 | 28 | for(int i=0 ; i < e ; i++) 29 | { 30 | if(a == 1) 31 | { 32 | return (1 << i); 33 | } 34 | a = (a * a) & ones; 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | if(argc < 4) 43 | { 44 | fprintf(stderr, "Usage : %s a e d\n", argv[0]); 45 | exit(EXIT_FAILURE); 46 | } 47 | 48 | uint64_t a, e, a_i, d; 49 | 50 | sscanf(argv[1], "%" SCNu64, &a); 51 | sscanf(argv[2], "%" SCNu64, &e); 52 | sscanf(argv[3], "%" SCNu64, &d); 53 | 54 | uint64_t ones = (1 << e) - 1; 55 | 56 | for(int i=1 ; i <= d ; i++) 57 | { 58 | a_i = mod_exp(a, i, (1 << e)); 59 | printf("%" PRIu64 " = %" PRIu64 "^%d has multiplicative order %" PRIu64 " mod 2^%" PRIu64 "\n", a_i, a, i, order(a_i, e), e); 60 | } 61 | 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /Standard_BFRS/Misc/primes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **argv) 7 | { 8 | mpz_t N; 9 | uint64_t n; 10 | 11 | mpz_init(N); 12 | 13 | printf("Finding sparse primes congruent to 17 mod 32...\n"); 14 | 15 | printf("Finding primes of the form 2^i + 2^4 + 1...\n"); 16 | for(uint64_t i = 5 ; i < 64 ; i++) 17 | { 18 | n = (((uint64_t) 1)< 5 | #include 6 | 7 | 8 | #include "common.h" 9 | 10 | int get_bit_b(scalar x, scalar i); 11 | 12 | void ntt(uint32_t p[PARAM_N]); 13 | 14 | void invntt_frominvmont(uint32_t p[PARAM_N]); 15 | 16 | void divide_by_2pow32(poly f, int deg); 17 | 18 | void multiply_by_2pow32(poly f, int deg); 19 | 20 | scalar barrett_reduce(double_scalar a); 21 | 22 | scalar csubq(scalar a); 23 | 24 | uint32_t montgomery_reduce(uint64_t a); 25 | 26 | void poly_pointwise_invmontgomery(poly c, const poly a, const poly b); 27 | 28 | void matrix_ntt(poly_matrix A, int l1, int l2); 29 | 30 | void matrix_invntt(poly_matrix A, int l1, int l2); 31 | 32 | scalar reduce_naive(scalar x); 33 | 34 | signed_scalar reduce_signed_double_naive(signed_double_scalar x); 35 | 36 | scalar reduce_signed_double_to_positive_naive(signed_double_scalar x); 37 | 38 | scalar reduce_signed_naive(signed_scalar x); 39 | 40 | scalar reduce_sparse(scalar x); 41 | 42 | scalar reduce_double_naive(double_scalar x); 43 | 44 | scalar reduce_double_sparse(double_scalar x); 45 | 46 | scalar reduce_double_montgomery(double_scalar x); 47 | 48 | signed_scalar signed_scalar_inverse(signed_scalar x); 49 | 50 | void polynomial_division(signed_poly quo, signed_poly rem, signed_poly a, signed_poly b, int deg_a, int deg_b); 51 | 52 | void invert_poly(poly f_inv, poly f, int deg, scalar c); 53 | 54 | void alloc_poly(poly f, int deg); 55 | 56 | void alloc_double_poly(double_poly f, int deg); 57 | 58 | void free_poly(poly f); 59 | 60 | void free_double_poly(double_poly f); 61 | 62 | void print_poly(poly f, int deg); 63 | 64 | void print_double_poly(double_poly f, int deg); 65 | 66 | void print_signed_poly(signed_poly f, int deg); 67 | 68 | void print_signed_double_poly(signed_double_poly f, int deg); 69 | 70 | void print_poly_matrix(poly_matrix A, int l1, int l2); 71 | 72 | void print_signed_poly_matrix(signed_poly_matrix A, int l1, int l2); 73 | 74 | bool equals_poly(poly f, poly g, int deg); 75 | 76 | void print_cplx_poly(cplx_poly f, int deg); 77 | 78 | void print_cplx_poly_matrix(cplx_poly_matrix A, int l1, int l2); 79 | 80 | void print_triangular_cplx_poly_matrix(cplx_poly_matrix A, int l); 81 | 82 | void zero_poly(poly f, int deg); 83 | 84 | bool is_zero_poly(poly f, int deg); 85 | 86 | void freeze_poly(poly f, int deg); 87 | 88 | void freeze_double_poly(poly f, double_poly double_f, int deg); 89 | 90 | void freeze_upper_half_double_poly(double_poly double_f, int deg); 91 | 92 | void freeze_signed_poly(poly f_out, signed_poly f_in, int deg); 93 | 94 | void freeze_signed_double_poly(signed_poly f_out, signed_double_poly f_in, int deg); 95 | 96 | void freeze_signed_double_poly_to_positive(poly f_out, signed_double_poly f_in, int deg); 97 | 98 | void random_poly(poly f, int deg); 99 | 100 | void add_poly(poly h, poly f, poly g, int deg); 101 | 102 | void add_double_poly(double_poly h, double_poly f, double_poly g, int deg); 103 | 104 | void add_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 105 | 106 | void sub_signed_poly(signed_poly h, signed_poly f, signed_poly g, int deg); 107 | 108 | void sub_poly(poly h, poly f, poly g, int deg); 109 | 110 | void mul_full_poly_naive(poly h, poly f, poly g); 111 | 112 | void mul_poly_naive(poly h, poly f, poly g, int deg, scalar c); 113 | 114 | void mul_poly_crt(poly h, poly f, poly g); 115 | 116 | void mul_poly_crt_rec(poly h, poly f, poly g, int depth, int index); 117 | 118 | void mul_poly_crt_with_max_depth(poly h, poly f, poly g, int depth, int index, int max_depth); 119 | 120 | void reduce_poly_mod_sparse(poly h, poly f, int deg, scalar c); 121 | 122 | void modulo_cyclotomic_poly(poly f); 123 | 124 | void modulo_cyclotomic_signed_poly(signed_poly f); 125 | 126 | void modulo_cyclotomic_double_poly(double_poly f); 127 | 128 | void invert_crt(poly f, poly f1, poly f2, int deg, scalar c1, scalar c2, scalar u, scalar v); 129 | 130 | void crt_representation(poly f, int max_depth); 131 | 132 | void coeffs_representation(poly f, int max_depth); 133 | 134 | void mul_crt_poly(double_poly crt_h, poly crt_f, poly crt_g, int depth); 135 | 136 | void reduce_double_crt_poly(poly crt_f, double_poly double_crt_f, int depth); 137 | 138 | 139 | 140 | void mul_poly_schoolbook(double_poly h, poly f, poly g, int deg_f, int deg_g); 141 | 142 | void mul_signed_poly_schoolbook(signed_double_poly h, signed_poly f, signed_poly g, int deg_f, int deg_g); 143 | 144 | void mul_signed_poly_karatsuba(signed_poly h, signed_poly f, signed_poly g, int deg); 145 | 146 | void mul_poly_karatsuba(poly h, poly f, poly g, int deg); 147 | 148 | void modulo_poly(double_poly p, poly f, int deg, scalar c); 149 | 150 | void modulo_double_poly(double_poly f, int deg, scalar c); 151 | 152 | void modulo_signed_poly(signed_double_poly f_out, signed_poly f_in, int deg, scalar c); 153 | 154 | void mul_and_reduce_full_poly_karatsuba(poly h, poly f, poly g); 155 | 156 | void matrix_crt_representation(poly_matrix A, int l1, int l2, int depth); 157 | 158 | void matrix_coeffs_representation(poly_matrix A, int l1, int l2, int depth); 159 | 160 | void mul_crt_poly_matrix(poly_matrix H, poly_matrix F, poly_matrix G, int l1, int l2, int l3, int depth); 161 | 162 | void add_to_poly_matrix(poly_matrix A, poly_matrix B, int l1, int l2); 163 | 164 | void multiply_by_scalar_gadget_vector(scalar *prod, signed_scalar *v); 165 | 166 | void multiply_by_ring_gadget_vector(poly prod, signed_poly_matrix v); 167 | 168 | void multiply_by_module_gadget_matrix(poly_matrix res, signed_poly_matrix v); 169 | 170 | void multiply_by_A(poly_matrix y, poly_matrix A, poly_matrix x); 171 | 172 | void multiply_by_TI(poly_matrix y, poly_matrix T, poly_matrix x); 173 | 174 | void multiply_by_T(poly_matrix y, poly_matrix T, poly_matrix x); 175 | 176 | void construct_A_m(poly_matrix A, scalar *m); 177 | 178 | void deconstruct_A_m(poly_matrix A, scalar *m); 179 | 180 | double_scalar norm_squared(poly_matrix v, int l); 181 | 182 | void zero_cplx_poly(cplx_poly f, int deg); 183 | 184 | void add_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 185 | 186 | void fma_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 187 | 188 | void sub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 189 | 190 | void fmsub_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 191 | 192 | void inv_cplx_poly(cplx_poly h, cplx_poly f, int deg); 193 | 194 | void mul_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 195 | 196 | void div_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 197 | 198 | void mul_cplx_poly_by_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 199 | 200 | void mul_cplx_poly_by_own_transpose(cplx_poly h, cplx_poly f, int deg); 201 | 202 | void cplx_fma_transpose(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 203 | 204 | void fmsub_transpose_cplx_poly(cplx_poly h, cplx_poly f, cplx_poly g, int deg); 205 | 206 | void transpose_cplx_poly(cplx_poly f, int deg); 207 | 208 | void stride(cplx_poly f, int depth); 209 | 210 | void inverse_stride(cplx_poly f, int depth); 211 | 212 | void scalar_stride(signed_scalar *p, int size); 213 | 214 | void reduce_mod_sparse_cplx_poly(cplx_poly f, int deg, cplx c); 215 | 216 | void cplx_crt_representation(cplx_poly f); 217 | 218 | void matrix_cplx_crt_representation(cplx_poly_matrix M, int l1, int l2); 219 | 220 | void construct_T_schur_complement(cplx_poly_matrix sch_comp, cplx_poly_matrix T); 221 | 222 | void construct_schur_complement_and_center(cplx_poly_matrix M, cplx_poly_matrix c, cplx_poly d, cplx_poly x1, int l); 223 | 224 | void construct_schur_complement(cplx_poly_matrix M, int l); 225 | 226 | void construct_new_center(cplx_poly_matrix c, cplx_poly_matrix M, cplx_poly q1, int l); 227 | 228 | void construct_first_center(cplx_poly_matrix c, cplx_poly_matrix T, cplx_poly_matrix p); 229 | 230 | void construct_complex_private_key(cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly_matrix T); 231 | 232 | void init_crt_trees(void); 233 | 234 | void init_cplx_roots_of_unity(void); 235 | 236 | #endif 237 | -------------------------------------------------------------------------------- /Standard_BFRS/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // ------------------- 9 | // DEFINING PARAMETERS 10 | // ------------------- 11 | 12 | //#define TESTING_ZETA 13 | 14 | /*// q = 1073741441, d = 4, r = 64 15 | #define PARAM_Q 1073741441 // modulus q 16 | #define PARAM_K 30 // size of q 17 | #define PARAM_N 256 // degree of polynomials 18 | #define PARAM_R 64 // number of irreducible factors of x^n + 1 in F_q[x] 19 | #define PARAM_D 4 // rank of the module 20 | #define PARAM_SIGMA 7.00 // Gaussian parameter (generation of the trapdoor) 21 | #define PARAM_ALPHA (48.34) // Gaussian parameter (sampling perturbations) 22 | #define PARAM_ZETA (83832.0) // Gaussian parameter (presampling) 23 | #define PARAM_T 12 // Tailcut 24 | */ 25 | 26 | /*// q = 1073741441, d = 5, r = 64 27 | #define PARAM_Q 1073741441 // modulus q 28 | #define PARAM_K 30 // size of q 29 | #define PARAM_N 256 // degree of polynomials 30 | #define PARAM_R 64 // number of irreducible factors of x^n + 1 in F_q[x] 31 | #define PARAM_D 5 // rank of the module 32 | #define PARAM_SIGMA 5.55 // Gaussian parameter (generation of the trapdoor) 33 | #define PARAM_ALPHA (54.35) // Gaussian parameter (sampling perturbations) 34 | #define PARAM_ZETA (83290.0) // Gaussian parameter (presampling) 35 | #define PARAM_T 14 // Tailcut 36 | #define PARAM_B 2 37 | */ 38 | 39 | // q = 1073740609, d = 6, r = 32 40 | #define PARAM_Q 1073740609 // modulus q 41 | #define PARAM_K 30 // size of q 42 | #define PARAM_N 256 // degree of polynomials 43 | #define PARAM_R 32 // number of irreducible factors of x^n + 1 in F_q[x] 44 | #define PARAM_D 6 // rank of the module 45 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 46 | #define PARAM_ALPHA (60.50) // Gaussian parameter (sampling perturbations) 47 | #define PARAM_ZETA (112522.0) // Gaussian parameter (presampling) 48 | #define PARAM_T 15 // Tailcut 49 | #define PARAM_B 2 50 | 51 | 52 | /* 53 | #define MONT 4860 54 | #define MONT2 23619600 55 | #define QINV 62745407 56 | #define BARRETT_MULT 4 57 | #define BARRETT_SHIFT 32 58 | */ 59 | 60 | /*// q = 1073739937, d = 4, r = 16 61 | #define PARAM_Q 1073739937 // modulus q 62 | #define PARAM_K 30 // size of q 63 | #define PARAM_N 256 // degree of polynomials 64 | #define PARAM_R 16 // number of irreducible factors of x^n + 1 in F_q[x] 65 | #define PARAM_D 6 // rank of the module 66 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 67 | #define PARAM_ALPHA (60.50) // Gaussian parameter (sampling perturbations) 68 | #define PARAM_ZETA (112522.0) // Gaussian parameter (presampling) 69 | #define PARAM_T 15 // Tailcut 70 | #define PARAM_B 2 71 | */ 72 | /* 73 | #define MONT 7548 74 | #define MONT2 56972304 75 | #define QINV 26743967 76 | #define BARRETT_MULT 4 77 | #define BARRETT_SHIFT 32 78 | */ 79 | 80 | 81 | #define NTT_ALWAYS_REDUCE 82 | 83 | 84 | /*// Test parameter set 85 | //#define PARAM_Q 134218289 // modulus q 86 | //#define PARAM_Q 134221313 87 | #define PARAM_K 28 // size of q 88 | #define PARAM_N 256 // degree of polynomials 89 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 90 | #define PARAM_D 3 // rank of the module 91 | #define PARAM_SIGMA 4.470600 // Gaussian parameter (generation of the trapdoor) 92 | //#define PARAM_ZETA 4569.684701 // C = 0.4 93 | #define PARAM_ZETA 12566.627427 // C = 1.1 94 | //#define PARAM_ZETA 14851.468496 // C = 1.3 95 | //#define PARAM_ZETA 20563.571294 // C = 1.8 96 | #define PARAM_T 11 // Tailcut 97 | #define PARAM_B 2 98 | */ 99 | 100 | 101 | // Test parameter set 102 | // q = 1073740609, d = 6, r = 32 103 | /*#define PARAM_Q 1073740609 // modulus q 104 | #define PARAM_K 19 // size of q 105 | #define PARAM_N 256 // degree of polynomials 106 | #define PARAM_R 32 // number of irreducible factors of x^n + 1 in F_q[x] 107 | #define PARAM_D 6 // rank of the module 108 | #define PARAM_SIGMA 6.15 // Gaussian parameter (generation of the trapdoor) 109 | #define PARAM_ALPHA (103.53) // Gaussian parameter (sampling perturbations) 110 | #define PARAM_ZETA (184130.23) // Gaussian parameter (presampling) 111 | #define PARAM_T 15 // Tailcut 112 | #define PARAM_B 3*/ 113 | 114 | /*// Test parameter set 115 | #define PARAM_Q 8388593 // modulus q 116 | #define PARAM_K 23 // size of q 117 | #define PARAM_N 256 // degree of polynomials 118 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 119 | #define PARAM_D 3 // rank of the module 120 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 121 | #define PARAM_ZETA 9129.0 // Gaussian parameter (presampling) 122 | #define PARAM_T 12 // Tailcut 123 | #define PARAM_B 2 124 | */ 125 | 126 | /*// Pauline parameter set, 81-bit classical security 127 | #define PARAM_Q 134218289 // modulus q 128 | #define PARAM_K 28 // size of q 129 | #define PARAM_N 256 // degree of polynomials 130 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 131 | #define PARAM_D 6 // rank of the module 132 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 133 | #define PARAM_ZETA 9129.0 // Gaussian parameter (presampling) 134 | #define PARAM_T 12 // Tailcut 135 | #define PARAM_B 2 136 | */ 137 | 138 | /*// Pauline parameter set, 97-bit classical security 139 | #define PARAM_Q 134218289 // modulus q 140 | #define PARAM_K 28 // size of q 141 | #define PARAM_N 256 // degree of polynomials 142 | #define PARAM_R 7 // number of irreducible factors of x^n + 1 in F_q[x] 143 | #define PARAM_D 6 // rank of the module 144 | #define PARAM_SIGMA 4.5 // Gaussian parameter (generation of the trapdoor) 145 | #define PARAM_ZETA 12165.0 // Gaussian parameter (presampling) 146 | #define PARAM_T 12 // Tailcut 147 | #define PARAM_B 2 148 | */ 149 | 150 | // ------------------ 151 | // DERIVED PARAMETERS 152 | // ------------------ 153 | 154 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 155 | #define PARAM_M (PARAM_D * (PARAM_K + 2)) // parameter m ( = d(k+2) for the computational instantiation) 156 | //#define PARAM_ALPHA (3.0 * PARAM_SIGMA) // Gaussian parameter (sampling perturbations) 157 | 158 | /*// Parameters for n = 256, q = 8388593 159 | #define PARAM_Q 8388593 // modulus q 160 | #define PARAM_K 23 // size of q 161 | #define PARAM_N 256 // degree of polynomials 162 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 163 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 164 | */ 165 | 166 | /* 167 | // Parameters for n = 8, q = 8000053 168 | #define PARAM_Q 8000053 // modulus q 169 | #define PARAM_K 23 // size of q 170 | #define PARAM_N 8 // degree of polynomials 171 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 172 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 173 | */ 174 | 175 | /*// Parameters for n = 8, q = 13 176 | #define PARAM_Q 13 // modulus q 177 | #define PARAM_K 4 // size of q 178 | #define PARAM_N 8 // degree of polynomials 179 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 180 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 181 | */ 182 | 183 | /*// Parameters for n = 2, q = 13 184 | #define PARAM_Q 13 // modulus q 185 | #define PARAM_K 4 // size of q 186 | #define PARAM_N 2 // degree of polynomials 187 | #define PARAM_R 2 // number of irreducible factors of x^n + 1 in F_q[x] 188 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 189 | */ 190 | 191 | /*// Parameters for n = 256, q = 17 192 | #define PARAM_Q 17 // modulus q 193 | #define PARAM_K 5 // size of q 194 | #define PARAM_N 256 // degree of polynomials 195 | #define PARAM_R 8 // number of irreducible factors of x^n + 1 in F_q[x] 196 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 197 | */ 198 | 199 | /*// Parameters for n = 256, q = 7681 200 | #define PARAM_Q 7681 // modulus q 201 | #define PARAM_K 13 // size of q 202 | #define PARAM_N 256 // degree of polynomials 203 | #define PARAM_R 256 // number of irreducible factors of x^n + 1 in F_q[x] 204 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 205 | */ 206 | 207 | /*// Parameters for n = 256, q = 1032193 208 | #define PARAM_Q 1032193 // modulus q 209 | #define PARAM_K 20 // size of q 210 | #define PARAM_N 256 // degree of polynomials 211 | #define PARAM_R 256 // number of irreducible factors of x^n + 1 in F_q[x] 212 | #define SMALL_DEGREE (PARAM_N / PARAM_R) // degree of irreducible factors of x^n + 1 in F_q[x] 213 | */ 214 | 215 | 216 | // LOG_N = base 2 log of n, defines the depth of the complex factorisation tree 217 | #if (PARAM_N == 256) 218 | #define LOG_N 8 219 | #elif (PARAM_N == 512) 220 | #define LOG_N 9 221 | #elif (PARAM_N == 8) 222 | #define LOG_N 3 223 | #else 224 | #error "LOG_N is not defined for this value of PARAM_N" 225 | #endif 226 | 227 | // LOG_R = base 2 log of r, defines the depth of the factorisation tree 228 | #if (PARAM_R == 64) 229 | #define LOG_R 6 230 | #elif (PARAM_R == 32) 231 | #define LOG_R 5 232 | #elif (PARAM_R == 16) 233 | #define LOG_R 4 234 | #elif (PARAM_R == 8) 235 | #define LOG_R 3 236 | #elif (PARAM_R == 2) 237 | #define LOG_R 1 238 | #else 239 | #error "LOG_R is not defined for this value of PARAM_R" 240 | #endif 241 | 242 | #if ((1 << LOG_N) != PARAM_N) 243 | #error "LOG_N is not base 2 log of PARAM_N" 244 | #endif 245 | 246 | #if ((1 << LOG_R) != PARAM_R) 247 | #error "LOG_R is not base 2 log of PARAM_R" 248 | #endif 249 | 250 | /*#if ((1 << PARAM_K) < PARAM_Q) || ((1 << (PARAM_K - 1)) >= PARAM_Q) 251 | #error "PARAM_K is not base 2 log of PARAM_Q" 252 | #endif*/ 253 | 254 | #if (PARAM_K < 2) 255 | #error "PARAM_K < 2, not enough space in cplx_p_coeffs (sample_perturb)" 256 | #endif 257 | 258 | //#define GET_BIT(x, i) (((x) >> (i)) & 1) 259 | 260 | 261 | #define GET_BIT(x, i) get_bit_b(x, i) 262 | #define Q_BIT(i) get_bit_b(PARAM_Q, i) 263 | 264 | //#define DOUBLE_ZERO (((double_scalar) PARAM_Q) << (8*sizeof(double_scalar) - PARAM_K - 1)) // a double_scalar that is 0 mod q, such that there will be no underflow nor overflow during computations 265 | #define DOUBLE_ZERO (((double_scalar) PARAM_Q) * PARAM_Q) // a double_scalar that is 0 mod q, such that there will be no underflow nor overflow during computations 266 | #define SIGNED_DOUBLE_ZERO (((double_scalar) PARAM_Q) << (8*sizeof(double_scalar) - PARAM_K - 2)) 267 | 268 | typedef uint32_t scalar; 269 | typedef uint64_t double_scalar; 270 | typedef int32_t signed_scalar; 271 | typedef int64_t signed_double_scalar; 272 | 273 | typedef double complex cplx; 274 | typedef cplx *cplx_poly; 275 | typedef cplx *cplx_poly_matrix; 276 | 277 | #if (PARAM_Q > 0x7FFFFFFF) 278 | #error "Modulus PARAM_Q does not fit in 31 bits" 279 | #endif 280 | 281 | /* 282 | #if (LOG_N - LOG_R + 2 * PARAM_K) >= 63 283 | #error "(n/r)*q^2 >= 2^63, there might be overflow in polynomial multiplication" 284 | #endif 285 | */ 286 | // Polynomial in standard (coefficients) representation 287 | typedef scalar *poly; 288 | 289 | // Non-normalized polynomial with double_scalar coefficients 290 | typedef double_scalar *double_poly; 291 | 292 | // Polynomial with signed coefficients (used in Karatsuba) 293 | typedef signed_scalar *signed_poly; 294 | 295 | // Polynomial with signed_double_scalar coefficients (used in Karatsuba) 296 | typedef signed_double_scalar *signed_double_poly; 297 | 298 | // Matrix of polynomials (single pointer on scalars, everything is accessed through macros) 299 | typedef scalar *poly_matrix; 300 | 301 | // Matrix of signed polynomials, used when sampling since Gaussian values are signed 302 | typedef signed_scalar *signed_poly_matrix; 303 | 304 | #define poly_matrix_element(M, nb_col, i, j) (&M[(PARAM_N)*(((i)*(nb_col)) + (j))]) 305 | 306 | #define crt_poly_component(f, deg, i) (&(f)[(i)*(deg)]) 307 | 308 | #define triangular_poly_matrix_element(M, i, j) (&M[(PARAM_N) * ((i)*((i)+1)/2 + (j))]) 309 | 310 | extern scalar cyclotomic_factorisation_array[2*PARAM_R - 1]; 311 | extern scalar *cyclotomic_factorisation_tree[LOG_R + 1]; 312 | extern scalar bezout_coefficients_array[2*PARAM_R - 1]; 313 | extern scalar *bezout_coefficients_tree[LOG_R + 1]; 314 | extern cplx cplx_roots_of_unity[2*PARAM_N - 1]; 315 | 316 | //#define cplx_root_of_unity_of_order(k, i) (cplx_roots_of_unity[(2 * (PARAM_N) / (k) * (i))]) 317 | 318 | #define cplx_cyclotomic_factorisation_tree(i, j) (cplx_roots_of_unity[(1 << (i)) + (j) - 1]) 319 | 320 | /* 321 | Stuff for Gaussian sampling 322 | */ 323 | typedef long double RR_t; 324 | typedef double real; 325 | #define LDRMX ((RR_t) RAND_MAX) 326 | #define LOG_2 0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202357581305570326707516L 327 | #define SIGMA_1 0.84932180028801904272150283410288961971514109378435394286159953238339383120795466719298223538163406787061691601172910413284884326532697308797136114023L //sqrt(1/(2*log(2))) 328 | 329 | #endif 330 | -------------------------------------------------------------------------------- /Standard_BFRS/cpucycles.c: -------------------------------------------------------------------------------- 1 | #include "cpucycles.h" 2 | 3 | unsigned long long cpucycles_overhead(void) { 4 | unsigned long long t0, t1, overhead = -1; 5 | unsigned int i; 6 | 7 | for(i = 0; i < 100000; ++i) { 8 | t0 = cpucycles_start(); 9 | asm volatile(""); 10 | t1 = cpucycles_stop(); 11 | if(t1 - t0 < overhead) 12 | overhead = t1 - t0; 13 | } 14 | 15 | return overhead; 16 | } 17 | -------------------------------------------------------------------------------- /Standard_BFRS/cpucycles.h: -------------------------------------------------------------------------------- 1 | #ifndef CPUCYCLES_H 2 | #define CPUCYCLES_H 3 | 4 | #ifdef DBENCH 5 | #define DBENCH_START() unsigned long long time = cpucycles_start() 6 | #define DBENCH_STOP(t) t += cpucycles_stop() - time - timing_overhead 7 | #else 8 | #define DBENCH_START() 9 | #define DBENCH_STOP(t) 10 | #endif 11 | 12 | #ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ 13 | #ifdef SERIALIZE_RDC 14 | 15 | static inline unsigned long long cpucycles_start(void) { 16 | const unsigned int ecx = (1U << 30) + 1; 17 | unsigned long long result; 18 | 19 | asm volatile("cpuid; movl %1,%%ecx; rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 20 | : "=&a" (result) : "r" (ecx) : "rbx", "rcx", "rdx"); 21 | 22 | return result; 23 | } 24 | 25 | static inline unsigned long long cpucycles_stop(void) { 26 | const unsigned int ecx = (1U << 30) + 1; 27 | unsigned long long result, dummy; 28 | 29 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax; movq %%rax,%0; cpuid" 30 | : "=&r" (result), "=c" (dummy) : "c" (ecx) : "rax", "rbx", "rdx"); 31 | 32 | return result; 33 | } 34 | 35 | #else 36 | 37 | static inline unsigned long long cpucycles_start(void) { 38 | const unsigned int ecx = (1U << 30) + 1; 39 | unsigned long long result; 40 | 41 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 42 | : "=a" (result) : "c" (ecx) : "rdx"); 43 | 44 | return result; 45 | } 46 | 47 | static inline unsigned long long cpucycles_stop(void) { 48 | const unsigned int ecx = (1U << 30) + 1; 49 | unsigned long long result; 50 | 51 | asm volatile("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" 52 | : "=a" (result) : "c" (ecx) : "rdx"); 53 | 54 | return result; 55 | } 56 | 57 | #endif 58 | #else 59 | #ifdef SERIALIZE_RDC 60 | 61 | static inline unsigned long long cpucycles_start(void) { 62 | unsigned long long result; 63 | 64 | asm volatile("cpuid; rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 65 | : "=a" (result) : : "%rbx", "%rcx", "%rdx"); 66 | 67 | return result; 68 | } 69 | 70 | static inline unsigned long long cpucycles_stop(void) { 71 | unsigned long long result; 72 | 73 | asm volatile("rdtscp; shlq $32,%%rdx; orq %%rdx,%%rax; mov %%rax,%0; cpuid" 74 | : "=r" (result) : : "%rax", "%rbx", "%rcx", "%rdx"); 75 | 76 | return result; 77 | } 78 | 79 | #else 80 | 81 | static inline unsigned long long cpucycles_start(void) { 82 | unsigned long long result; 83 | 84 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 85 | : "=a" (result) : : "%rdx"); 86 | 87 | return result; 88 | } 89 | 90 | static inline unsigned long long cpucycles_stop(void) { 91 | unsigned long long result; 92 | 93 | asm volatile("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" 94 | : "=a" (result) : : "%rdx"); 95 | 96 | return result; 97 | } 98 | 99 | #endif 100 | #endif 101 | 102 | unsigned long long cpucycles_overhead(void); 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /Standard_BFRS/main_signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "arithmetic.h" 9 | #include "sampling.h" 10 | #include "signature.h" 11 | 12 | void check_trapgen(void) 13 | { 14 | scalar A_coeffs[PARAM_D * (PARAM_M - PARAM_D) * PARAM_N], TI_coeffs[PARAM_M * PARAM_D * PARAM_K * PARAM_N], prod_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N], AwithI_coeffs[PARAM_D * PARAM_M * PARAM_N]; 15 | poly_matrix A = A_coeffs, T = TI_coeffs, TI = TI_coeffs, Idk = poly_matrix_element(TI, PARAM_D * PARAM_K, 2*PARAM_D, 0), prod = prod_coeffs, AwithI = AwithI_coeffs; 16 | 17 | // Generate A and T 18 | TrapGen(A, T); 19 | 20 | // Generate Idk (in the CRT domain) and append it to T vertically 21 | memset(Idk, 0, PARAM_D * PARAM_K * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 22 | for(int i = 0 ; i < PARAM_D * PARAM_K ; ++i) 23 | { 24 | poly p_i = poly_matrix_element(Idk, PARAM_D * PARAM_K, i, i); 25 | for(int j = 0 ; j < PARAM_R ; ++j) 26 | { 27 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 28 | p_ij[0] = 1; 29 | } 30 | } 31 | 32 | // Prepend Id (in the CRT domain) to A horizontally 33 | for(int i = 0 ; i < PARAM_D ; ++i) 34 | { 35 | poly_matrix AwithI_i = poly_matrix_element(AwithI, PARAM_M, i, 0); 36 | poly_matrix A_i = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 37 | 38 | // build Id 39 | memset(AwithI_i, 0, PARAM_D * PARAM_N * sizeof(scalar)); 40 | poly p_i = poly_matrix_element(AwithI, PARAM_M, i, i); 41 | for(int j = 0 ; j < PARAM_R ; ++j) 42 | { 43 | poly p_ij = crt_poly_component(p_i, SMALL_DEGREE, j); 44 | p_ij[0] = 1; 45 | } 46 | 47 | // copy A 48 | memcpy(poly_matrix_element(AwithI_i, PARAM_M, 0, PARAM_D), A_i, (PARAM_M - PARAM_D) * PARAM_N * sizeof(scalar)); 49 | } 50 | 51 | 52 | // prod = AwithI * TI 53 | mul_crt_poly_matrix(prod, AwithI, TI, PARAM_D, PARAM_M, PARAM_D * PARAM_K, LOG_R); 54 | 55 | 56 | 57 | for(int i = 0 ; i < PARAM_D * PARAM_D * PARAM_K * PARAM_N ; ++i) 58 | { 59 | if(prod[i] != 0) 60 | { 61 | printf("%d : %" PRIu32 "\n", i, prod[i]); 62 | } 63 | else 64 | { 65 | } 66 | } 67 | } 68 | 69 | int main(int argc, char **argv) 70 | { 71 | init_crt_trees(); 72 | init_D_lattice_coeffs(); 73 | init_cplx_roots_of_unity(); 74 | 75 | srand48(0); 76 | srand(0); 77 | 78 | 79 | check_trapgen(); 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /Standard_BFRS/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "random.h" 10 | 11 | /* 12 | Returns an integer sampled from the uniform distribution over [0, n] 13 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 14 | */ 15 | uint32_t uniform_int_distribution(uint32_t n) 16 | { 17 | uint32_t scaling = (UINT32_MAX) / (n + 1); 18 | uint32_t past = (n + 1) * scaling; 19 | uint32_t r_data[4]; 20 | 21 | while(true) 22 | { 23 | random_bytes((uint8_t *) r_data); 24 | 25 | for(int i = 0 ; i < 4 ; ++i) 26 | { 27 | uint32_t r = r_data[i]; 28 | 29 | if(r < past) 30 | { 31 | return r / scaling; 32 | } 33 | } 34 | } 35 | } 36 | 37 | /* 38 | Returns an integer sampled from the uniform distribution over [0, q-1] 39 | using the uniform distribution over [0, 2^32 - 1] provided by random_bytes 40 | */ 41 | scalar uniform_mod_q(void) 42 | { 43 | uint32_t scaling = (UINT32_MAX) / PARAM_Q; 44 | uint32_t past = PARAM_Q * scaling; 45 | uint32_t r_data[4]; 46 | 47 | while(true) 48 | { 49 | random_bytes((uint8_t *) r_data); 50 | 51 | for(int i = 0 ; i < 4 ; ++i) 52 | { 53 | uint32_t r = r_data[i]; 54 | 55 | if(r < past) 56 | { 57 | return r / scaling; 58 | } 59 | } 60 | } 61 | } 62 | 63 | /* 64 | Code from random_aesni.c 65 | */ 66 | 67 | //macros 68 | #define DO_ENC_BLOCK(m,k) \ 69 | do{\ 70 | m = _mm_xor_si128 (m, k[ 0]); \ 71 | m = _mm_aesenc_si128 (m, k[ 1]); \ 72 | m = _mm_aesenc_si128 (m, k[ 2]); \ 73 | m = _mm_aesenc_si128 (m, k[ 3]); \ 74 | m = _mm_aesenc_si128 (m, k[ 4]); \ 75 | m = _mm_aesenc_si128 (m, k[ 5]); \ 76 | __auto_type m5 = m;\ 77 | m = _mm_aesenc_si128 (m, k[ 6]); \ 78 | m = _mm_aesenc_si128 (m, k[ 7]); \ 79 | m = _mm_aesenc_si128 (m, k[ 8]); \ 80 | m = _mm_aesenc_si128 (m, k[ 9]); \ 81 | m = _mm_aesenclast_si128(m, k[10]);\ 82 | m = _mm_xor_si128(m, m5);\ 83 | }while(0) 84 | 85 | #define DO_DEC_BLOCK(m,k) \ 86 | do{\ 87 | m = _mm_xor_si128 (m, k[10+0]); \ 88 | m = _mm_aesdec_si128 (m, k[10+1]); \ 89 | m = _mm_aesdec_si128 (m, k[10+2]); \ 90 | m = _mm_aesdec_si128 (m, k[10+3]); \ 91 | m = _mm_aesdec_si128 (m, k[10+4]); \ 92 | m = _mm_aesdec_si128 (m, k[10+5]); \ 93 | m = _mm_aesdec_si128 (m, k[10+6]); \ 94 | m = _mm_aesdec_si128 (m, k[10+7]); \ 95 | m = _mm_aesdec_si128 (m, k[10+8]); \ 96 | m = _mm_aesdec_si128 (m, k[10+9]); \ 97 | m = _mm_aesdeclast_si128(m, k[0]);\ 98 | }while(0) 99 | 100 | #define AES_128_key_exp(k, rcon) aes_128_key_expansion(k, _mm_aeskeygenassist_si128(k, rcon)) 101 | 102 | //the expanded key 103 | static __m128i key_schedule[20]; 104 | static uint64_t ctr = 0; 105 | 106 | static __m128i aes_128_key_expansion(__m128i key, __m128i keygened){ 107 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3)); 108 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 109 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 110 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); 111 | return _mm_xor_si128(key, keygened); 112 | } 113 | 114 | static void aes128_load_key(const int8_t * enc_key){ 115 | key_schedule[0] = _mm_loadu_si128((const __m128i*) enc_key); 116 | key_schedule[1] = AES_128_key_exp(key_schedule[0], 0x01); 117 | key_schedule[2] = AES_128_key_exp(key_schedule[1], 0x02); 118 | key_schedule[3] = AES_128_key_exp(key_schedule[2], 0x04); 119 | key_schedule[4] = AES_128_key_exp(key_schedule[3], 0x08); 120 | key_schedule[5] = AES_128_key_exp(key_schedule[4], 0x10); 121 | key_schedule[6] = AES_128_key_exp(key_schedule[5], 0x20); 122 | key_schedule[7] = AES_128_key_exp(key_schedule[6], 0x40); 123 | key_schedule[8] = AES_128_key_exp(key_schedule[7], 0x80); 124 | key_schedule[9] = AES_128_key_exp(key_schedule[8], 0x1B); 125 | key_schedule[10] = AES_128_key_exp(key_schedule[9], 0x36); 126 | 127 | // generate decryption keys in reverse order. 128 | // k[10] is shared by last encryption and first decryption rounds 129 | // k[0] is shared by first encryption round and last decryption round (and is the original user key) 130 | // For some implementation reasons, decryption key schedule is NOT the encryption key schedule in reverse order 131 | key_schedule[11] = _mm_aesimc_si128(key_schedule[9]); 132 | key_schedule[12] = _mm_aesimc_si128(key_schedule[8]); 133 | key_schedule[13] = _mm_aesimc_si128(key_schedule[7]); 134 | key_schedule[14] = _mm_aesimc_si128(key_schedule[6]); 135 | key_schedule[15] = _mm_aesimc_si128(key_schedule[5]); 136 | key_schedule[16] = _mm_aesimc_si128(key_schedule[4]); 137 | key_schedule[17] = _mm_aesimc_si128(key_schedule[3]); 138 | key_schedule[18] = _mm_aesimc_si128(key_schedule[2]); 139 | key_schedule[19] = _mm_aesimc_si128(key_schedule[1]); 140 | } 141 | 142 | static void aes128_enc(const int8_t * restrict plainText, int8_t * restrict cipherText){ 143 | __m128i m = _mm_loadu_si128((__m128i *) plainText); 144 | 145 | DO_ENC_BLOCK(m,key_schedule); 146 | 147 | _mm_storeu_si128((__m128i *) cipherText, m); 148 | } 149 | 150 | 151 | //public API 152 | void random_bytes_init(void) { 153 | // Open random file 154 | int randomData = open("/dev/urandom", O_RDONLY); 155 | 156 | // Seed the AES key 157 | uint8_t seed[16]; 158 | read(randomData, seed, sizeof(uint8_t)*16); 159 | aes128_load_key((int8_t *) seed); // don't know why the AES key is signed but whatever 160 | ctr = 0; 161 | 162 | // Don't forget to close the file !!! 163 | close(randomData); 164 | } 165 | 166 | void random_bytes(uint8_t * restrict data) { 167 | uint8_t plaintext[16] = {0}; 168 | *((uint64_t *) plaintext) = ctr++; 169 | aes128_enc((int8_t *) plaintext, (int8_t *) data); // let's cast them to signed because why not 170 | } 171 | 172 | /* 173 | Code from exp_aes.cpp 174 | */ 175 | 176 | double algorithm_EA(uint64_t * n) { 177 | const double ln2 = 0.6931471805599453; // log(2); 178 | const double a = 5.713363152645423; //(4+3*sqrt(2))*log(2); 179 | const double b = 3.414213562373095; // 2+sqrt(2); 180 | const double c = -1.6734053240284923; // -(1+sqrt(2))*log(2); 181 | const double p = 0.9802581434685472; //sqrt(2)*log(2); 182 | const double A = 5.6005707569738075; //a*p; 183 | const double B = 3.3468106480569846; // b*p; 184 | //const double z = c + 2; // unused ? 185 | //const double r = 1.010089582001449; // 8*exp(-z)*b*(b-1)*log(2)/(a*a); // unused ? 186 | //const double h = r - p; // unused ? 187 | const double D = 0.08578643762690495; // 1/(b*b); 188 | const double H = 0.0026106723602095233;// h*D/p; 189 | 190 | uint8_t data[16]; 191 | random_bytes(data); 192 | 193 | const unsigned long long int II = *((uint64_t *) data); 194 | const int j = __builtin_ctzll(II); 195 | const double G = c + j*ln2; 196 | 197 | const double U = *((uint16_t *) (data + 8)) / (UINT16_MAX*1.0); 198 | random_bytes(data); 199 | 200 | (*n)++; 201 | if (U <= p) { 202 | return G + A/(B - U); 203 | } 204 | //unsigned long long k = 0; // unused ? 205 | while(true) { 206 | for(unsigned i = 0; i < 4; i++) { 207 | (*n)++; 208 | const double U1 = *((uint16_t *) (data + i*2)) / (UINT16_MAX*1.0); 209 | const double U2 = *((uint16_t *) (data + i*2 + 8)) / (UINT16_MAX*1.0); 210 | 211 | const double bU1 = b - U1; 212 | const double Y = a/bU1; 213 | const double L = (U2*H + D)*(bU1)*(bU1); 214 | const double Z = Y + c; 215 | 216 | const double LZ = L - 1 + Z; 217 | const double ZZ = Z*Z; 218 | const bool cond1 = LZ <= 0; 219 | const bool cond2 = LZ - ZZ/2 + ZZ*Z/6 <= 0; 220 | const bool cond3 = LZ - ZZ <= 0; 221 | 222 | if (cond1 || cond2 || (cond3 && (L <= exp(-Z)))) { 223 | return G + Y; 224 | } 225 | // if(!cond1 && !cond2 && cond3) { 226 | // (*n)++; 227 | // } 228 | } 229 | random_bytes(data); 230 | } 231 | } 232 | 233 | /* 234 | Code from algoF_aes.cpp 235 | */ 236 | 237 | int algorithmF(double mu, double sigma) { 238 | const double sigma_floor = floor(sigma); 239 | const unsigned sigma_max = (unsigned) (((sigma_floor == sigma) && (sigma_floor != 0)) ? sigma - 1 : (sigma_floor)); 240 | 241 | 242 | uint8_t randomData[16]; 243 | random_bytes(randomData); 244 | while(true) { 245 | for(unsigned i = 0; i < 16; i++) { 246 | uint64_t n = 0; 247 | unsigned k = (unsigned) ceil(2*algorithm_EA(&n)) - 1; 248 | 249 | int s = (randomData[i] > 127) ? -1 : 1; 250 | //printf("\ts = %d\n", s); 251 | unsigned j = uniform_int_distribution(sigma_max); 252 | 253 | int i0 = ceil(sigma*k + s*mu); 254 | double x0 = (i0 - (sigma*k + s*mu))/sigma; 255 | double x = x0 + j/sigma; 256 | 257 | unsigned k1 = (unsigned) ceil(2*algorithm_EA(&n)) - 1; 258 | double z = algorithm_EA(&n); 259 | 260 | bool cond1 = k1 >= k*(k-1); 261 | bool cond2 = x < 1; 262 | bool cond3a = x != 0; 263 | bool cond3b = k != 0; 264 | bool cond3c = s == 1; 265 | bool cond3 = cond3a || cond3b || cond3c; 266 | bool cond4 = z > 0.5*x*(2*k+x); 267 | 268 | if (cond1 && cond2 && cond3 && cond4) { 269 | return s*(i0 + j); 270 | } 271 | } 272 | random_bytes(randomData); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /Standard_BFRS/random.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "common.h" 5 | 6 | uint32_t uniform_int_distribution(uint32_t n); 7 | 8 | scalar uniform_mod_q(void); 9 | 10 | /* 11 | Code from random_aesni.c 12 | */ 13 | 14 | //public API 15 | void random_bytes_init(void); 16 | 17 | void random_bytes(uint8_t * restrict data); 18 | 19 | /* 20 | Code from exp_aes.cpp 21 | */ 22 | 23 | double algorithm_EA(uint64_t * n); 24 | 25 | /* 26 | Code from algoF_aes.cpp 27 | */ 28 | 29 | int algorithmF(double mu, double sigma); 30 | -------------------------------------------------------------------------------- /Standard_BFRS/sage.sage: -------------------------------------------------------------------------------- 1 | #q = 7681 2 | #q = 8388593 3 | #q = 8000033 4 | #q = 1073741969 5 | #q = 1032193 6 | #q = 17 7 | #q = 134218289 8 | #q = 33554641 9 | #q = 13 10 | #q = 1073740609 11 | #q = 1073739937 12 | #q = 1073740609 13 | q = 1073741441 14 | n = 256 15 | #n = 512 16 | #r = 16 17 | #r = 32 18 | r = 64 19 | log_r = ceil(log(r, 2)) 20 | K = ceil(log(q, 2)) 21 | d = 2 22 | m = d * (K + 2) 23 | 24 | ZZx. = ZZ[] 25 | GFq = GF(q) 26 | R. = GF(q)[] 27 | Rq. = R.quotient_ring((xx^(n) + 1)) 28 | 29 | def my_ext_euclid(f, g): 30 | (r0, r1, v0, v1) = (g, f, R(0), R(1)) 31 | while r0.degree() != 0: 32 | (q, r) = r0.quo_rem(r1) 33 | (v0, v1) = (v1, v0 - q*v1) 34 | (r0, r1) = (r1, r0 - q*r1) 35 | print "q\n", q, "\nr\n", r, "\nv0\n", v0, "\nv1\n", v1, "\nr0\n", r0, "\nr1\n", r1, "\n" 36 | 37 | def cyclotomic_factorisation_tree(n): 38 | tree = [[GFq(1)]] 39 | i = 1 40 | for i in range(1, n): 41 | primitive_roots = [] 42 | for r in tree[i-1]: 43 | primitive_roots += (-r).square_root(extend=False, all=True) 44 | tree.append(primitive_roots) 45 | return tree 46 | 47 | def bezout_coefficients_tree(c_tree): 48 | b_tree = [[0]] 49 | for i in range(1, len(c_tree)): 50 | b_tree.append(2**i*[0]) 51 | for j in range(2**(i-1)): 52 | #inv1 = (c_tree[i][2*j] - c_tree[i][2*j+1]).inverse_of_unit() 53 | inv1 = GFq((ZZ(c_tree[i][2*j] - c_tree[i][2*j+1])).inverse_mod(q)) 54 | b_tree[i][2*j] = inv1 55 | b_tree[i][2*j+1] = -inv1 56 | return b_tree 57 | 58 | def flatten_tree(tree): 59 | l = [] 60 | for list in tree: 61 | l += list 62 | return l 63 | 64 | def ext_euclid(f, nb): 65 | (r0, r1, v0, v1) = (xx^n + 1, f, R(0), R(1)) 66 | for i in range(nb): 67 | (quo, rem) = r0.quo_rem(r1) 68 | (r0, r1) = (r1, rem) 69 | (v0, v1) = (v1, v0 - quo * v1) 70 | return (r0, r1, quo, v0, v1) 71 | 72 | def crt(f): 73 | crt_f = [R(f.list()).quo_rem(c_f)[1].list() for c_f in cyclo_factors] 74 | return [crt_f_i if crt_f_i != [] else [0] for crt_f_i in crt_f] 75 | 76 | def my_norm(v): 77 | coeffs = [ZZ(v_ij) for v_i in v.list() for v_ij in v_i] 78 | centered_v = vector(ZZ, [v_ij if v_ij < q/2 else (v_ij - q) for v_ij in coeffs]) 79 | return centered_v.norm() 80 | 81 | c_tree = cyclotomic_factorisation_tree(log_r + 1) 82 | b_tree = bezout_coefficients_tree(c_tree) 83 | 84 | print flatten_tree(c_tree) 85 | print flatten_tree(b_tree) 86 | 87 | cyclo_factors = [xx^(n/r) + c for c in c_tree[-1]] 88 | 89 | Rx. = RLF[] 90 | Rr. = Rx.quotient_ring((xxr^n + 1)) 91 | Cx. = CIF[] 92 | Rc. = Cx.quotient_ring((xxc^n + 1)) 93 | 94 | if(n == 8): 95 | cplx_prim_roots = [-e^(I*k*pi/n) for k in [3, 11, 15, 7, 13, 5, 1, 9]] 96 | cplx_roots = [[1], [I, -I], [-e^(I*k*pi/4) for k in [7, 3, 1, 5]], cplx_prim_roots] 97 | 98 | def stride(f): 99 | return Cx([f[i] for i in range(0, len(f.list()), 2)]), Cx([f[i] for i in range(1, len(f.list()), 2)]) 100 | 101 | def inv_cplx_crt(f): 102 | return Cx.lagrange_polynomial(zip(cplx_prim_roots, f)) 103 | 104 | def is_almost_real(f): 105 | return max([abs(f_i.imag()) for f_i in f]) 106 | 107 | def cplx_crt(f): 108 | return Rc([Cx(f.list())(w) for w in cplx_prim_roots]) 109 | 110 | def matrix_cplx_crt(A): 111 | return A.apply_map(cplx_crt) 112 | 113 | def extend_matrix(A): 114 | return block_matrix([[a.matrix().T for a in r] for r in A.rows()]) 115 | 116 | def poly_matrix(A): 117 | return matrix(Rr, [[A[i:i+n, j].list() for j in range(0, A.ncols(), n)] for i in range(0, A.nrows(), n)]) 118 | 119 | stored_A = matrix(Rq) 120 | 121 | 122 | T = matrix(Rc) 123 | 124 | p = matrix() 125 | 126 | h_m = Rq() 127 | 128 | if stored_A.dimensions() != (d, m-d): 129 | print "wrong dimensions for A" 130 | exit 131 | 132 | if T.dimensions() != (2*d, d*K): 133 | print "wrong dimensions for T" 134 | exit 135 | 136 | A = block_matrix([[1, stored_A]]) 137 | TI = block_matrix([[T], [1]]) 138 | 139 | g = matrix(Rq, [2**i for i in range(K)]) 140 | G = block_diagonal_matrix([g for i in range(d)]) 141 | 142 | def construct_A_m(A, h_m): 143 | zero_matrix = matrix(Rq, d, 2*d, 0) 144 | return A + block_matrix([[zero_matrix, h_m * G]]) 145 | 146 | -------------------------------------------------------------------------------- /Standard_BFRS/sage.sage.py: -------------------------------------------------------------------------------- 1 | 2 | # This file was *autogenerated* from the file sage.sage 3 | from sage.all_cmdline import * # import sage library 4 | 5 | _sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_7 = Integer(7); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4); _sage_const_256 = Integer(256); _sage_const_8 = Integer(8); _sage_const_13 = Integer(13); _sage_const_11 = Integer(11); _sage_const_1073741969 = Integer(1073741969); _sage_const_15 = Integer(15); _sage_const_9 = Integer(9)#q = 7681 6 | #q = 8388593 7 | #q = 8000033 8 | q = _sage_const_1073741969 9 | #q = 1032193 10 | #q = 17 11 | #q = 134218289 12 | #q = 33554641 13 | #q = 13 14 | n = _sage_const_256 15 | #n = 512 16 | r = _sage_const_8 17 | log_r = _sage_const_3 18 | K = ceil(log(q, _sage_const_2 )) 19 | d = _sage_const_2 20 | m = d * (K + _sage_const_2 ) 21 | 22 | ZZx = ZZ['xz']; (xz,) = ZZx._first_ngens(1) 23 | GFq = GF(q) 24 | R = GF(q)['xx']; (xx,) = R._first_ngens(1) 25 | Rq = R.quotient_ring((xx**(n) + _sage_const_1 ), names=('x',)); (x,) = Rq._first_ngens(1) 26 | 27 | def my_ext_euclid(f, g): 28 | (r0, r1, v0, v1) = (g, f, R(_sage_const_0 ), R(_sage_const_1 )) 29 | while r0.degree() != _sage_const_0 : 30 | (q, r) = r0.quo_rem(r1) 31 | (v0, v1) = (v1, v0 - q*v1) 32 | (r0, r1) = (r1, r0 - q*r1) 33 | print "q\n", q, "\nr\n", r, "\nv0\n", v0, "\nv1\n", v1, "\nr0\n", r0, "\nr1\n", r1, "\n" 34 | 35 | def cyclotomic_factorisation_tree(n): 36 | tree = [[GFq(_sage_const_1 )]] 37 | i = _sage_const_1 38 | for i in range(_sage_const_1 , n): 39 | primitive_roots = [] 40 | for r in tree[i-_sage_const_1 ]: 41 | primitive_roots += (-r).square_root(extend=False, all=True) 42 | tree.append(primitive_roots) 43 | return tree 44 | 45 | def bezout_coefficients_tree(c_tree): 46 | b_tree = [[_sage_const_0 ]] 47 | for i in range(_sage_const_1 , len(c_tree)): 48 | b_tree.append(_sage_const_2 **i*[_sage_const_0 ]) 49 | for j in range(_sage_const_2 **(i-_sage_const_1 )): 50 | #inv1 = (c_tree[i][2*j] - c_tree[i][2*j+1]).inverse_of_unit() 51 | inv1 = GFq((ZZ(c_tree[i][_sage_const_2 *j] - c_tree[i][_sage_const_2 *j+_sage_const_1 ])).inverse_mod(q)) 52 | b_tree[i][_sage_const_2 *j] = inv1 53 | b_tree[i][_sage_const_2 *j+_sage_const_1 ] = -inv1 54 | return b_tree 55 | 56 | def flatten_tree(tree): 57 | l = [] 58 | for list in tree: 59 | l += list 60 | return l 61 | 62 | def ext_euclid(f, nb): 63 | (r0, r1, v0, v1) = (xx**n + _sage_const_1 , f, R(_sage_const_0 ), R(_sage_const_1 )) 64 | for i in range(nb): 65 | (quo, rem) = r0.quo_rem(r1) 66 | (r0, r1) = (r1, rem) 67 | (v0, v1) = (v1, v0 - quo * v1) 68 | return (r0, r1, quo, v0, v1) 69 | 70 | def crt(f): 71 | crt_f = [R(f.list()).quo_rem(c_f)[_sage_const_1 ].list() for c_f in cyclo_factors] 72 | return [crt_f_i if crt_f_i != [] else [_sage_const_0 ] for crt_f_i in crt_f] 73 | 74 | def my_norm(v): 75 | coeffs = [ZZ(v_ij) for v_i in v.list() for v_ij in v_i] 76 | centered_v = vector(ZZ, [v_ij if v_ij < q/_sage_const_2 else (v_ij - q) for v_ij in coeffs]) 77 | return centered_v.norm() 78 | 79 | c_tree = cyclotomic_factorisation_tree(log_r + _sage_const_1 ) 80 | b_tree = bezout_coefficients_tree(c_tree) 81 | 82 | print flatten_tree(c_tree) 83 | print flatten_tree(b_tree) 84 | 85 | cyclo_factors = [xx**(n/r) + c for c in c_tree[-_sage_const_1 ]] 86 | 87 | Rx = RLF['xxr']; (xxr,) = Rx._first_ngens(1) 88 | Rr = Rx.quotient_ring((xxr**n + _sage_const_1 ), names=('xr',)); (xr,) = Rr._first_ngens(1) 89 | Cx = CIF['xxc']; (xxc,) = Cx._first_ngens(1) 90 | Rc = Cx.quotient_ring((xxc**n + _sage_const_1 ), names=('xc',)); (xc,) = Rc._first_ngens(1) 91 | 92 | if(n == _sage_const_8 ): 93 | cplx_prim_roots = [-e**(I*k*pi/n) for k in [_sage_const_3 , _sage_const_11 , _sage_const_15 , _sage_const_7 , _sage_const_13 , _sage_const_5 , _sage_const_1 , _sage_const_9 ]] 94 | cplx_roots = [[_sage_const_1 ], [I, -I], [-e**(I*k*pi/_sage_const_4 ) for k in [_sage_const_7 , _sage_const_3 , _sage_const_1 , _sage_const_5 ]], cplx_prim_roots] 95 | 96 | def stride(f): 97 | return Cx([f[i] for i in range(_sage_const_0 , len(f.list()), _sage_const_2 )]), Cx([f[i] for i in range(_sage_const_1 , len(f.list()), _sage_const_2 )]) 98 | 99 | def inv_cplx_crt(f): 100 | return Cx.lagrange_polynomial(zip(cplx_prim_roots, f)) 101 | 102 | def is_almost_real(f): 103 | return max([abs(f_i.imag()) for f_i in f]) 104 | 105 | def cplx_crt(f): 106 | return Rc([Cx(f.list())(w) for w in cplx_prim_roots]) 107 | 108 | def matrix_cplx_crt(A): 109 | return A.apply_map(cplx_crt) 110 | 111 | def extend_matrix(A): 112 | return block_matrix([[a.matrix().T for a in r] for r in A.rows()]) 113 | 114 | def poly_matrix(A): 115 | return matrix(Rr, [[A[i:i+n, j].list() for j in range(_sage_const_0 , A.ncols(), n)] for i in range(_sage_const_0 , A.nrows(), n)]) 116 | 117 | stored_A = matrix(Rq) 118 | 119 | 120 | T = matrix(Rc) 121 | 122 | p = matrix() 123 | 124 | h_m = Rq() 125 | 126 | if stored_A.dimensions() != (d, m-d): 127 | print "wrong dimensions for A" 128 | exit 129 | 130 | if T.dimensions() != (_sage_const_2 *d, d*K): 131 | print "wrong dimensions for T" 132 | exit 133 | 134 | A = block_matrix([[_sage_const_1 , stored_A]]) 135 | TI = block_matrix([[T], [_sage_const_1 ]]) 136 | 137 | g = matrix(Rq, [_sage_const_2 **i for i in range(K)]) 138 | G = block_diagonal_matrix([g for i in range(d)]) 139 | 140 | def construct_A_m(A, h_m): 141 | zero_matrix = matrix(Rq, d, _sage_const_2 *d, _sage_const_0 ) 142 | return A + block_matrix([[zero_matrix, h_m * G]]) 143 | 144 | 145 | -------------------------------------------------------------------------------- /Standard_BFRS/sampling.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void TrapGen(poly_matrix A, poly_matrix T); 6 | 7 | //============================================================================== 8 | // Samples from distribution D_{c,sigma}, ie 9 | // Samples an element in Z with probability proportionnal to e^{-(c-x)^2/2*(sigma^2)} 10 | //============================================================================== 11 | signed int SampleZ(RR_t c, RR_t sigma); 12 | 13 | void SampleR_centered(signed_poly f, RR_t sigma); 14 | 15 | void SampleR_matrix_centered(signed_poly_matrix A, int l1, int l2, RR_t sigma); 16 | 17 | void init_D_lattice_coeffs(void); 18 | 19 | void sample_D(signed_scalar *z, real *c, real sigma); 20 | 21 | void sample_G_perturb(real *p, real sigma); 22 | 23 | void scalar_sample_G(signed_scalar *t, scalar u); 24 | 25 | void ring_sample_G(signed_poly_matrix t, poly u); 26 | 27 | void transpose_scalar_matrix(scalar *A_T, scalar *A, int l0, int l1); 28 | 29 | void module_sample_G(signed_poly_matrix t, poly_matrix u); 30 | 31 | void sample_2z(signed_scalar *q, cplx_poly cplx_q, cplx_poly a, cplx_poly b, cplx_poly d, cplx *c, int deg); 32 | 33 | void sample_fz(signed_scalar *p, cplx_poly cplx_p, cplx_poly f, cplx *c, int deg); 34 | 35 | void sample_perturb(signed_poly_matrix p, cplx_poly_matrix T, cplx_poly_matrix sch_comp); 36 | 37 | void sample_pre(poly_matrix x, poly_matrix A_m, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, poly h_inv); 38 | 39 | extern real d_coeffs[PARAM_K]; 40 | extern real l_coeffs[PARAM_K]; 41 | extern real h_coeffs[PARAM_K]; 42 | -------------------------------------------------------------------------------- /Standard_BFRS/script.sage: -------------------------------------------------------------------------------- 1 | #q = 1073740609 2 | #q = 1073739937 3 | q = 1073740609 4 | n = 256 5 | r = 32 6 | #r = 16 7 | 8 | GFq = GF(q) 9 | root = GFq.zeta(2*r) 10 | 11 | def flatten_tree(tree): 12 | l = [] 13 | for list in tree: 14 | l += list 15 | return l 16 | 17 | def montgomery_list(l): 18 | return [l_i * 2^32 for l_i in l] 19 | 20 | def brv(a): 21 | return sum([a_i * 2^i for i, a_i in enumerate(reversed(a.bits()))]) 22 | 23 | def precompute_zetas(root): 24 | assert root.multiplicative_order() == 2*r 25 | 26 | zetas = [] 27 | 28 | k = r // 2 29 | while k > 0: 30 | zetas = [root^brv(k+i) for i in range(k)] + zetas 31 | root = zetas[0]^2 32 | k = k // 2 33 | 34 | zetas = [0] + zetas 35 | zetas_inv = [-zeta for zeta in reversed(zetas)] 36 | 37 | return zetas, zetas_inv 38 | 39 | def list_order(l): 40 | return [l_i.multiplicative_order() if l_i.is_unit() else 0 for l_i in l] 41 | 42 | mont = mod(2^32, q) 43 | mont2 = mod(2^64, q) 44 | q_inv = - mod(q, 2^32)^(-1) 45 | barrett_mult = floor(2^32 / q) 46 | barrett_shift = 32 47 | double_barrett_mult = floor(2^34 / q) 48 | double_barrett_shift = 34 49 | 50 | print "===== common.h =====\n" 51 | print "#define MONT", mont 52 | print "#define MONT2", mont2 53 | print "#define QINV", q_inv 54 | print "#define BARRETT_MULT", barrett_mult 55 | print "#define BARRETT_SHIFT", barrett_shift 56 | print "#define DOUBLE_BARRETT_MULT", double_barrett_mult 57 | print "#define DOUBLE_BARRETT_SHIFT", double_barrett_shift 58 | print "\n" 59 | 60 | zetas, zetas_inv = precompute_zetas(root) 61 | montgomery_zetas = montgomery_list(zetas) 62 | montgomery_zetas_inv = montgomery_list(zetas_inv) 63 | 64 | m_z_str = "{" + ", ".join(map(str, montgomery_zetas)) + "}" 65 | m_z_i_str = "{" + ", ".join(map(str, montgomery_zetas_inv)) + "}" 66 | 67 | print "===== arithmetic.c =====\n" 68 | print "static const scalar zetas[PARAM_R] = " + m_z_str + ";\n" 69 | print "static const scalar zetas_inv[PARAM_R] = " + m_z_i_str + ";\n" 70 | -------------------------------------------------------------------------------- /Standard_BFRS/signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "common.h" 9 | #include "arithmetic.h" 10 | #include "sampling.h" 11 | 12 | /* 13 | Generates a signing key (T, cplx_T, sch_comp) and an associated verification key A 14 | */ 15 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp) 16 | { 17 | //scalar A_hat_coeffs[PARAM_D * PARAM_D * PARAM_N], AprimeT_coeffs[PARAM_D * PARAM_D * PARAM_K * PARAM_N]; 18 | scalar *A_hat_coeffs = malloc(PARAM_D * PARAM_D * PARAM_N * sizeof(scalar)), *AprimeT_coeffs = malloc(PARAM_D * PARAM_D * PARAM_K * PARAM_N * sizeof(scalar)); 19 | poly_matrix A_hat = A_hat_coeffs, AprimeT = AprimeT_coeffs; 20 | 21 | // A_hat <- U(R_q^{d,d}) is considered to be in the CRT domain 22 | random_poly(A_hat, PARAM_N * PARAM_D * PARAM_D - 1); 23 | 24 | // T <- D_{R^{2d,dk},sigma} 25 | SampleR_matrix_centered((signed_poly_matrix) T, 2*PARAM_D, PARAM_D * PARAM_K, PARAM_SIGMA); 26 | 27 | // Compute the Schur complements 28 | construct_complex_private_key(cplx_T, sch_comp, T); 29 | 30 | // Add q to each component of T and put it in the CRT domain 31 | for(int i = 0 ; i < PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K ; ++i) 32 | { 33 | T[i] += PARAM_Q; 34 | } 35 | 36 | matrix_crt_representation(T, 2*PARAM_D, PARAM_D * PARAM_K, LOG_R); 37 | 38 | // AprimeT = A_hat * T2 + T1, where T1 and T2 are the upper and lower half of T 39 | poly_matrix T1 = T, T2 = poly_matrix_element(T, PARAM_D * PARAM_K, PARAM_D, 0); 40 | 41 | mul_crt_poly_matrix(AprimeT, A_hat, T2, PARAM_D, PARAM_D, PARAM_D * PARAM_K, LOG_R); 42 | add_to_poly_matrix(AprimeT, T1, PARAM_D, PARAM_D * PARAM_K); 43 | 44 | // A = (A_hat | -A'T) ( = (I | A_hat | -A'T) implicitly) 45 | for(int i = 0 ; i < PARAM_D ; ++i) 46 | { 47 | poly_matrix A_i0 = poly_matrix_element(A, PARAM_M - PARAM_D, i, 0); 48 | poly_matrix A_hat_i = poly_matrix_element(A_hat, PARAM_D, i, 0); 49 | 50 | memcpy(A_i0, A_hat_i, PARAM_D * PARAM_N * sizeof(scalar)); 51 | } 52 | for(int i = 0 ; i < PARAM_D ; ++i) 53 | { 54 | poly_matrix A_i1 = poly_matrix_element(A, PARAM_M - PARAM_D, i, PARAM_D); 55 | poly_matrix AprimeT_i = poly_matrix_element(AprimeT, PARAM_D * PARAM_K, i, 0); 56 | for(int j = 0 ; j < PARAM_D * PARAM_K * PARAM_N ; ++j) 57 | { 58 | A_i1[j] = 2*PARAM_Q - AprimeT_i[j]; 59 | } 60 | } 61 | 62 | // Reduce A's coefficients mod q 63 | freeze_poly(A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) - 1); 64 | 65 | free(A_hat); 66 | free(AprimeT); 67 | } 68 | 69 | /* 70 | Signs a message m using the signing key (T, cplx_T, sch_comp) and the verification key A 71 | */ 72 | void Sign(poly_matrix nu, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *m) 73 | { 74 | // Compute m's inverse and put it in the CRT domain 75 | scalar m_inv_coeffs[PARAM_N]; 76 | poly m_inv = m_inv_coeffs; 77 | 78 | invert_poly(m_inv, m, PARAM_N, 1); 79 | crt_representation(m_inv, LOG_R); 80 | 81 | // Use m to construct A_m 82 | construct_A_m(A, m); 83 | 84 | // Sample nu 85 | sample_pre(nu, A, T, cplx_T, sch_comp, m_inv); 86 | 87 | // Deconstruct A_m 88 | deconstruct_A_m(A, m); 89 | } 90 | 91 | /* 92 | Checks is the signature nu is valid for the message m, given the verification key A 93 | */ 94 | bool Verify(poly_matrix nu, poly_matrix A, scalar *m) 95 | { 96 | // Verify that A * nu = m mod q 97 | scalar prod_coeffs[PARAM_N * PARAM_D]; 98 | poly_matrix prod = prod_coeffs; 99 | 100 | construct_A_m(A, m); 101 | multiply_by_A(prod, A, (poly_matrix) nu); 102 | deconstruct_A_m(A, m); 103 | 104 | 105 | if(!is_zero_poly(prod, PARAM_N * PARAM_D - 1)) 106 | { 107 | 108 | printf("prod (CRT)\n"); 109 | print_poly_matrix(prod, PARAM_D, 1); 110 | 111 | return false; 112 | } 113 | 114 | 115 | // Verify that nu has a small norm 116 | matrix_coeffs_representation(nu, PARAM_M, 1, LOG_R); 117 | 118 | double_scalar norm_nu_squared = norm_squared((poly_matrix) nu, PARAM_M); 119 | double bound_squared = PARAM_T * PARAM_T * PARAM_ZETA * PARAM_ZETA * PARAM_N * PARAM_M; 120 | 121 | matrix_crt_representation(nu, PARAM_M, 1, LOG_R); 122 | 123 | if(norm_nu_squared >= bound_squared) 124 | { 125 | printf("norm^2 = %" PRIu64 " %c bound^2 = %f\n", norm_nu_squared, (norm_nu_squared < bound_squared)?'<':'>', bound_squared); 126 | 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | -------------------------------------------------------------------------------- /Standard_BFRS/signature.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "common.h" 4 | 5 | void KeyGen(poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp); 6 | 7 | void Sign(poly_matrix nu, poly_matrix A, poly_matrix T, cplx_poly_matrix cplx_T, cplx_poly_matrix sch_comp, scalar *m); 8 | 9 | bool Verify(poly_matrix nu, poly_matrix A, scalar *m); 10 | -------------------------------------------------------------------------------- /Standard_BFRS/signature_tests.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "random.h" 9 | #include "sampling.h" 10 | #include "signature.h" 11 | #include "arithmetic.h" 12 | 13 | void test_KeyGen(int n) 14 | { 15 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)); 16 | scalar *IA_coeffs = malloc(PARAM_N * PARAM_D * PARAM_M * sizeof(scalar)); 17 | scalar *TI_coeffs = malloc(PARAM_N * PARAM_M * PARAM_D * PARAM_K * sizeof(scalar)); 18 | scalar *AtimesTI_coeffs = malloc(PARAM_N * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 19 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)); 20 | cplx *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 21 | 22 | poly_matrix A = A_coeffs, IA = IA_coeffs, TI = TI_coeffs, T = TI_coeffs, I_dk = poly_matrix_element(TI, PARAM_D * PARAM_K, 2 * PARAM_D, 0), AtimesTI = AtimesTI_coeffs; 23 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 24 | 25 | // build I_dk in the CRT domain 26 | memset(I_dk, 0, PARAM_N * PARAM_D * PARAM_K * PARAM_D * PARAM_K * sizeof(scalar)); 27 | for(int i = 0 ; i < PARAM_D * PARAM_K ; ++i) 28 | { 29 | poly I_dk_ii = poly_matrix_element(I_dk, PARAM_D * PARAM_K, i, i); 30 | 31 | I_dk_ii[0] = 1; 32 | 33 | crt_representation(I_dk_ii, LOG_R); 34 | } 35 | 36 | // build I_d in the CRT domain 37 | for(int i = 0 ; i < PARAM_D ; ++i) 38 | { 39 | poly_matrix IA_i = poly_matrix_element(IA, PARAM_M, i, 0); 40 | poly_matrix IA_ii = poly_matrix_element(IA, PARAM_M, i, i); 41 | 42 | memset(IA_i, 0, PARAM_N * PARAM_D * sizeof(scalar)); 43 | IA_ii[0] = 1; 44 | 45 | crt_representation(IA_ii, LOG_R); 46 | } 47 | 48 | printf("Generating and verifying keys\n"); 49 | 50 | for(int i = 0 ; i < n ; ++i) 51 | { 52 | // Generate the keys 53 | KeyGen(A, T, cplx_T, sch_comp); 54 | 55 | // Test the keys 56 | for(int j = 0 ; j < PARAM_D ; ++j) 57 | { 58 | poly_matrix IA_jd = poly_matrix_element(IA, PARAM_M, j, PARAM_D); 59 | poly_matrix A_j = poly_matrix_element(A, PARAM_M - PARAM_D, j, 0); 60 | 61 | memcpy(IA_jd, A_j, PARAM_N * (PARAM_M - PARAM_D) * sizeof(scalar)); 62 | } 63 | 64 | mul_crt_poly_matrix(AtimesTI, IA, TI, PARAM_D, PARAM_M, PARAM_D * PARAM_K, LOG_R); 65 | 66 | if(!is_zero_poly(AtimesTI, PARAM_N * PARAM_D * PARAM_D * PARAM_K - 1)) 67 | { 68 | printf("AtimesTI\n"); 69 | print_poly_matrix(AtimesTI, PARAM_D * PARAM_K, PARAM_D); 70 | } 71 | else 72 | { 73 | printf("ok @ %d\n", i); 74 | } 75 | } 76 | 77 | free(A); 78 | free(IA); 79 | free(TI); 80 | free(AtimesTI); 81 | free(sch_comp); 82 | free(cplx_T); 83 | } 84 | 85 | int time_KeyGen1(int n) 86 | { 87 | clock_t t0, t1; 88 | 89 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 90 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 91 | poly_matrix A = A_coeffs, T = T_coeffs; 92 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 93 | 94 | // Generate the keys 95 | printf("Generating keys (A, T, cplx_T, sch_comp)... "); 96 | fflush(stdout); 97 | 98 | t0 = clock(); 99 | for(int i = 0 ; i < n ; ++i) 100 | { 101 | KeyGen(A, T, cplx_T, sch_comp); 102 | } 103 | t1 = clock() - t0; 104 | 105 | printf("Done : %ld\n\n", t1); 106 | 107 | free(A); 108 | free(T); 109 | free(sch_comp); 110 | free(cplx_T); 111 | 112 | return t1; 113 | } 114 | 115 | int time_KeyGen2(int n) 116 | { 117 | clock_t t0, t1; 118 | 119 | scalar A_coeffs[PARAM_N * PARAM_D * (PARAM_M - PARAM_D)], T_coeffs[PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K]; 120 | poly_matrix A = A_coeffs, T = T_coeffs; 121 | 122 | printf("Generating keys (A,T)...\n"); 123 | 124 | t0 = clock(); 125 | for(int i = 0 ; i < n ; ++i) 126 | { 127 | TrapGen(A, T); 128 | } 129 | t1 = clock() - t0; 130 | 131 | printf("Done : %ld\n\n", t1); 132 | 133 | free(A); 134 | free(T); 135 | 136 | return t1; 137 | } 138 | 139 | void test_construct_and_deconstruct_A_m(int n) 140 | { 141 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)); 142 | scalar *A_copy = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)); 143 | scalar m_coeffs[SMALL_DEGREE]; 144 | 145 | poly A = A_coeffs, m = m_coeffs; 146 | 147 | // Generate some "public key"-like A and message-like m 148 | printf("Generating A and m...\n"); 149 | 150 | random_poly(A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) - 1); 151 | random_poly(m, SMALL_DEGREE - 1); 152 | memcpy(A_copy, A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)); 153 | 154 | printf("Done\n"); 155 | 156 | // Construct and deconstruct A_m, and check that it hasn't changed 157 | for(int i = 0 ; i < n ; ++i) 158 | { 159 | printf("%d\n", i); 160 | construct_A_m(A, m); 161 | deconstruct_A_m(A, m); 162 | 163 | for(int j = 0 ; j < PARAM_D ; ++j) 164 | { 165 | for(int k = 0 ; k < PARAM_M - PARAM_D ; ++k) 166 | { 167 | for(int l = 0 ; l < PARAM_N ; ++l) 168 | { 169 | poly A_jk = poly_matrix_element(A, PARAM_M - PARAM_D, j, k); 170 | poly A_copy_jk = poly_matrix_element(A_copy, PARAM_M - PARAM_D, j, k); 171 | 172 | if(A_copy_jk[l] != A_jk[l]) 173 | { 174 | printf("(%d, %d, %d) : %" PRIu32 " != %" PRIu32 "\n", j, k, l, A_copy_jk[l], A_jk[l]); 175 | } 176 | } 177 | } 178 | } 179 | } 180 | 181 | free(A); 182 | free(A_copy); 183 | } 184 | 185 | void test_Sign_and_Verify(int n) 186 | { 187 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 188 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 189 | poly_matrix A = A_coeffs, T = T_coeffs; 190 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 191 | 192 | 193 | scalar *A_copy = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_copy = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 194 | cplx *sch_comp_copy = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_copy = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 195 | 196 | // Generate the keys 197 | printf("Generating keys (A, T, cplx_T, sch_comp)...\n"); 198 | 199 | KeyGen(A, T, cplx_T, sch_comp); 200 | 201 | printf("Done\n"); 202 | 203 | 204 | // Copy them to later check if they have changed 205 | memcpy(A_copy, A, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)); 206 | memcpy(T_copy, T, PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 207 | memcpy(cplx_T_copy, cplx_T, PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 208 | memcpy(sch_comp_copy, sch_comp, PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)); 209 | 210 | 211 | // Generate a message (a polynomial of degree < n/r) 212 | printf("Generating a message m...\n"); 213 | 214 | scalar m_coeffs[PARAM_N] = {0}; 215 | poly m = m_coeffs; 216 | 217 | random_poly(m, SMALL_DEGREE - 1); 218 | 219 | printf("Done\n"); 220 | 221 | // Sample a signature nu 222 | scalar nu_coeffs[PARAM_N * PARAM_M]; 223 | poly_matrix nu = nu_coeffs; 224 | 225 | printf("Signing...\n"); 226 | 227 | for(int i = 0 ; i < n ; ++i) 228 | { 229 | 230 | Sign(nu, A, T, cplx_T, sch_comp, m); 231 | 232 | for(int j = 0 ; j < PARAM_D ; ++j) 233 | { 234 | for(int k = 0 ; k < PARAM_M - PARAM_D ; ++k) 235 | { 236 | for(int l = 0 ; l < PARAM_N ; ++l) 237 | { 238 | poly A_jk = poly_matrix_element(A, PARAM_M - PARAM_D, j, k); 239 | poly A_copy_jk = poly_matrix_element(A_copy, PARAM_M - PARAM_D, j, k); 240 | 241 | if(A_copy_jk[l] != A_jk[l]) 242 | { 243 | printf("(%d, %d, %d) : %" PRIu32 " != %" PRIu32 "\n", j, k, l, A_copy_jk[l], A_jk[l]); 244 | } 245 | } 246 | } 247 | } 248 | 249 | if(Verify(nu, A, m) == false) 250 | { 251 | printf("verification failed @ %d\n", i); 252 | } 253 | else 254 | { 255 | printf("verification successful @ %d\n", i); 256 | } 257 | 258 | if(memcmp(A, A_copy, PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)) != 0) 259 | { 260 | printf("A changed after verifying\n"); 261 | } 262 | 263 | } 264 | 265 | free(A); 266 | free(T); 267 | free(sch_comp); 268 | free(cplx_T); 269 | 270 | free(A_copy); 271 | free(T_copy); 272 | free(sch_comp_copy); 273 | free(cplx_T_copy); 274 | } 275 | 276 | int time_Sign1(int n) 277 | { 278 | clock_t t0, t1; 279 | 280 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 281 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 282 | poly_matrix A = A_coeffs, T = T_coeffs; 283 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 284 | 285 | // Generate the keys 286 | printf("Generating keys (A, T, cplx_T, sch_comp)... "); 287 | fflush(stdout); 288 | 289 | KeyGen(A, T, cplx_T, sch_comp); 290 | 291 | printf("Done.\n"); 292 | 293 | // Generate a message (a polynomial of degree < n/r) 294 | printf("Generating a message m... "); 295 | fflush(stdout); 296 | 297 | scalar m_coeffs[PARAM_N] = {0}; 298 | poly m = m_coeffs; 299 | 300 | random_poly(m, SMALL_DEGREE - 1); 301 | 302 | printf("Done.\n"); 303 | 304 | // Sample a signature nu 305 | scalar nu_coeffs[PARAM_N * PARAM_M]; 306 | poly_matrix nu = nu_coeffs; 307 | 308 | printf("Signing the same message multiple times... "); 309 | fflush(stdout); 310 | 311 | t0 = clock(); 312 | for(int i = 0 ; i < n ; ++i) 313 | { 314 | Sign(nu, A, T, cplx_T, sch_comp, m); 315 | } 316 | t1 = clock() - t0; 317 | 318 | printf("Done : %ld\n\n", t1); 319 | 320 | free(A); 321 | free(T); 322 | free(sch_comp); 323 | free(cplx_T); 324 | 325 | return t1; 326 | } 327 | 328 | int time_Sign2(int n) 329 | { 330 | clock_t t0, t1; 331 | 332 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 333 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 334 | poly_matrix A = A_coeffs, T = T_coeffs; 335 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 336 | 337 | // Generate the keys 338 | printf("Generating keys (A, T, cplx_T, sch_comp)... "); 339 | fflush(stdout); 340 | 341 | KeyGen(A, T, cplx_T, sch_comp); 342 | 343 | printf("Done.\n"); 344 | 345 | // Generate a message (a polynomial of degree < n/r) 346 | printf("Generating a message m... "); 347 | fflush(stdout); 348 | 349 | scalar m_coeffs[PARAM_N] = {0}; 350 | poly m = m_coeffs; 351 | 352 | random_poly(m, SMALL_DEGREE - 1); 353 | 354 | printf("Done.\n"); 355 | 356 | // Sample a signature nu 357 | scalar nu_coeffs[PARAM_N * PARAM_M]; 358 | poly_matrix nu = nu_coeffs; 359 | 360 | printf("Signing different messages... "); 361 | fflush(stdout); 362 | 363 | t1 = 0; 364 | for(int i = 0 ; i < n ; ++i) 365 | { 366 | // Generate a message (a polynomial of degree < n/r) 367 | random_poly(m, SMALL_DEGREE - 1); 368 | 369 | t0 = clock(); 370 | 371 | // Sign it 372 | Sign(nu, A, T, cplx_T, sch_comp, m); 373 | 374 | t1 += clock() - t0; 375 | } 376 | 377 | printf("Done : %ld\n\n", t1); 378 | 379 | free(A); 380 | free(T); 381 | free(sch_comp); 382 | free(cplx_T); 383 | 384 | return t1; 385 | } 386 | 387 | int time_Verify1(int n) 388 | { 389 | clock_t t0, t1; 390 | 391 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 392 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 393 | poly_matrix A = A_coeffs, T = T_coeffs; 394 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 395 | 396 | // Generate the keys 397 | printf("Generating keys (A, T, cplx_T, sch_comp)... "); 398 | fflush(stdout); 399 | 400 | KeyGen(A, T, cplx_T, sch_comp); 401 | 402 | printf("Done.\n"); 403 | 404 | // Generate a message (a polynomial of degree < n/r) 405 | printf("Generating a message m... "); 406 | fflush(stdout); 407 | 408 | scalar m_coeffs[PARAM_N] = {0}; 409 | poly m = m_coeffs; 410 | 411 | random_poly(m, SMALL_DEGREE - 1); 412 | 413 | printf("Done.\n"); 414 | 415 | // Sample a signature nu 416 | scalar nu_coeffs[PARAM_N * PARAM_M]; 417 | poly_matrix nu = nu_coeffs; 418 | 419 | printf("Signing the message... "); 420 | fflush(stdout); 421 | 422 | Sign(nu, A, T, cplx_T, sch_comp, m); 423 | 424 | printf("Done.\n"); 425 | 426 | // Verify the signature 427 | printf("Verifying the same signature multiple times... "); 428 | fflush(stdout); 429 | 430 | t0 = clock(); 431 | for(int i = 0 ; i < n ; ++i) 432 | { 433 | Verify(nu, A, m); 434 | } 435 | t1 = clock() - t0; 436 | 437 | printf("Done : %ld\n\n", t1); 438 | 439 | free(A); 440 | free(T); 441 | free(sch_comp); 442 | free(cplx_T); 443 | 444 | return t1; 445 | } 446 | 447 | int time_Verify2(int n) 448 | { 449 | clock_t t0, t1; 450 | 451 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 452 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 453 | poly_matrix A = A_coeffs, T = T_coeffs; 454 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 455 | 456 | // Generate the keys 457 | printf("Generating keys (A, T, cplx_T, sch_comp)... "); 458 | fflush(stdout); 459 | 460 | KeyGen(A, T, cplx_T, sch_comp); 461 | 462 | printf("Done.\n"); 463 | 464 | printf("Verifying different signatures for different messages... "); 465 | fflush(stdout); 466 | 467 | t1 = 0; 468 | for(int i = 0 ; i < n ; ++i) 469 | { 470 | // Generate a message 471 | scalar m_coeffs[PARAM_N] = {0}; 472 | poly m = m_coeffs; 473 | 474 | random_poly(m, SMALL_DEGREE - 1); 475 | 476 | // Sign it 477 | scalar nu_coeffs[PARAM_N * PARAM_M]; 478 | poly_matrix nu = nu_coeffs; 479 | 480 | Sign(nu, A, T, cplx_T, sch_comp, m); 481 | 482 | // Verify the signature 483 | t0 = clock(); 484 | Verify(nu, A, m); 485 | t1 += clock() - t0; 486 | } 487 | 488 | printf("Done : %ld\n\n", t1); 489 | 490 | free(A); 491 | free(T); 492 | free(sch_comp); 493 | free(cplx_T); 494 | 495 | return t1; 496 | } 497 | 498 | 499 | int main(int argc, char **argv) 500 | { 501 | if(argc < 2) 502 | { 503 | fprintf(stderr, "Usage : %s n\n", argv[0]); 504 | exit(EXIT_FAILURE); 505 | } 506 | 507 | int n = atoi(argv[1]); 508 | 509 | printf("=========== Parameters ===========\n"); 510 | printf("\tn = %d\n", PARAM_N); 511 | printf("\tr = %d\n", PARAM_R); 512 | printf("\tq = %d\n", PARAM_Q); 513 | printf("\tb = %d\n", PARAM_B); 514 | printf("\tk = %d\n", PARAM_K); 515 | printf("\td = %d\n", PARAM_D); 516 | printf("\tsigma = %f\n", PARAM_SIGMA); 517 | printf("\tzeta = %f\n", PARAM_ZETA); 518 | printf("\talpha = %f\n", PARAM_ALPHA); 519 | printf("==================================\n\n"); 520 | 521 | init_crt_trees(); 522 | init_D_lattice_coeffs(); 523 | init_cplx_roots_of_unity(); 524 | 525 | //random_bytes_init(); 526 | 527 | test_KeyGen(n); 528 | //test_Sign_and_Verify(n); 529 | //test_construct_and_deconstruct_A_m(n); 530 | 531 | //time_KeyGen1(n); 532 | //time_Sign1(n); 533 | //time_Sign2(n); 534 | //time_Verify1(n); 535 | //time_Verify2(n); 536 | 537 | return 0; 538 | } 539 | -------------------------------------------------------------------------------- /Standard_BFRS/timing.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "random.h" 7 | #include "sampling.h" 8 | #include "signature.h" 9 | #include "arithmetic.h" 10 | 11 | #include "cpucycles.h" 12 | 13 | #define MESSAGE_BYTES 512 // keep it divisible by 16 14 | #define NTESTS 100 15 | #define CPU_CYCLES (1.9 * 1000000000.0) 16 | 17 | unsigned long long timing_overhead; 18 | unsigned long long timing_sampleZ_G = 0; 19 | unsigned long long timing_sampleZ_P = 0; 20 | unsigned long long timing_sampleG = 0; 21 | unsigned long long timing_samplePerturb = 0; 22 | unsigned long long timing_sampleArith = 0; 23 | 24 | unsigned long long timing_sign = 0; 25 | 26 | unsigned long long timing_sampleZ_KG = 0; 27 | unsigned long long timing_precomp_KG = 0; 28 | unsigned long long timing_arith_KG = 0; 29 | unsigned long long timing_keygen = 0; 30 | 31 | unsigned long long timing_verify = 0; 32 | 33 | void time_keygen(void) 34 | { 35 | timing_overhead = cpucycles_overhead(); 36 | unsigned long long begin_timing = 0; 37 | unsigned long long end_timing = 0; 38 | 39 | 40 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 41 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 42 | poly_matrix A = A_coeffs, T = T_coeffs; 43 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 44 | 45 | 46 | 47 | for(unsigned i = 0; i < NTESTS; ++i) { 48 | 49 | begin_timing = cpucycles_start(); 50 | 51 | // Generate Keys 52 | KeyGen(A, T, cplx_T, sch_comp); 53 | 54 | end_timing = cpucycles_stop(); 55 | timing_keygen += (end_timing - begin_timing); 56 | } 57 | 58 | timing_sampleZ_KG = timing_sampleZ_KG/NTESTS - timing_overhead; 59 | timing_precomp_KG = timing_precomp_KG/NTESTS - timing_overhead; 60 | timing_arith_KG = timing_arith_KG/NTESTS - timing_overhead; 61 | double timing_total = timing_sampleZ_KG + timing_precomp_KG + timing_arith_KG; 62 | 63 | 64 | printf("----------- KeyGen -----------\n"); 65 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_sampleZ_KG, (timing_sampleZ_KG*1000)/CPU_CYCLES, (timing_sampleZ_KG/timing_total)*100.0); 66 | printf("Precomp : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_precomp_KG, (timing_precomp_KG*1000)/CPU_CYCLES, (timing_precomp_KG/timing_total)*100.0); 67 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of KeyGen)\n", timing_arith_KG, (timing_arith_KG*1000)/CPU_CYCLES, (timing_arith_KG/timing_total)*100.0); 68 | printf("-----\n"); 69 | 70 | timing_keygen = timing_keygen/NTESTS - timing_overhead; 71 | printf("Total: %lld cycles (%.2lf ms)\n", timing_keygen, (timing_keygen*1000)/CPU_CYCLES); 72 | 73 | printf("\n\n"); 74 | 75 | free(A); 76 | free(T); 77 | free(sch_comp); 78 | free(cplx_T); 79 | } 80 | 81 | void time_sign(void) 82 | { 83 | timing_overhead = cpucycles_overhead(); 84 | unsigned long long begin_timing = 0; 85 | unsigned long long end_timing = 0; 86 | 87 | 88 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 89 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 90 | poly_matrix A = A_coeffs, T = T_coeffs; 91 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 92 | 93 | // Generate Keys 94 | KeyGen(A, T, cplx_T, sch_comp); 95 | 96 | 97 | 98 | for(unsigned i = 0; i < NTESTS; ++i) { 99 | // Generate a message 100 | scalar m_coeffs[PARAM_N] = {0}; 101 | poly m = m_coeffs; 102 | 103 | random_poly(m, SMALL_DEGREE - 1); 104 | 105 | // Compute a signature (nu) 106 | scalar nu_coeffs[PARAM_N * PARAM_M]; 107 | poly_matrix nu = nu_coeffs; 108 | 109 | begin_timing = cpucycles_start(); 110 | Sign(nu, A, T, cplx_T, sch_comp, m); 111 | end_timing = cpucycles_stop(); 112 | timing_sign += (end_timing - begin_timing); 113 | } 114 | 115 | timing_sampleZ_G = timing_sampleZ_G/NTESTS - timing_overhead; 116 | timing_sampleZ_P = timing_sampleZ_P/NTESTS - timing_overhead; 117 | unsigned long long timing_sampleZ = timing_sampleZ_G + timing_sampleZ_P; 118 | 119 | timing_sampleG = timing_sampleG/NTESTS - timing_overhead; 120 | timing_samplePerturb = timing_samplePerturb/NTESTS - timing_overhead; 121 | timing_sampleArith = timing_sampleArith/NTESTS - timing_overhead; 122 | double timing_samplePre = timing_sampleG + timing_samplePerturb + timing_sampleArith; 123 | 124 | 125 | printf("----------- SampleZ -----------\n"); 126 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleG)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, ((double) timing_sampleZ_G/timing_sampleG)*100.0); 127 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SampleP)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, ((double) timing_sampleZ_P/timing_samplePerturb)*100.0); 128 | printf("SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ, (timing_sampleZ*1000)/CPU_CYCLES, ((double) timing_sampleZ/timing_samplePre)*100.0); 129 | 130 | 131 | printf("\n----------- SamplePre -----------\n"); 132 | printf("SampleG : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG, (timing_sampleG*1000)/CPU_CYCLES, (timing_sampleG/timing_samplePre)*100.0); 133 | printf("G-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_G, (timing_sampleZ_G*1000)/CPU_CYCLES, (timing_sampleZ_G/timing_samplePre)*100.0); 134 | printf("G-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleG - timing_sampleZ_G, ((timing_sampleG - timing_sampleZ_G)*1000)/CPU_CYCLES, ((timing_sampleG - timing_sampleZ_G)/timing_samplePre)*100.0); 135 | printf("-----\n"); 136 | 137 | printf("SamplePerturb: %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb, (timing_samplePerturb*1000)/CPU_CYCLES, (timing_samplePerturb/timing_samplePre)*100.0); 138 | printf("P-SampleZ : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleZ_P, (timing_sampleZ_P*1000)/CPU_CYCLES, (timing_sampleZ_P/timing_samplePre)*100.0); 139 | printf("P-Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_samplePerturb - timing_sampleZ_P, ((timing_samplePerturb - timing_sampleZ_P)*1000)/CPU_CYCLES, ((timing_samplePerturb - timing_sampleZ_P)/timing_samplePre)*100.0); 140 | printf("-----\n"); 141 | 142 | printf("Arith : %lld cycles (%.2lf ms) (%.2lf %% of SamplePre)\n", timing_sampleArith, (timing_sampleArith*1000)/CPU_CYCLES, (timing_sampleArith/timing_samplePre)*100.0); 143 | 144 | printf("\n----------- Signature -----------\n"); 145 | timing_sign = timing_sign/NTESTS - timing_overhead; 146 | printf("Signature: %lld cycles (%.2lf ms)\n", timing_sign, (timing_sign*1000)/CPU_CYCLES); 147 | 148 | printf("\n\n"); 149 | 150 | free(A); 151 | free(T); 152 | free(sch_comp); 153 | free(cplx_T); 154 | } 155 | 156 | void time_verify(void) 157 | { 158 | timing_overhead = cpucycles_overhead(); 159 | unsigned long long begin_timing = 0; 160 | unsigned long long end_timing = 0; 161 | 162 | 163 | scalar *A_coeffs = malloc(PARAM_N * PARAM_D * (PARAM_M - PARAM_D) * sizeof(scalar)), *T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(scalar)); 164 | cplx *sch_comp_coeffs = malloc(PARAM_N * PARAM_D * (2 * PARAM_D + 1) * sizeof(cplx)), *cplx_T_coeffs = malloc(PARAM_N * 2 * PARAM_D * PARAM_D * PARAM_K * sizeof(cplx)); 165 | poly_matrix A = A_coeffs, T = T_coeffs; 166 | cplx_poly_matrix sch_comp = sch_comp_coeffs, cplx_T = cplx_T_coeffs; 167 | 168 | 169 | // Generate Keys 170 | KeyGen(A, T, cplx_T, sch_comp); 171 | 172 | // Generate a message 173 | scalar m_coeffs[PARAM_N] = {0}; 174 | poly m = m_coeffs; 175 | 176 | random_poly(m, SMALL_DEGREE - 1); 177 | 178 | // Compute a signature (nu) 179 | scalar nu_coeffs[PARAM_N * PARAM_M]; 180 | poly_matrix nu = nu_coeffs; 181 | 182 | Sign(nu, A, T, cplx_T, sch_comp, m); 183 | 184 | for(unsigned i = 0; i < NTESTS; ++i) { 185 | 186 | begin_timing = cpucycles_start(); 187 | 188 | Verify(nu, A, m); 189 | 190 | end_timing = cpucycles_stop(); 191 | timing_verify += (end_timing - begin_timing); 192 | } 193 | 194 | 195 | printf("----------- Verify -----------\n"); 196 | 197 | timing_verify = timing_verify/NTESTS - timing_overhead; 198 | printf("Total: %lld cycles (%.2lf ms)\n\n\n", timing_verify, (timing_verify*1000)/CPU_CYCLES); 199 | 200 | printf("\n\n"); 201 | 202 | free(A); 203 | free(T); 204 | free(sch_comp); 205 | free(cplx_T); 206 | } 207 | 208 | int main(void) { 209 | 210 | init_crt_trees(); 211 | init_D_lattice_coeffs(); 212 | init_cplx_roots_of_unity(); 213 | 214 | time_keygen(); 215 | 216 | time_sign(); 217 | 218 | time_verify(); 219 | 220 | 221 | return 0; 222 | } 223 | 224 | --------------------------------------------------------------------------------