From 3c78750e22b3d36a6af321e0ead700f36665da13 Mon Sep 17 00:00:00 2001 From: "Diego F. Aranha" Date: Wed, 24 Apr 2024 01:53:05 +0200 Subject: [PATCH] Implemented aggregate BLS signatures. --- include/relic_cp.h | 27 ++++++++++++ src/cp/relic_cp_bls.c | 95 +++++++++++++++++++++++++++++++++++++++++++ test/test_cp.c | 67 ++++++++++++++++++++++++------ 3 files changed, 176 insertions(+), 13 deletions(-) diff --git a/include/relic_cp.h b/include/relic_cp.h index 59b5ea62d..3d48d5051 100644 --- a/include/relic_cp.h +++ b/include/relic_cp.h @@ -1670,6 +1670,33 @@ int cp_bls_sig(g1_t s, const uint8_t *msg, size_t len, const bn_t d); */ int cp_bls_ver(const g1_t s, const uint8_t *msg, size_t len, const g2_t q); +/** + * Aggregates a pair (signature, public key) into a signature over the same + * message, as in the Boneh-Drijvers-Neven scheme. + * The aggregate signature can then be verified as in the original BLS scheme. + * + * @param[in,out] sig - the aggregate signature. + * @param[in,out] a - the aggregate public key + * @param[in] s - the signature to aggregate. + * @param[in] q - the public key to aggregate. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bls_agg_sig(g1_t sig, g2_t a, const g1_t s, const g2_t q); + +/** + * Verifies an aggregate signature over distinct messages, given an aggregate + * signature in the Boneh-Gentry-Lynn-Schacham format and the public keys. + * + * @param[in,out] s - the aggregate signature. + * @param[in] m - the signed messages. + * @param[in] l - the message lengths. + * @param[in] size - the number of messages or aggregated signatures. + * @param[in] q - the public keys. + * @return a boolean value indicating if the signature is valid. + */ +int cp_bls_agg_ver(const g1_t s, const uint8_t **m, const size_t *l, + size_t size, const g2_t q[]); + /** * Generates a key pair for the Boneh-Boyen (BB) signature protocol. * diff --git a/src/cp/relic_cp_bls.c b/src/cp/relic_cp_bls.c index 6ddb347a9..27b8e24ba 100644 --- a/src/cp/relic_cp_bls.c +++ b/src/cp/relic_cp_bls.c @@ -119,3 +119,98 @@ int cp_bls_ver(const g1_t s, const uint8_t *msg, size_t len, const g2_t q) { } return result; } + +int cp_bls_agg_sig(g1_t sig, g2_t a, const g1_t s, const g2_t q) { + bn_t t; + g1_t u; + g2_t p; + uint8_t h[RLC_MD_LEN], *buf = RLC_ALLOCA(uint8_t, g2_size_bin(q, 0)); + int result = RLC_OK; + + bn_null(t); + g1_null(u); + g2_null(p); + + RLC_TRY { + if (buf == NULL) { + RLC_THROW(ERR_NO_MEMORY); + } + bn_new(t); + g1_new(p); + + md_map(h, buf, g2_size_bin(q, 0)); + bn_read_bin(t, h, RLC_MIN(RLC_MD_LEN, RLC_CEIL(pc_param_level(), 8))); + + g1_mul(u, s, t); + g1_add(sig, sig, u); + + g2_mul(p, q, t); + g2_add(a, a, p); + } + RLC_CATCH_ANY { + result = RLC_ERR; + } + RLC_FINALLY { + bn_free(t); + g1_free(u); + g2_free(p); + RLC_FREE(buf); + } + return result; +} + +int cp_bls_agg_ver(const g1_t s, const uint8_t **m, const size_t *l, + size_t size, const g2_t q[]) { + g1_t *p = RLC_ALLOCA(g1_t, size + 1); + g2_t *r = RLC_ALLOCA(g2_t, size + 1); + gt_t e; + int result = 1; + + gt_null(e); + + RLC_TRY { + if (p == NULL || r == NULL) { + RLC_FREE(p); + RLC_FREE(r); + RLC_THROW(ERR_NO_MEMORY); + } + g1_null(p[0]); + g2_null(r[0]); + g1_new(p[0]); + g2_new(r[0]); + for (size_t i = 0; i < size; i++) { + g1_null(p[i + 1]); + g1_new(p[i + 1]); + g2_null(r[i + 1]); + g2_new(r[i + 1]); + g1_map(p[i + 1], m[i], l[i]); + g2_copy(r[i + 1], q[i]); + } + gt_new(e); + + g1_copy(p[0], s); + g2_get_gen(r[0]); + g2_neg(r[0], r[0]); + + pc_map_sim(e, p, r, size + 1); + if (gt_is_unity(e)) { + result = 1; + } + for (size_t i = 0; i < size; i++) { + result = result & g2_is_valid(q[i]); + } + } + RLC_CATCH_ANY { + RLC_THROW(ERR_CAUGHT); + } + RLC_FINALLY { + for (size_t i = 0; i < size + 1; i++) { + g1_free(p[i]); + g2_free(r[i]); + } + gt_free(e); + RLC_FREE(p); + RLC_FREE(r); + } + return result; +} \ No newline at end of file diff --git a/test/test_cp.c b/test/test_cp.c index b8bc9951f..60850163b 100644 --- a/test/test_cp.c +++ b/test/test_cp.c @@ -1509,27 +1509,66 @@ static int bgn(void) { static int bls(void) { int code = RLC_ERR; bn_t d; - g1_t s; - g2_t q; + g1_t s[2]; + g2_t q[2]; uint8_t m[5] = { 0, 1, 2, 3, 4 }; + uint8_t n[5] = { 4, 3, 2, 1, 0 }; + const uint8_t *ms[2] = { m, n }; + const size_t ls[2] = { sizeof(m), sizeof(n) }; bn_null(d); - g1_null(s); - g2_null(q); + g1_null(s[0]); + g1_null(s[1]); + g2_null(q[0]); + g2_null(q[1]); RLC_TRY { bn_new(d); - g1_new(s); - g2_new(q); + g1_new(s[0]); + g1_new(s[1]); + g2_new(q[0]); + g2_new(q[1]); TEST_CASE("boneh-lynn-schacham short signature is correct") { - TEST_ASSERT(cp_bls_gen(d, q) == RLC_OK, end); - TEST_ASSERT(cp_bls_sig(s, m, sizeof(m), d) == RLC_OK, end); - TEST_ASSERT(cp_bls_ver(s, m, sizeof(m), q) == 1, end); + TEST_ASSERT(cp_bls_gen(d, q[0]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[0], m, sizeof(m), d) == RLC_OK, end); + TEST_ASSERT(cp_bls_ver(s[0], m, sizeof(m), q[0]) == 1, end); /* Check adversarial signature. */ memset(m, 0, sizeof(m)); - g2_set_infty(q); - TEST_ASSERT(cp_bls_ver(s, m, sizeof(m), q) == 0, end); + g2_set_infty(q[0]); + TEST_ASSERT(cp_bls_ver(s[0], m, sizeof(m), q[0]) == 0, end); + } + TEST_END; + + TEST_CASE("boneh-gentry-lynn-schacham aggregate signature is correct") { + TEST_ASSERT(cp_bls_gen(d, q[0]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[0], m, sizeof(m), d) == RLC_OK, end); + TEST_ASSERT(cp_bls_gen(d, q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[1], m, sizeof(m), d) == RLC_OK, end); + g1_add(s[0], s[0], s[1]); + g2_add(q[0], q[0], q[1]); + TEST_ASSERT(cp_bls_ver(s[0], m, sizeof(m), q[0]) == 1, end); + } + TEST_END; + + TEST_CASE("boneh-drijvers-neven aggregate signature is correct") { + g1_set_infty(s[0]); + g2_set_infty(q[0]); + TEST_ASSERT(cp_bls_gen(d, q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[1], m, sizeof(m), d) == RLC_OK, end); + TEST_ASSERT(cp_bls_agg_sig(s[0], q[0], s[1], q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_gen(d, q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[1], m, sizeof(m), d) == RLC_OK, end); + TEST_ASSERT(cp_bls_agg_sig(s[0], q[0], s[1], q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_ver(s[1], m, sizeof(m), q[1]) == 1, end); + g1_set_infty(s[0]); + g2_set_infty(q[0]); + TEST_ASSERT(cp_bls_gen(d, q[0]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[0], ms[0], ls[0], d) == RLC_OK, end); + TEST_ASSERT(cp_bls_gen(d, q[1]) == RLC_OK, end); + TEST_ASSERT(cp_bls_sig(s[1], ms[1], ls[1], d) == RLC_OK, end); + g1_add(s[0], s[0], s[1]); + TEST_ASSERT(cp_bls_agg_ver(s[0], ms, ls, 2, q) == 1, end); } TEST_END; } @@ -1540,8 +1579,10 @@ static int bls(void) { end: bn_free(d); - g1_free(s); - g2_free(q); + g1_free(s[0]); + g1_free(s[1]); + g2_free(q[0]); + g2_free(q[1]); return code; }