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 }