github.com/onflow/flow-go/crypto@v0.24.8/dkg_core.c (about) 1 // +build relic 2 3 #include "dkg_include.h" 4 5 6 #define N_max 250 7 #define N_bits_max 8 // log(250) 8 #define T_max ((N_max-1)/2) 9 10 // computes P(x) = a_0 + a_1*x + .. + a_n x^n (mod r) 11 // r being the order of G1 12 // writes P(x) in out and P(x).g2 in y if y is non NULL 13 // x being a small integer 14 void Zr_polynomialImage_export(byte* out, ep2_t y, const bn_st* a, const int a_size, const byte x){ 15 bn_t image; 16 bn_new(image); 17 Zr_polynomialImage(image, y, a, a_size, x); 18 // exports the result 19 const int out_size = Fr_BYTES; 20 bn_write_bin(out, out_size, image); 21 bn_free(image); 22 } 23 24 // computes P(x) = a_0 + a_1*x + .. + a_n x^n (mod r) 25 // r being the order of G1 26 // writes P(x) in out and P(x).g2 in y if y is non NULL 27 // x being a small integer 28 void Zr_polynomialImage(bn_t image, ep2_t y, const bn_st *a, const int a_size, const byte x){ 29 bn_t r; 30 bn_new(r); 31 g2_get_ord(r); 32 33 // temp variables 34 bn_t acc; 35 bn_new(acc); 36 bn_new_size(acc, BITS_TO_DIGITS(Fr_BITS+8+1)); 37 bn_set_dig(acc, 0); 38 39 for (int i=a_size-1; i >= 0; i--) { 40 bn_mul_dig(acc, acc, x); 41 // Use basic reduction as it's an 9-bits reduction 42 // in the worst case (|acc|<|r|+9 ) 43 bn_mod_basic(acc, acc, r); 44 bn_add(acc, acc, &a[i]); 45 } 46 // export the result 47 bn_mod_basic(image, acc, r); 48 49 // compute y = P(x).g2 50 if (y) g2_mul_gen(y, acc); 51 52 bn_free(acc) 53 bn_free(r); 54 } 55 56 // computes Q(x) = A_0 + A_1*x + ... + A_n*x^n in G2 57 // and stores the point in y 58 // r is the order of G2 59 static void G2_polynomialImage(ep2_t y, const ep2_st* A, const int len_A, 60 const byte x, const bn_t r){ 61 62 bn_t bn_x; 63 bn_new(bn_x); 64 ep2_set_infty(y); 65 bn_set_dig(bn_x, x); 66 for (int i = len_A-1; i >= 0 ; i--) { 67 ep2_mul_lwnaf(y, y, bn_x); 68 ep2_add_projc(y, y, (ep2_st*)&A[i]); 69 } 70 71 ep2_norm(y, y); // not necessary but left here to optimize the 72 // multiple pairing computations with the same public key 73 bn_free(bn_x); 74 } 75 76 // compute the participants public keys from the verification vector 77 // y[i] = Q(i+1) for all participants i, with: 78 // Q(x) = A_0 + A_1*x + ... + A_n*x^n in G2 79 void G2_polynomialImages(ep2_st *y, const int len_y, const ep2_st* A, const int len_A) { 80 // order r 81 bn_t r; 82 bn_new(r); 83 g2_get_ord(r); 84 for (byte i=0; i<len_y; i++) { 85 //y[i] = Q(i+1) 86 G2_polynomialImage(y+i , A, len_A, i+1, r); 87 } 88 bn_free(r); 89 } 90 91 // export an array of ep2_st into an array of bytes 92 // the length matching is supposed to be checked 93 void ep2_vector_write_bin(byte* out, const ep2_st* A, const int len) { 94 const int size = (G2_BYTES/(G2_SERIALIZATION+1)); 95 byte* p = out; 96 for (int i=0; i<len; i++){ 97 ep2_write_bin_compact(p, &A[i], size); 98 p += size; 99 } 100 } 101 102 // The function imports an array of ep2_st from an array of bytes 103 // the length matching is supposed to be already done. 104 // 105 // It returns RLC_OK if reading all the vector succeeded and RLC_ERR 106 // otherwise. 107 int ep2_vector_read_bin(ep2_st* A, const byte* src, const int len){ 108 const int size = (G2_BYTES/(G2_SERIALIZATION+1)); 109 byte* p = (byte*) src; 110 for (int i=0; i<len; i++){ 111 int read_ret = ep2_read_bin_compact(&A[i], p, size); // returns RLC_OK or RLC_ERR 112 if (read_ret != RLC_OK) 113 return read_ret; 114 p += size; 115 } 116 return RLC_OK; 117 } 118 119 // returns 1 if g2^x = y, where g2 is the generator of G2 120 // returns 0 otherwise 121 int verifyshare(const bn_t x, const ep2_t y) { 122 ep2_t res; 123 ep2_new(res); 124 g2_mul_gen(res, (bn_st*)x); 125 return (ep2_cmp(res, (ep2_st*)y) == RLC_EQ); 126 } 127