Skip to content

Commit ecbbd24

Browse files
committed
group: add ge_to_bytes and ge_from_bytes
1 parent f6d9a11 commit ecbbd24

File tree

4 files changed

+65
-28
lines changed

4 files changed

+65
-28
lines changed

src/group.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g
174174
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
175175
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
176176

177+
/** Convert a group element into a 64-byte array */
178+
static void secp256k1_ge_to_bytes(unsigned char *buf, secp256k1_ge *ge);
179+
180+
/** Convert a 64-byte array into group element. This function assumes that the
181+
* provided buffer correctly encodes a group element. */
182+
static void secp256k1_ge_from_bytes(secp256k1_ge *ge, const unsigned char *buf);
183+
177184
/** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve.
178185
*
179186
* In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the

src/group_impl.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#ifndef SECP256K1_GROUP_IMPL_H
88
#define SECP256K1_GROUP_IMPL_H
99

10+
#include <string.h>
11+
1012
#include "field.h"
1113
#include "group.h"
1214
#include "util.h"
@@ -941,4 +943,38 @@ static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp25
941943
return secp256k1_fe_is_square_var(&r);
942944
}
943945

946+
static void secp256k1_ge_to_bytes(unsigned char *buf, secp256k1_ge *ge) {
947+
if (sizeof(secp256k1_ge_storage) == 64) {
948+
secp256k1_ge_storage s;
949+
secp256k1_ge_to_storage(&s, ge);
950+
memcpy(&buf[0], &s, sizeof(s));
951+
} else {
952+
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
953+
secp256k1_fe_normalize_var(&ge->x);
954+
secp256k1_fe_normalize_var(&ge->y);
955+
secp256k1_fe_get_b32(buf, &ge->x);
956+
secp256k1_fe_get_b32(buf + 32, &ge->y);
957+
}
958+
}
959+
960+
static void secp256k1_ge_from_bytes(secp256k1_ge *ge, const unsigned char *buf) {
961+
if (sizeof(secp256k1_ge_storage) == 64) {
962+
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
963+
* representation inside secp256k1_pubkey, as conversion is very fast.
964+
* Note that secp256k1_pubkey_save must use the same representation. */
965+
secp256k1_ge_storage s;
966+
memcpy(&s, &buf[0], sizeof(s));
967+
secp256k1_ge_from_storage(ge, &s);
968+
} else {
969+
/* Otherwise, fall back to 32-byte big endian for X and Y. */
970+
secp256k1_fe x, y;
971+
int ret = 1;
972+
973+
ret &= secp256k1_fe_set_b32_limit(&x, buf);
974+
ret &= secp256k1_fe_set_b32_limit(&y, buf + 32);
975+
VERIFY_CHECK(ret);
976+
secp256k1_ge_set_xy(ge, &x, &y);
977+
}
978+
}
979+
944980
#endif /* SECP256K1_GROUP_IMPL_H */

src/secp256k1.c

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -237,39 +237,13 @@ static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx,
237237
}
238238

239239
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
240-
if (sizeof(secp256k1_ge_storage) == 64) {
241-
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
242-
* representation inside secp256k1_pubkey, as conversion is very fast.
243-
* Note that secp256k1_pubkey_save must use the same representation. */
244-
secp256k1_ge_storage s;
245-
memcpy(&s, &pubkey->data[0], sizeof(s));
246-
secp256k1_ge_from_storage(ge, &s);
247-
} else {
248-
/* Otherwise, fall back to 32-byte big endian for X and Y. */
249-
secp256k1_fe x, y;
250-
int ret = 1;
251-
252-
ret &= secp256k1_fe_set_b32_limit(&x, pubkey->data);
253-
ret &= secp256k1_fe_set_b32_limit(&y, pubkey->data + 32);
254-
VERIFY_CHECK(ret);
255-
secp256k1_ge_set_xy(ge, &x, &y);
256-
}
240+
secp256k1_ge_from_bytes(ge, pubkey->data);
257241
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
258242
return 1;
259243
}
260244

261245
static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
262-
if (sizeof(secp256k1_ge_storage) == 64) {
263-
secp256k1_ge_storage s;
264-
secp256k1_ge_to_storage(&s, ge);
265-
memcpy(&pubkey->data[0], &s, sizeof(s));
266-
} else {
267-
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
268-
secp256k1_fe_normalize_var(&ge->x);
269-
secp256k1_fe_normalize_var(&ge->y);
270-
secp256k1_fe_get_b32(pubkey->data, &ge->x);
271-
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
272-
}
246+
secp256k1_ge_to_bytes(pubkey->data, ge);
273247
}
274248

275249
int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) {

src/tests.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4016,13 +4016,33 @@ static void test_add_neg_y_diff_x(void) {
40164016
CHECK(secp256k1_gej_eq_ge_var(&sumj, &res));
40174017
}
40184018

4019+
static void test_ge_bytes(void) {
4020+
unsigned char buf[64];
4021+
unsigned char expected_buf[64] = {
4022+
0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59,
4023+
0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02,
4024+
0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55,
4025+
0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79,
4026+
0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C,
4027+
0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD,
4028+
0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D,
4029+
0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48,
4030+
};
4031+
secp256k1_ge p, g = secp256k1_ge_const_g;
4032+
secp256k1_ge_to_bytes(buf, &g);
4033+
CHECK(memcmp(buf, expected_buf, sizeof(buf)) == 0);
4034+
secp256k1_ge_from_bytes(&p, buf);
4035+
CHECK(secp256k1_ge_eq_var(&p, &g));
4036+
}
4037+
40194038
static void run_ge(void) {
40204039
int i;
40214040
for (i = 0; i < COUNT * 32; i++) {
40224041
test_ge();
40234042
}
40244043
test_add_neg_y_diff_x();
40254044
test_intialized_inf();
4045+
test_ge_bytes();
40264046
}
40274047

40284048
static void test_gej_cmov(const secp256k1_gej *a, const secp256k1_gej *b) {

0 commit comments

Comments
 (0)