/ src / tests / dkg.c
dkg.c
  1  #include <string.h>
  2  #include "dkg.h"
  3  #include "toprf.h"
  4  #include "utils.h"
  5  
  6  extern int liboprf_debug;
  7  
  8  typedef struct {
  9    uint8_t index;
 10    uint8_t value[crypto_core_ristretto255_BYTES];
 11  } __attribute((packed)) TOPRF_Part;
 12  
 13  static void topart(TOPRF_Part *r, const TOPRF_Share *s) {
 14    r->index=s->index;
 15    crypto_scalarmult_ristretto255_base(r->value, s->value);
 16  }
 17  
 18  static int test_dkg_start(const uint8_t n,
 19                            const uint8_t a[crypto_core_ristretto255_SCALARBYTES],
 20                            const TOPRF_Share shares[n]) {
 21    const size_t response_len = 3;
 22    uint8_t responses[response_len][TOPRF_Part_BYTES];
 23    uint8_t result[crypto_scalarmult_ristretto255_BYTES];
 24    uint8_t v[crypto_scalarmult_ristretto255_BYTES];
 25  
 26    topart((TOPRF_Part *) responses[0], &shares[4]);
 27    topart((TOPRF_Part *) responses[1], &shares[2]);
 28    topart((TOPRF_Part *) responses[2], &shares[0]);
 29  
 30    if(toprf_thresholdmult(response_len, responses, result)) return 1;
 31  
 32    crypto_scalarmult_ristretto255_base(v, a);
 33  
 34    if(memcmp(v,result,sizeof v)!=0) {
 35      fprintf(stderr,"\e[0;31mmeh!\e[0m\n");
 36      dump(v,sizeof v, "v");
 37      dump(result,sizeof v, "r");
 38      return 1;
 39    }
 40    return 0;
 41  }
 42  
 43  static int test_dkg_finish(const uint8_t n, const TOPRF_Share shares[n]) {
 44    const size_t response_len = 3;
 45    uint8_t responses[response_len][TOPRF_Part_BYTES];
 46    uint8_t v0[crypto_scalarmult_ristretto255_BYTES]={0};
 47    uint8_t v1[crypto_scalarmult_ristretto255_BYTES]={0};
 48  
 49    //dump((uint8_t*) &shares[4], sizeof(TOPRF_Share), "&shares[4][0] ");
 50    topart((TOPRF_Part *) responses[0], &shares[4]);
 51    topart((TOPRF_Part *) responses[1], &shares[2]);
 52    topart((TOPRF_Part *) responses[2], &shares[0]);
 53    //topart((TOPRF_Part *) responses[3], &shares[1][0]);
 54    //topart((TOPRF_Part *) responses[4], &shares[3][0]);
 55    if(toprf_thresholdmult(response_len, responses, v0)) return 1;
 56    dump(v0,sizeof v0, "v0 ");
 57  
 58    topart((TOPRF_Part *) responses[0], &shares[3]);
 59    topart((TOPRF_Part *) responses[1], &shares[1]);
 60    topart((TOPRF_Part *) responses[2], &shares[0]);
 61    //topart((TOPRF_Part *) responses[3], &shares[2][0]);
 62    //topart((TOPRF_Part *) responses[4], &shares[4][0]);
 63    if(toprf_thresholdmult(response_len, responses, v1)) return 1;
 64    dump(v1,sizeof v1, "v1 ");
 65  
 66    if(memcmp(v0,v1,sizeof v1)!=0) {
 67      fprintf(stderr,"\e[0;31mfailed to verify shares from dkg_finish!\e[0m\n");
 68      return 1;
 69    }
 70    return 0;
 71  }
 72  
 73  int main(void) {
 74    liboprf_debug = 1;
 75    uint8_t n=5, threshold=3;
 76    uint8_t commitments[n][threshold][crypto_core_ristretto255_BYTES];
 77    TOPRF_Share shares[n][n];
 78  
 79    for(int i=0;i<n;i++) {
 80      if(dkg_start(n, threshold, commitments[i], shares[i])) {
 81        return 1;
 82      }
 83      if(liboprf_debug) {
 84        for(int j=0;j<n;j++) {
 85          dump((uint8_t*) &shares[i][j], sizeof(TOPRF_Share), "s[%d,%d] ", i+1, j+1);
 86        }
 87        fprintf(stderr,"\n");
 88      }
 89    }
 90  
 91    // each Pi sends s_ij, and s'_ij to Pj
 92    // basically we are transposing here the shares matrix above
 93    TOPRF_Share sent_shares[n];
 94    TOPRF_Share final_shares[n];
 95  
 96    for(int i=0;i<n;i++) {
 97      for(int j=0;j<n;j++) {
 98        memcpy(&sent_shares[j], &shares[j][i], sizeof(TOPRF_Share));
 99        if(liboprf_debug) {
100           fprintf(stderr, "\nsent to peer %d\n",i+1);
101           dump((uint8_t*) &sent_shares[j], sizeof(TOPRF_Share), "s[%d,%d] ", i+1, j+1);
102        }
103      }
104  
105      uint8_t fails[n];
106      memset(fails, 0, sizeof fails);
107      uint8_t fails_len=0;
108  
109      // verify step (2)
110      if(dkg_verify_commitments(n,threshold,i+1, commitments,
111                                sent_shares, fails, &fails_len)) {
112        for(int j=0;j<fails_len;j++) {
113           fprintf(stderr,"\e[0;31m[%d] failed to verify commitments from %d!\e[0m\n", i+1, fails[j]);
114        }
115        return 1;
116      }
117  
118      fprintf(stderr, "\e[0;32mP_%d stage 1 correct!\e[0m\n", i);
119  
120      final_shares[i].index=i+1;
121      // finalize dkg (3)
122      dkg_finish(n,sent_shares,i+1,&final_shares[i]);
123    }
124  
125    for(int i=0;i<n;i++) {
126      dump((uint8_t*) &final_shares[i], sizeof(TOPRF_Share), "final_shares[%d]", i+1);
127    }
128  
129    if(test_dkg_finish(n, final_shares)) return 1;
130  
131    // x = sum(a[0]) == 0x28 if debian_rng_scalar is used
132    uint8_t x[crypto_core_ristretto255_BYTES]={0x28};
133    if(test_dkg_start(n, x, final_shares)) return 1;
134  
135    uint8_t v[crypto_core_ristretto255_BYTES];
136    dkg_reconstruct(threshold, final_shares, v);
137    if(memcmp(v,x,sizeof v)!=0) {
138      fprintf(stderr,"\e[0;31mfailed to verify reconstruction of generated x from final shares!\e[0m\n");
139      dump(x,sizeof x, "x ");
140      dump(v,sizeof v, "v ");
141      return 1;
142    }
143  
144    fprintf(stderr, "\e[0;32meverything correct!\e[0m\n");
145    return 0;
146  }