/ src / tests / mpmult.c
mpmult.c
  1  #include <stdio.h>
  2  #include "../oprf.h"
  3  #include "../mpmult.h"
  4  #include "../dkg.h"
  5  #include "../utils.h"
  6  #include <assert.h>
  7  #include <string.h>
  8  #include <stdint.h>
  9  
 10  int test_mpmul(void) {
 11    const uint8_t threshold = 2, dealers = (threshold*2) + 1U, peers = dealers * 2;
 12  
 13    // share value k0
 14    uint8_t k0[crypto_core_ristretto255_SCALARBYTES];
 15    crypto_core_ristretto255_scalar_random(k0);
 16    //debian_rng(k0);
 17    dump(k0, sizeof k0, "k0");
 18    // split k into shares
 19    uint8_t shares0[peers][TOPRF_Share_BYTES];
 20    toprf_create_shares(k0, peers, threshold, shares0);
 21    if(liboprf_debug) {
 22      for(unsigned j=0;j<peers;j++)
 23        dump(shares0[j], TOPRF_Share_BYTES, "shares0[%d]", j);
 24      printf("\n");
 25    }
 26  
 27    // share value k1
 28    uint8_t k1[crypto_core_ristretto255_SCALARBYTES];
 29    crypto_core_ristretto255_scalar_random(k1);
 30    //debian_rng(k1);
 31    dump(k1, sizeof k1, "k1");
 32    // split k into shares
 33    uint8_t shares1[peers][TOPRF_Share_BYTES];
 34    toprf_create_shares(k1, peers, threshold, shares1);
 35    if(liboprf_debug) {
 36      for(unsigned j=0;j<peers;j++)
 37        dump(shares1[j], TOPRF_Share_BYTES, "shares1[%d]", j);
 38      printf("\n");
 39    }
 40  
 41    // each shareholder multiplies their k0,k1 shares
 42    // and creates a sharing of this product
 43    uint8_t mulshares[dealers][peers][TOPRF_Share_BYTES];
 44    for(uint8_t i=0;i<dealers;i++) {
 45      if( toprf_mpc_mul_start(shares0[i], shares1[i], peers, threshold, mulshares[i])) return 1;
 46    }
 47  
 48    uint8_t indexes[dealers];
 49    for(uint8_t i=0; i<dealers; i++) indexes[i]=i+1;
 50  
 51    uint8_t sharesP[peers][TOPRF_Share_BYTES];
 52    //memset(sharesP,0,sizeof sharesP);
 53  
 54    for(uint8_t i=0;i<peers;i++) {
 55      uint8_t shares[dealers][TOPRF_Share_BYTES];
 56      for(uint8_t j=0; j<dealers;j++) {
 57        memcpy(shares[j], mulshares[j][i], TOPRF_Share_BYTES);
 58        dump(mulshares[j][i], TOPRF_Share_BYTES, "mulsharesx[%d][%d]", j,i);
 59        dump(shares[j], TOPRF_Share_BYTES, "sharesx[%d]", i);
 60      }
 61      toprf_mpc_mul_finish(dealers, indexes, i+1, shares, sharesP[i]);
 62    }
 63  
 64    // verify
 65    uint8_t k0k1[crypto_core_ristretto255_SCALARBYTES];
 66    crypto_core_ristretto255_scalar_mul(k0k1, k0, k1);
 67  
 68    uint8_t r[crypto_core_ristretto255_SCALARBYTES];
 69    crypto_core_ristretto255_scalar_random(r);
 70    //debian_rng(r);
 71    uint8_t gr[crypto_core_ristretto255_BYTES];
 72    crypto_scalarmult_ristretto255_base(gr, r);
 73    uint8_t verifier[crypto_core_ristretto255_BYTES];
 74    if(crypto_scalarmult_ristretto255(verifier, k0k1, gr)) return 1;
 75  
 76    uint8_t sharesP2[2][TOPRF_Share_BYTES];
 77    if(crypto_scalarmult_ristretto255(sharesP2[0]+1, sharesP[0]+1, gr)) return 1;
 78    sharesP2[0][0]=1;
 79    if(crypto_scalarmult_ristretto255(sharesP2[1]+1, sharesP[2]+1, gr)) return 1;
 80    sharesP2[1][0]=3;
 81    uint8_t result[crypto_core_ristretto255_BYTES];
 82    if(toprf_thresholdmult(2, sharesP2, result)) return 1;
 83  
 84    if(memcmp(result,verifier,crypto_core_ristretto255_BYTES)!=0) {
 85      printf("\n");
 86      fprintf(stderr,"\e[0;31mhumiliating failure /o\\e[0m\n");
 87      return 1;
 88    }
 89  
 90    for(unsigned i=0;i<=peers-threshold;i++) {
 91      uint8_t v[crypto_core_ristretto255_BYTES];
 92      TOPRF_Share *shares = (TOPRF_Share *) sharesP[i];
 93      dkg_reconstruct(threshold, shares, v);
 94      dump(v,sizeof v, "v[%d] ", i);
 95      if(memcmp(v,k0k1,sizeof v)!=0) {
 96        fprintf(stderr,"\e[0;31mfailed to verify reconstruction of generated x from final shares!\e[0m\n");
 97        dump(k0k1,sizeof k0k1, "k0k1 ");
 98        dump(v,sizeof v, "v ");
 99        return 1;
100      }
101    }
102    return 0;
103  }
104  
105  static void rnd_poly(const uint8_t threshold,
106                       uint8_t a[threshold][crypto_core_ristretto255_SCALARBYTES]) {
107  #ifdef UNIT_TEST
108    fprintf(stderr,"coeffs\n");
109  #endif
110    for(int i=0;i<threshold;i++) {
111  #ifdef UNIT_TEST
112      debian_rng_scalar(a[i]);
113      dump(a[i],crypto_core_ristretto255_SCALARBYTES,"\t");
114  #else
115      crypto_core_ristretto255_scalar_random(a[i]);
116  #endif
117    }
118  }
119  
120  static void eval_poly(const uint8_t t,
121                        const uint8_t a[t][crypto_core_ristretto255_SCALARBYTES],
122                        const uint8_t _x,
123                        uint8_t result[crypto_core_ristretto255_SCALARBYTES]) {
124    uint8_t x0[crypto_core_ristretto255_SCALARBYTES]={0};
125    x0[0]=_x;
126    uint8_t x[crypto_core_ristretto255_SCALARBYTES]={0};
127    x[0]=1;
128    memset(result,0, crypto_core_ristretto255_SCALARBYTES);
129    uint8_t tmp[crypto_core_ristretto255_SCALARBYTES]={0};
130    for(int i=0;i<t;i++) {
131      crypto_core_ristretto255_scalar_mul(tmp, a[i], x);
132      crypto_core_ristretto255_scalar_add(result, result, tmp);
133      crypto_core_ristretto255_scalar_mul(x, x, x0);
134    }
135  }
136  
137  int test_vsps(void) {
138    // page 8, paragraph 3, line 1.
139    const uint8_t t = 1; // the degree of the polynomial
140    const uint8_t n = 2*(t + 1U);
141  
142    // we need a second generator h = g^z, without knowning what z is.
143    uint8_t h[crypto_scalarmult_ristretto255_BYTES] = {0};
144  #ifdef UNIT_TEST
145    uint8_t z[crypto_scalarmult_ristretto255_BYTES];
146    debian_rng_scalar(z);
147    dump(z, sizeof z, "z");
148    crypto_scalarmult_ristretto255_base(h,z);
149    dump(h, sizeof h, "h");
150  #else
151    const uint8_t numsn[] = "nothing up my sleeve number";
152    uint8_t hash[crypto_core_ristretto255_HASHBYTES] = {0};
153    crypto_generichash(hash, sizeof hash, numsn, sizeof numsn, NULL, 0);
154    if(0!=voprf_hash_to_group(hash, sizeof hash, h)) return -1;
155  #endif
156  
157    uint8_t f[t+1][crypto_core_ristretto255_SCALARBYTES];
158    rnd_poly(t+1,f);
159    uint8_t r[t+1][crypto_core_ristretto255_SCALARBYTES];
160    rnd_poly(t+1,r);
161  
162    // calulate the commitments A_i = g^f(i) * h^r(i)
163    // A[0] contains A_1, not A_0 which is not calculated above
164    uint8_t A[n][crypto_scalarmult_ristretto255_BYTES];
165    uint8_t tmp_s[crypto_scalarmult_ristretto255_SCALARBYTES];
166    uint8_t tmp[crypto_scalarmult_ristretto255_BYTES];
167    for(uint8_t i=0;i<n;i++) {
168      eval_poly(t+1, f, i, tmp_s);
169      fprintf(stderr,"f(%d)",i);
170      dump(tmp_s, sizeof tmp_s, "");
171      //dump(F[i], TOPRF_Share_BYTES, "f(%d)", i);
172      // A_i = g^f(i)
173      crypto_scalarmult_ristretto255_base(A[i],tmp_s);
174      //dump(h, sizeof h, "h    ");
175      //dump(R[i], TOPRF_Share_BYTES, "R_i");
176      eval_poly(t+1, r, i, tmp_s);
177      fprintf(stderr,"f(%d)",i);
178      dump(tmp_s, sizeof tmp_s, "");
179      // h ^ R_i
180      if(0!=crypto_scalarmult_ristretto255(tmp, tmp_s, h)) {
181        return -1;
182      }
183      //dump(tmp, sizeof tmp, "tmp  ");
184      // A_i = g^f(i) * h ^ r(i)
185      // the group is additive, the notation multiplicative
186      crypto_core_ristretto255_add(A[i], A[i], tmp);
187    }
188    fprintf(stderr,"commitments\n");
189    for(uint8_t i=0;i<n;i++) {
190      dump(A[i], crypto_scalarmult_ristretto255_BYTES, "A_%d\t", i);
191    }
192  
193    // in practice each peer i receives their f(i) and their r(i) privately
194    // and A is broadcast to everyone
195    // each peer i checks if A[i] == g^f(i)*h^r(i)
196    // we skip this for this test
197  
198    // check if A is of degree t
199    if(0!=toprf_mpc_vsps_check(t, A)) {
200      fprintf(stderr,"\e[0;31mhumiliating failure /o\\\e[0m\n");
201      return 1;
202    }
203  
204    return 0;
205  }
206  
207  int main(void) {
208    liboprf_debug = 0; // is a global variable from utils.h
209    if(0!=test_mpmul()) return 1;
210    liboprf_debug = 1; // is a global variable from utils.h
211    if(0!=test_vsps()) return 1;
212  
213    fprintf(stderr, "\e[0;32mgreat success!!5!\e[0m\n");
214  
215    return 0;
216  }