Skip to content

Commit

Permalink
Implemented aggregate BLS signatures.
Browse files Browse the repository at this point in the history
  • Loading branch information
dfaranha committed Apr 23, 2024
1 parent 7156953 commit 3c78750
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 13 deletions.
27 changes: 27 additions & 0 deletions include/relic_cp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
95 changes: 95 additions & 0 deletions src/cp/relic_cp_bls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
67 changes: 54 additions & 13 deletions test/test_cp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}

Expand Down

0 comments on commit 3c78750

Please sign in to comment.