From a66e92f3e28680fc733b02ef9e3f9ebd56f5d5ec Mon Sep 17 00:00:00 2001 From: "Diego F. Aranha" Date: Wed, 9 Oct 2024 22:40:19 +0200 Subject: [PATCH] Add batch pairing delegation protocol. --- bench/bench_cp.c | 26 ++++++- include/relic_cp.h | 82 +++++++++++++++++--- src/cp/relic_cp_pcdel.c | 160 ++++++++++++++++++++++++++++++++++++++++ test/test_cp.c | 50 ++++++++----- 4 files changed, 289 insertions(+), 29 deletions(-) diff --git a/bench/bench_cp.c b/bench/bench_cp.c index 06257498d..15c0ed30d 100644 --- a/bench/bench_cp.c +++ b/bench/bench_cp.c @@ -943,13 +943,13 @@ static void pdpub(void) { gt_free(g[3]); } -#define AGGS 10 +#define AGGS 2 static void pdprv(void) { bn_t r1, r2[3], ls[AGGS+1]; g1_t p[AGGS], u1[2], v1[3]; g2_t q[AGGS], u2[2], v2[4], w2[4], ds[AGGS], rs[AGGS+1]; - gt_t e[2], r, g[4]; + gt_t e[2], r, g[RLC_MAX(4, AGGS + 1)]; bn_null(r1); gt_null(r); @@ -965,6 +965,8 @@ static void pdprv(void) { for (int i = 0; i < 4; i++) { g2_null(v2[i]); g2_null(w2[i]); + } + for (int i = 0; i < RLC_MAX(4, AGGS + 1); i++) { gt_null(g[i]); } for (int i = 0; i < AGGS; i++) { @@ -991,6 +993,8 @@ static void pdprv(void) { for (int i = 0; i < 4; i++) { g2_new(v2[i]); g2_new(w2[i]); + } + for (int i = 0; i < RLC_MAX(4, AGGS + 1); i++) { gt_new(g[i]); } for (int i = 0; i < AGGS; i++) { @@ -1049,6 +1053,22 @@ static void pdprv(void) { BENCH_ADD(cp_lvprv_ver(r, g, r1, e)); } BENCH_END; + BENCH_RUN("cp_ambat_gen (AGGS)") { + BENCH_ADD(cp_ambat_gen(r1, r2[0], u1[0], u2[0], e[0])); + } BENCH_END; + + BENCH_RUN("cp_ambat_ask (AGGS)") { + BENCH_ADD(cp_ambat_ask(ls, rs, u1[1], u2[1], r1, r2[0], p, q[0], u1[0], u2[0], e[0], AGGS)); + } BENCH_END; + + BENCH_RUN("cp_amprd_ans (AGGS)") { + BENCH_ADD(cp_ambat_ans(g, rs, u1[1], u2[1], r2[0], p, AGGS)); + } BENCH_END; + + BENCH_RUN("cp_amprd_ver (AGGS)") { + BENCH_ADD(cp_ambat_ver(g, g, ls, e[0], AGGS)); + } BENCH_END; + BENCH_RUN("cp_amprd_gen (AGGS)") { BENCH_ADD(cp_amprd_gen(ls, rs, r1, r2[0], r2[1], u1[0], u2[0], r2[2], e[0], AGGS)); } BENCH_END; @@ -1079,6 +1099,8 @@ static void pdprv(void) { for (int i = 0; i < 4; i++) { g2_free(v2[i]); g2_free(w2[i]); + } + for (int i = 0; i < RLC_MAX(4, AGGS + 1); i++) { gt_free(g[i]); } for (int i = 0; i < AGGS; i++) { diff --git a/include/relic_cp.h b/include/relic_cp.h index ae0aaedb8..bf86b85e1 100644 --- a/include/relic_cp.h +++ b/include/relic_cp.h @@ -1147,7 +1147,7 @@ int cp_ecss_ver(bn_t e, bn_t s, const uint8_t *msg, size_t len, const ec_t q); * @param[out] u1 - the U1 precomputed value in G_1. * @param[out] u2 - the U2 precomputed value in G_2. * @param[out] v2 - the image of the randomness in G_2. - * @param[out] e - the precomputed values e(U1, U2). + * @param[out] e - the precomputed value e(U1, U2). * @return RLC_OK if no errors occurred, RLC_ERR otherwise. */ int cp_pdpub_gen(bn_t c, bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e); @@ -1189,7 +1189,7 @@ int cp_pdpub_ans(gt_t g[3], const g1_t p, const g2_t q, const g1_t v1, * @param[out] r - the result of the computation. * @param[in] g - the group elements returned by the server. * @param[in] c - the challenge. - * @param[in] e - the precomputed values e(U1, U2). + * @param[in] e - the precomputed value e(U1, U2). * @return a boolean value indicating if the computation is correct. */ int cp_pdpub_ver(gt_t r, const gt_t g[3], const bn_t c, const gt_t e); @@ -1260,7 +1260,7 @@ int cp_pdprv_ver(gt_t r, const gt_t g[4], const bn_t c, const gt_t e[2]); * @param[out] u1 - the U1 precomputed value in G_1. * @param[out] u2 - the U2 precomputed value in G_2. * @param[out] v2 - the image of the randomness in G_2. - * @param[out] e - the precomputed values e(U1, U2). + * @param[out] e - the precomputed value e(U1, U2). * @return RLC_OK if no errors occurred, RLC_ERR otherwise. */ int cp_lvpub_gen(bn_t c, bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e); @@ -1303,7 +1303,7 @@ int cp_lvpub_ans(gt_t g[2], const g1_t p, const g2_t q, const g1_t v1, * @param[out] r - the result of the computation. * @param[in] g - the group elements returned by the server. * @param[in] c - the challenge. - * @param[in] e - the precomputed values e(U1, U2). + * @param[in] e - the precomputed value e(U1, U2). * @return a boolean value indicating if the computation is correct. */ int cp_lvpub_ver(gt_t r, const gt_t g[2], const bn_t c, const gt_t e); @@ -1375,7 +1375,7 @@ int cp_lvprv_ver(gt_t r, const gt_t g[4], const bn_t c, const gt_t e[2]); * @param[out] u - the mask in G_1. * @param[out] v - the mask in G_2. * @param[in,out] x - the secret key. - * @param[in,out] e - the precomputed values e(U1, U2). + * @param[in,out] e - the precomputed value e(U1, U2). * @param[in] first - the flag to indicate if the first iteration. * @param[in] longc - the flag to indicate if challenge is long. * @param[in] priva - the flag to indicate if first point is private. @@ -1429,7 +1429,7 @@ int cp_amore_ans(gt_t g[2], const bn_t d, const g1_t a1, const g2_t b1, * @param[out] r - the result of the computation. * @param[in] g - the group elements returned by the server. * @param[in] c - the challenge. - * @param[in] e - the precomputed values e(U1, U2). + * @param[in] e - the precomputed value e(U1, U2). * @param[in] priva - the flag to indicate if first point is private. * @param[in] privb - the flag to indicate if second point is private. * @return a boolean value indicating if the computation is correct. @@ -1437,6 +1437,69 @@ int cp_amore_ans(gt_t g[2], const bn_t d, const g1_t a1, const g2_t b1, int cp_amore_ver(gt_t r, const gt_t g[2], const bn_t c, const gt_t e, int priva, int privb); +/** + * Generates parameters for the AMORE batch pairing delegation protocol. + * + * @param[out] r - the randomness. + * @param[out] d - the delta value computed during setup. + * @param[out] u - the mask in G_1. + * @param[out] v - the mask in G_2. + * @param[out] e - the precomputed value e(U1, U2). + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ambat_gen(bn_t r, bn_t d, g1_t u, g2_t v, gt_t e); + +/** + * Executes the client-side request for the AMORE batch pairing delegation + * protocol. + * + * @param[out] ls - the challenges. + * @param[out] rs - the group elements computed by the client. + * @param[out] a - the element in G_1 computed by the client. + * @param[out] b - the element in G_2 computed by the client. + * @param[in] r - the randomness. + * @param[in] d - the delta value computed during setup. + * @param[in] p - the first arguments of the pairing. + * @param[in] q - the second argument of the pairing. + * @param[in] u - the U1 precomputed value in G_1. + * @param[in] v - the U2 precomputed value in G_2. + * @param[in] e - the precomputed value e(U1, U2). + * @param[in] m - the number of pairings delegated in the batch. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ambat_ask(bn_t *ls, g2_t *rs, g1_t a, g2_t b, const bn_t r, const bn_t d, + const g1_t *p, const g2_t q, const g1_t u, const g2_t v, gt_t e, + size_t m); + +/** + * Executes the server-side response for the AMORE batch pairing delegation + * protocol. + * + * @param[out] gs - the group elements computed by the server. + * @param[out] rs - the group elements sent by the client. + * @param[in] a - the element in G_1 computed by the client. + * @param[in] b - the element in G_2 computed by the client. + * @param[in] d - the delta value computed during setup. + * @param[in] p - the first arguments of the delegated pairings. + * @param[in] m - the number of pairings delegated in the batch. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ambat_ans(gt_t *gs, const g2_t *rs, const g1_t a, const g2_t b, + const bn_t d, const g1_t *p, size_t m); + +/** + * Verifies the result of the AMORE batch pairing delegation protocol. + * + * @param[out] es - the results of the computation. + * @param[in] gs - the group elements returned by the server. + * @param[in] ls - the challenges. + * @param[in] e - the precomputed value e(U1, U2). + * @param[in] m - the number of pairings delegated in the batch. + * @return a boolean value indicating if the computation is correct. + */ +int cp_ambat_ver(gt_t *es, const gt_t *gs, const bn_t *ls, const gt_t e, + size_t m); + /** * Generates parameters for the AMORE delegation protocol to compute the * product of m pairings using a pairing delegation protocol. @@ -1449,7 +1512,7 @@ int cp_amore_ver(gt_t r, const gt_t g[2], const bn_t c, const gt_t e, * @param[out] u - the mask in G_1 for the pairing delegation. * @param[out] v - the mask in G_2 for the pairing delegation. * @param[in,out] x - the secret key. - * @param[in,out] e - the precomputed values e(U1, U2). + * @param[in,out] e - the precomputed value e(U1, U2). * @param[in] m - the number of pairing to compute. * @return RLC_OK if no errors occurred, RLC_ERR otherwise. */ @@ -1506,11 +1569,12 @@ int cp_amprd_ans(gt_t g[4], const g2_t *ds, const bn_t d, const g1_t a1, * @param[in] g - the group elements returned by the server. * @param[in] c - the pairing product delegation challenge. * @param[in] c - the pairing delegation challenge. - * @param[in] e - the precomputed values e(U1, U2). + * @param[in] e - the precomputed value e(U1, U2). * @param[in] m - the number of pairing to compute. * @return a boolean value indicating if the computation is correct. */ -int cp_amprd_ver(gt_t r, const gt_t g[4], const bn_t l, const bn_t c, const gt_t e); +int cp_amprd_ver(gt_t r, const gt_t g[4], const bn_t l, const bn_t c, + const gt_t e); /** * Generates a master key for the SOKAKA identity-based non-interactive diff --git a/src/cp/relic_cp_pcdel.c b/src/cp/relic_cp_pcdel.c index 0c6b2f940..3c2ae4a47 100644 --- a/src/cp/relic_cp_pcdel.c +++ b/src/cp/relic_cp_pcdel.c @@ -715,6 +715,166 @@ int cp_amore_ver(gt_t r, const gt_t g[2], const bn_t c, const gt_t e, return result; } +int cp_ambat_gen(bn_t r, bn_t d, g1_t u, g2_t v, gt_t e) { + bn_t n, u1, u2; + int result = RLC_OK; + + bn_null(n); + bn_null(u1); + bn_null(u2); + + RLC_TRY { + bn_new(n); + bn_new(u1); + bn_new(u2); + + pc_get_ord(n); + bn_rand_mod(u1, n); + bn_rand_mod(u2, n); + + bn_mul(r, u1, u2); + bn_mod(r, r, n); + gt_get_gen(e); + gt_exp(e, e, r); + + bn_rand_mod(r, n); + bn_mod_inv(d, r, n); + bn_mul(d, d, u2); + bn_mod(d, d, n); + g1_mul_gen(u, u1); + g2_mul_gen(v, u2); + } RLC_CATCH_ANY { + result = RLC_ERR; + } RLC_FINALLY { + bn_free(n); + bn_free(u1); + bn_free(u2); + } + + return result; +} + +int cp_ambat_ask(bn_t *ls, g2_t *rs, g1_t a, g2_t b, const bn_t r, const bn_t d, + const g1_t *p, const g2_t q, const g1_t u, const g2_t v, gt_t e, + size_t m) { + bn_t n, *t = RLC_ALLOCA(bn_t, m); + size_t eps, len; + int result = RLC_OK; + + bn_null(n); + + RLC_TRY { + bn_new(n); + + pc_get_ord(n); + eps = gt_size_bin(e, 1) / g2_size_bin(rs[0], 1); + len = RAND_DIST; + for (size_t i = 0; i < m; i++) { + bn_null(t[i]); + bn_new(t[i]); + + if (ep_curve_is_pairf() == EP_BN) { + bn_rand(ls[i], RLC_POS, len); + } else { + bn_rand_frb(ls[i], &(core_get()->par), n, len); + } + len = RAND_DIST + BND_STORE + eps; + } + + g1_set_infty(a); + bn_mod_inv_sim(t, ls, n, m); + for (size_t i = 0; i < m; i++) { + g1_add(a, a, p[i]); + g2_mul(rs[i], q, t[i]); + } + + g1_sub(a, u, a); + g1_norm(a, a); + g1_mul(a, a, r); + g2_sub(b, v, q); + g2_norm(b, b); + } RLC_CATCH_ANY { + result = RLC_ERR; + } RLC_FINALLY { + bn_free(n); + for (size_t i = 0; i < m; i++) { + bn_free(t[i]); + } + } + + return result; +} + +int cp_ambat_ans(gt_t *gs, const g2_t *rs, const g1_t a, const g2_t b, + const bn_t d, const g1_t *p, size_t m) { + g1_t ps[2]; + g2_t qs[2]; + int result = RLC_OK; + + g1_null(ps[0]); + g1_null(ps[1]); + g2_null(qs[0]); + g2_null(qs[1]); + + RLC_TRY { + g1_new(ps[0]); + g1_new(ps[1]); + g2_new(qs[0]); + g2_new(qs[1]); + + g1_set_infty(ps[0]); + for (size_t i = 0; i < m; i++) { + g1_add(ps[0], ps[0], p[i]); + pc_map(gs[i], p[i], rs[i]); + } + g1_norm(ps[0], ps[0]); + g2_copy(qs[0], b); + g1_copy(ps[1], a); + g2_mul_gen(qs[1], d); + + pc_map_sim(gs[m], ps, qs, 2); + } RLC_CATCH_ANY { + result = RLC_ERR; + } RLC_FINALLY { + g1_free(ps[0]); + g1_free(ps[1]); + g2_free(qs[0]); + g2_free(qs[1]); + } + + return result; +} + +int cp_ambat_ver(gt_t *es, const gt_t *gs, const bn_t *ls, const gt_t e, + size_t m) { + int result = 1; + gt_t t; + + gt_null(t); + + RLC_TRY { + gt_new(t); + gt_set_unity(t); + for (size_t i = 0; i < m; i++) { + result &= gt_is_valid(gs[i]); + gt_exp(es[i], gs[i], ls[i]); + gt_mul(t, t, es[i]); + } + gt_mul(t, t, gs[m]); + if (!result || gt_cmp(e, t) != RLC_EQ) { + for (size_t i = 0; i < m; i++) { + gt_set_unity(es[i]); + } + } + } RLC_CATCH_ANY { + result = RLC_ERR; + } + RLC_FINALLY { + gt_free(t); + } + return result; +} + int cp_amprd_gen(bn_t *ls, g2_t *rs, bn_t c, bn_t r, bn_t d, g1_t u, g2_t v, bn_t x, gt_t e, size_t m) { bn_t n, xi; diff --git a/test/test_cp.c b/test/test_cp.c index dcc1b212b..3ffec2de0 100644 --- a/test/test_cp.c +++ b/test/test_cp.c @@ -1321,14 +1321,14 @@ static int pdprv(void) { return code; } -#define AGGS 10 +#define AGGS 1000 static int pdprd(void) { int code = RLC_ERR; bn_t x, t, r1, r2, ls[AGGS + 1]; g1_t p[AGGS], u1, v1, w1; g2_t q[AGGS], u2, v2, w2, rs[AGGS + 1], ds[AGGS]; - gt_t e, r, g[4]; + gt_t e, r, g[RLC_MAX(4, AGGS + 1)]; bn_null(t); bn_null(x); @@ -1356,6 +1356,10 @@ static int pdprd(void) { g2_new(w2); gt_new(e); gt_new(r); + for (size_t i = 0; i < RLC_MAX(4, AGGS + 1); i++) { + gt_null(g[i]); + gt_new(g[i]); + } for (size_t i = 0; i < AGGS; i++) { g1_null(p[i]); g2_null(q[i]); @@ -1373,10 +1377,20 @@ static int pdprd(void) { g2_null(rs[AGGS]); g2_new(rs[AGGS]); - for (size_t i = 0; i < 4; i++) { - gt_null(g[i]); - gt_new(g[i]); - } + TEST_CASE("batch delegated pairing with (n - 1) public inputs is correct") { + TEST_ASSERT(cp_ambat_gen(r1, r2, u1, u2, e) == RLC_OK, end); + for (size_t i = 0; i < AGGS; i++) { + g1_rand(p[i]); + } + g2_rand(q[0]); + TEST_ASSERT(cp_ambat_ask(ls, rs, v1, v2, r1, r2, p, q[0], u1, u2, e, AGGS) == RLC_OK, end); + TEST_ASSERT(cp_ambat_ans(g, rs, v1, v2, r2, p, AGGS) == RLC_OK, end); + TEST_ASSERT(cp_ambat_ver(g, g, ls, e, AGGS) == 1, end); + for (size_t i = 0; i < AGGS; i++) { + pc_map(e, p[i], q[0]); + TEST_ASSERT(gt_cmp(e, g[i]) == RLC_EQ, end); + } + } TEST_END; TEST_CASE("amortized delegated pairing product is correct") { TEST_ASSERT(cp_amprd_gen(ls, rs, r1, r2, t, u1, u2, x, e, AGGS) == RLC_OK, end); @@ -1408,18 +1422,18 @@ static int pdprd(void) { g2_free(w2); gt_free(e); gt_free(r); - for (size_t i = 0; i < AGGS; i++) { - g1_free(p[i]); - g2_free(q[i]); - g2_free(rs[i]); - g2_free(ds[i]); - bn_free(ls[i]); - } - bn_free(ls[AGGS]); - g2_free(rs[AGGS]); - for (size_t i = 0; i < 4; i++) { - gt_free(g[i]); - } + for (size_t i = 0; i < RLC_MAX(4, AGGS + 1); i++) { + gt_free(g[i]); + } + for (size_t i = 0; i < AGGS; i++) { + g1_free(p[i]); + g2_free(q[i]); + g2_free(rs[i]); + g2_free(ds[i]); + bn_free(ls[i]); + } + bn_free(ls[AGGS]); + g2_free(rs[AGGS]); return code; }