From 5d87e80c6928694bc9d2fe3bf8fd89343ba16f83 Mon Sep 17 00:00:00 2001 From: Russell O'Connor Date: Thu, 18 Jan 2024 10:33:12 -0500 Subject: [PATCH 1/3] shallue_van_de_woestijne rewrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation returns an off-curve point for the input t=0. This rewrite addresses that issue by implicity returning the on-curve point (d, sqrt(1 + b)), which is the point that the paper Indifferentiable Hashing to Barreto–Naehrig Curves suggests returning in this case. Note: At the moment it is cryptographically impossible for the input t to be 0. --- src/modules/generator/main_impl.h | 63 +++++++++++++------------------ 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index a00b22f4..2804a691 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -107,61 +107,50 @@ static void shallue_van_de_woestijne(secp256k1_ge* ge, const secp256k1_fe* t) { x2 = -(x1 + 1) x3 = 1 + 1/w^2 - To avoid the 2 divisions, compute the above in numerator/denominator form: - wn = c * t - wd = 1 + 7 + t^2 - x1n = d*wd - t*wn - x1d = wd - x2n = -(x1n + wd) - x2d = wd - x3n = wd^2 + c^2 * t^2 - x3d = (c * t)^2 + To avoid the 2 divisions, compute the joint denominator j = wd * x3d, where + wd = 1 + b + t^2 + x3d = c^2 * t^2 = -3 * t^2 - The joint denominator j = wd * c^2 * t^2, and - 1 / x1d = 1/j * c^2 * t^2 - 1 / x2d = x3d = 1/j * wd + so that + + 1 / wd = 1/j * x3d + 1 / x3d = 1/j * wd */ - static const secp256k1_fe c = SECP256K1_FE_CONST(0x0a2d2ba9, 0x3507f1df, 0x233770c2, 0xa797962c, 0xc61f6d15, 0xda14ecd4, 0x7d8d27ae, 0x1cd5f852); + static const secp256k1_fe negc = SECP256K1_FE_CONST(0xf5d2d456, 0xcaf80e20, 0xdcc88f3d, 0x586869d3, 0x39e092ea, 0x25eb132b, 0x8272d850, 0xe32a03dd); static const secp256k1_fe d = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); - static const secp256k1_fe b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7); - static const secp256k1_fe b_plus_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 8); - secp256k1_fe wn, wd, x1n, x2n, x3n, x3d, jinv, tmp, x1, x2, x3, alphain, betain, gammain, y1, y2, y3; + secp256k1_fe wd, x3d, jinv, tmp, x1, x2, x3, alphain, betain, gammain, y1, y2, y3; int alphaquad, betaquad; - secp256k1_fe_mul(&wn, &c, t); /* mag 1 */ secp256k1_fe_sqr(&wd, t); /* mag 1 */ - secp256k1_fe_add(&wd, &b_plus_one); /* mag 2 */ - secp256k1_fe_mul(&tmp, t, &wn); /* mag 1 */ - secp256k1_fe_negate(&tmp, &tmp, 1); /* mag 2 */ - secp256k1_fe_mul(&x1n, &d, &wd); /* mag 1 */ - secp256k1_fe_add(&x1n, &tmp); /* mag 3 */ - x2n = x1n; /* mag 3 */ - secp256k1_fe_add(&x2n, &wd); /* mag 5 */ - secp256k1_fe_negate(&x2n, &x2n, 5); /* mag 6 */ - secp256k1_fe_mul(&x3d, &c, t); /* mag 1 */ - secp256k1_fe_sqr(&x3d, &x3d); /* mag 1 */ - secp256k1_fe_sqr(&x3n, &wd); /* mag 1 */ - secp256k1_fe_add(&x3n, &x3d); /* mag 2 */ - secp256k1_fe_mul(&jinv, &x3d, &wd); /* mag 1 */ + secp256k1_fe_mul(&x1, &negc, &wd); /* mag 1 */ + x3d = wd; /* mag 1 */ + secp256k1_fe_mul_int(&x3d, 3); /* mag 3 */ + secp256k1_fe_negate(&x3d, &x3d, 3); /* mag 4 */ + secp256k1_fe_add_int(&wd, SECP256K1_B + 1); /* mag 2 */ + secp256k1_fe_mul(&jinv, &wd, &x3d); /* mag 1 */ secp256k1_fe_inv(&jinv, &jinv); /* mag 1 */ - secp256k1_fe_mul(&x1, &x1n, &x3d); /* mag 1 */ + secp256k1_fe_mul(&x1, &x1, &x3d); /* mag 1 */ secp256k1_fe_mul(&x1, &x1, &jinv); /* mag 1 */ - secp256k1_fe_mul(&x2, &x2n, &x3d); /* mag 1 */ - secp256k1_fe_mul(&x2, &x2, &jinv); /* mag 1 */ - secp256k1_fe_mul(&x3, &x3n, &wd); /* mag 1 */ + secp256k1_fe_add(&x1, &d); /* mag 2 */ + x2 = x1; /* mag 2 */ + secp256k1_fe_add_int(&x2, 1); /* mag 3 */ + secp256k1_fe_negate(&x2, &x2, 3); /* mag 4 */ + secp256k1_fe_sqr(&x3, &wd); /* mag 1 */ + secp256k1_fe_mul(&x3, &x3, &wd); /* mag 1 */ secp256k1_fe_mul(&x3, &x3, &jinv); /* mag 1 */ + secp256k1_fe_add_int(&x3, 1); /* mag 2 */ secp256k1_fe_sqr(&alphain, &x1); /* mag 1 */ secp256k1_fe_mul(&alphain, &alphain, &x1); /* mag 1 */ - secp256k1_fe_add(&alphain, &b); /* mag 2 */ + secp256k1_fe_add_int(&alphain, SECP256K1_B); /* mag 2 */ secp256k1_fe_sqr(&betain, &x2); /* mag 1 */ secp256k1_fe_mul(&betain, &betain, &x2); /* mag 1 */ - secp256k1_fe_add(&betain, &b); /* mag 2 */ + secp256k1_fe_add_int(&betain, SECP256K1_B); /* mag 2 */ secp256k1_fe_sqr(&gammain, &x3); /* mag 1 */ secp256k1_fe_mul(&gammain, &gammain, &x3); /* mag 1 */ - secp256k1_fe_add(&gammain, &b); /* mag 2 */ + secp256k1_fe_add_int(&gammain, SECP256K1_B); /* mag 2 */ alphaquad = secp256k1_fe_sqrt(&y1, &alphain); betaquad = secp256k1_fe_sqrt(&y2, &betain); From 26522241b407a04825442dea839af82d97372daf Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 19 Jan 2024 19:47:21 +0000 Subject: [PATCH 2/3] generators: shallue_van_de_woestijne improve comments --- src/modules/generator/main_impl.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index 2804a691..28536694 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -111,10 +111,20 @@ static void shallue_van_de_woestijne(secp256k1_ge* ge, const secp256k1_fe* t) { wd = 1 + b + t^2 x3d = c^2 * t^2 = -3 * t^2 - so that + so that if j != 0, then 1 / wd = 1/j * x3d 1 / x3d = 1/j * wd + + x1 = d - c * t^2 * x3d / j + x3 = 1 + wd^3 / j + + If j = 0, the function outputs the point (d, f(d)). This point is equal + to (x1, f(x1)) as defined above if division by 0 is defined to be 0. In + below code this is not special-cased because secp256k1_fe_inv returns 0 + on input 0. + + j = 0 happens only when t = 0 (since wd != 0 as -8 is not a square). */ static const secp256k1_fe negc = SECP256K1_FE_CONST(0xf5d2d456, 0xcaf80e20, 0xdcc88f3d, 0x586869d3, 0x39e092ea, 0x25eb132b, 0x8272d850, 0xe32a03dd); @@ -123,23 +133,41 @@ static void shallue_van_de_woestijne(secp256k1_ge* ge, const secp256k1_fe* t) { secp256k1_fe wd, x3d, jinv, tmp, x1, x2, x3, alphain, betain, gammain, y1, y2, y3; int alphaquad, betaquad; + /* wd = t^2 */ secp256k1_fe_sqr(&wd, t); /* mag 1 */ + /* x1 = -c * t^2 */ secp256k1_fe_mul(&x1, &negc, &wd); /* mag 1 */ + /* x3d = t^2 */ x3d = wd; /* mag 1 */ + /* x3d = 3 * t^2 */ secp256k1_fe_mul_int(&x3d, 3); /* mag 3 */ + /* x3d = -3 * t^2 */ secp256k1_fe_negate(&x3d, &x3d, 3); /* mag 4 */ + /* wd = 1 + b + t^2 */ secp256k1_fe_add_int(&wd, SECP256K1_B + 1); /* mag 2 */ + /* jinv = wd * x3d */ secp256k1_fe_mul(&jinv, &wd, &x3d); /* mag 1 */ + /* jinv = 1/(wd * x3d) */ secp256k1_fe_inv(&jinv, &jinv); /* mag 1 */ + /* x1 = -c * t^2 * x3d */ secp256k1_fe_mul(&x1, &x1, &x3d); /* mag 1 */ + /* x1 = -c * t^2 * x3d * 1/j */ secp256k1_fe_mul(&x1, &x1, &jinv); /* mag 1 */ + /* x1 = d + -c * t^2 * x3d * 1/j */ secp256k1_fe_add(&x1, &d); /* mag 2 */ + /* x2 = x1 */ x2 = x1; /* mag 2 */ + /* x2 = x1 + 1 */ secp256k1_fe_add_int(&x2, 1); /* mag 3 */ + /* x2 = - (x1 + 1) */ secp256k1_fe_negate(&x2, &x2, 3); /* mag 4 */ + /* x3 = wd^2 */ secp256k1_fe_sqr(&x3, &wd); /* mag 1 */ + /* x3 = wd^3 */ secp256k1_fe_mul(&x3, &x3, &wd); /* mag 1 */ + /* x3 = wd^3 * 1/j */ secp256k1_fe_mul(&x3, &x3, &jinv); /* mag 1 */ + /* x3 = 1 + (wd^3 * 1/j) */ secp256k1_fe_add_int(&x3, 1); /* mag 2 */ secp256k1_fe_sqr(&alphain, &x1); /* mag 1 */ From 6b9d335ef641b77884fdb0e65f95c5ac4dd2209f Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 19 Jan 2024 20:05:10 +0000 Subject: [PATCH 3/3] generator: add shallue_van_de_woestijne test for t = 0 --- src/modules/generator/tests_impl.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/generator/tests_impl.h b/src/modules/generator/tests_impl.h index 2b8d0bcc..14a993b9 100644 --- a/src/modules/generator/tests_impl.h +++ b/src/modules/generator/tests_impl.h @@ -48,7 +48,9 @@ static void test_generator_api(void) { static void test_shallue_van_de_woestijne(void) { /* Matches with the output of the shallue_van_de_woestijne.sage SAGE program */ - static const secp256k1_ge_storage results[32] = { + static const secp256k1_ge_storage results[34] = { + SECP256K1_GE_STORAGE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40, 0x4218f20a, 0xe6c646b3, 0x63db6860, 0x5822fb14, 0x264ca8d2, 0x587fdd6f, 0xbc750d58, 0x7e76a7ee), + SECP256K1_GE_STORAGE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40, 0x4218f20a, 0xe6c646b3, 0x63db6860, 0x5822fb14, 0x264ca8d2, 0x587fdd6f, 0xbc750d58, 0x7e76a7ee), SECP256K1_GE_STORAGE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c, 0x0225f529, 0xee75acaf, 0xccfc4560, 0x26c5e46b, 0xf80237a3, 0x3924655a, 0x16f90e88, 0x085ed52a), SECP256K1_GE_STORAGE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c, 0xfdda0ad6, 0x118a5350, 0x3303ba9f, 0xd93a1b94, 0x07fdc85c, 0xc6db9aa5, 0xe906f176, 0xf7a12705), SECP256K1_GE_STORAGE_CONST(0x2c5cdc9c, 0x338152fa, 0x85de92cb, 0x1bee9907, 0x765a922e, 0x4f037cce, 0x14ecdbf2, 0x2f78fe15, 0x56716069, 0x6818286b, 0x72f01a3e, 0x5e8caca7, 0x36249160, 0xc7ded69d, 0xd51913c3, 0x03a2fa97), @@ -87,7 +89,7 @@ static void test_shallue_van_de_woestijne(void) { secp256k1_fe fe; secp256k1_ge_storage ges; int i, s; - for (i = 1; i <= 16; i++) { + for (i = 0; i <= 16; i++) { secp256k1_fe_set_int(&fe, i); for (s = 0; s < 2; s++) { @@ -96,9 +98,9 @@ static void test_shallue_van_de_woestijne(void) { secp256k1_fe_normalize(&fe); } shallue_van_de_woestijne(&ge, &fe); + CHECK(secp256k1_ge_is_valid_var(&ge)); secp256k1_ge_to_storage(&ges, &ge); - - CHECK(secp256k1_memcmp_var(&ges, &results[i * 2 + s - 2], sizeof(secp256k1_ge_storage)) == 0); + CHECK(secp256k1_memcmp_var(&ges, &results[i * 2 + s], sizeof(secp256k1_ge_storage)) == 0); } } }