blynn / pbc

The Pairing-based Crypto library
http://crypto.stanford.edu/pbc/
GNU Lesser General Public License v3.0
237 stars 100 forks source link

Pairing product with a null element is always null #7

Open baz1 opened 8 years ago

baz1 commented 8 years ago

Hello,

I believe that there is a bad behavior implemented in the function element_prod_pairing, quoted below:

static inline void element_prod_pairing(
    element_t out, element_t in1[], element_t in2[], int n) {
  pairing_ptr pairing = out->field->pairing;
  int i;
  PBC_ASSERT(pairing->GT == out->field, "pairing output mismatch");
  for(i = 0; i < n; i++) {
    PBC_ASSERT(pairing->G1 == in1[i]->field, "pairing 1st input mismatch");
    PBC_ASSERT(pairing->G2 == in2[i]->field, "pairing 2nd input mismatch");
    if (element_is0(in1[i])) {
      element_set0(out);
      return;
    }
    if (element_is0(in2[i])) {
      element_set0(out);
      return;
    }
  }
  pairing->prod_pairings((element_ptr) out->data, in1, in2, n, pairing);
}

The first loop is looking for null elements and exits with a null (unity) result if it finds any. If the function is to be what it states - a product of pairings - it should just ignore couples with a null element, but not disregard the rest of the input and return a null result. The following snippet shows that the behavior is indeed not the same as what the manual product would produce:

    pairing_t params;
    // [...] (initialize params)
    element_t g1, g1_0, g2, gt, gt_0, gtp1, gtp2;

    element_init_G1(g1, params);
    element_init_G1(g1_0, params);
    element_init_G2(g2, params);
    element_init_GT(gt, params);
    element_init_GT(gt_0, params);
    element_init_GT(gtp1, params);
    element_init_GT(gtp2, params);

    element_random(g1);
    element_set0(g1_0);
    element_random(g2);

    /* Manual pairing product: */
    pairing_apply(gt, g1, g2, params);
    pairing_apply(gt_0, g1_0, g2, params);
    element_mul(gtp1, gt, gt_0);

    /* Pairing product using element_prod_pairing */
    element_t in1[2], in2[2];
    element_init_G1(in1[0], params);
    element_init_G1(in1[1], params);
    element_init_G2(in2[0], params);
    element_init_G2(in2[1], params);
    element_set(in1[0], g1);
    element_set(in1[1], g1_0);
    element_set(in2[0], g2);
    element_set(in2[1], g2);
    element_prod_pairing(gtp2, in1, in2, 2);

    cout << "gtp1 is gt: " << (!element_cmp(gtp1, gt)) << endl; // Yes
    cout << "gtp2 is gt: " << (!element_cmp(gtp2, gt)) << endl; // No

The couples containing a null element should therefore only be removed from the list before the pairing product is computed. Best regards,

Rémi

PS : Is there a better way to put already existing variables in a 'element_t[]' array other than copying them? I've tried to only copy their pointer value, but without success (I am not used to manipulating fixed-sized arrays). Thank you for your advice.

blynn commented 8 years ago

Thanks, and sorry it's taken so long for me to respond.

I think you're right but I'm afraid I wrote that code a long time ago, and I haven't had much time to look into this in detail. Any chance you could supply a patch that fixes these issues?

-Ben

On Sun, Sep 4, 2016 at 9:40 AM, Rémi Bazin notifications@github.com wrote:

Hello,

I believe that there is a bad behavior implemented in the function element_prod_pairing, quoted below:

static inline void element_prod_pairing( element_t out, element_t in1[], element_t in2[], int n) { pairing_ptr pairing = out->field->pairing; int i; PBC_ASSERT(pairing->GT == out->field, "pairing output mismatch"); for(i = 0; i < n; i++) { PBC_ASSERT(pairing->G1 == in1[i]->field, "pairing 1st input mismatch"); PBC_ASSERT(pairing->G2 == in2[i]->field, "pairing 2nd input mismatch"); if (element_is0(in1[i])) { element_set0(out); return; } if (element_is0(in2[i])) { element_set0(out); return; } } pairing->prod_pairings((element_ptr) out->data, in1, in2, n, pairing); }

The first loop is looking for null elements and exits with a null (unity) result if it finds any. If the function is to be what it states - a product of pairings - it should just ignore couples with a null element, but not disregard the rest of the input and return a null result. The following snippet shows that the behavior is indeed not the same as what the manual product would produce:

pairing_t params;
// [...] (initialize params)
element_t g1, g1_0, g2, gt, gt_0, gtp1, gtp2;

element_init_G1(g1, params);
element_init_G1(g1_0, params);
element_init_G2(g2, params);
element_init_GT(gt, params);
element_init_GT(gt_0, params);
element_init_GT(gtp1, params);
element_init_GT(gtp2, params);

element_random(g1);
element_set0(g1_0);
element_random(g2);

/* Manual pairing product: */
pairing_apply(gt, g1, g2, params);
pairing_apply(gt_0, g1_0, g2, params);
element_mul(gtp1, gt, gt_0);

/* Pairing product using element_prod_pairing */
element_t in1[2], in2[2];
element_init_G1(in1[0], params);
element_init_G1(in1[1], params);
element_init_G2(in2[0], params);
element_init_G2(in2[1], params);
element_set(in1[0], g1);
element_set(in1[1], g1_0);
element_set(in2[0], g2);
element_set(in2[1], g2);
element_prod_pairing(gtp2, in1, in2, 2);

cout << "gtp1 is gt: " << (!element_cmp(gtp1, gt)) << endl; // Yes
cout << "gtp2 is gt: " << (!element_cmp(gtp2, gt)) << endl; // No

The couples containing a null element should therefore only be removed from the list before the pairing product is computed. Best regards,

Rémi

PS : Is there a better way to put already existing variables in a 'element_t[]' array other than copying them? I've tried to only copy their pointer value, but without success (I am not used to manipulating fixed-sized arrays). Thank you for your advice.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/blynn/pbc/issues/7, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAOWHx_uSyQFziwwzAmZ3h721_-L06yks5qmvRkgaJpZM4J0kwy .