Skip to content

Commit

Permalink
group: add ge_to_bytes and ge_from_bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasnick committed Jan 6, 2024
1 parent f6d9a11 commit ecbbd24
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 28 deletions.
7 changes: 7 additions & 0 deletions src/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);

/** Convert a group element into a 64-byte array */
static void secp256k1_ge_to_bytes(unsigned char *buf, secp256k1_ge *ge);

/** Convert a 64-byte array into group element. This function assumes that the
* provided buffer correctly encodes a group element. */
static void secp256k1_ge_from_bytes(secp256k1_ge *ge, const unsigned char *buf);

/** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve.
*
* In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the
Expand Down
36 changes: 36 additions & 0 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef SECP256K1_GROUP_IMPL_H
#define SECP256K1_GROUP_IMPL_H

#include <string.h>

#include "field.h"
#include "group.h"
#include "util.h"
Expand Down Expand Up @@ -941,4 +943,38 @@ static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp25
return secp256k1_fe_is_square_var(&r);
}

static void secp256k1_ge_to_bytes(unsigned char *buf, secp256k1_ge *ge) {
if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge);
memcpy(&buf[0], &s, sizeof(s));
} else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(buf, &ge->x);
secp256k1_fe_get_b32(buf + 32, &ge->y);
}
}

static void secp256k1_ge_from_bytes(secp256k1_ge *ge, const unsigned char *buf) {
if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation inside secp256k1_pubkey, as conversion is very fast.
* Note that secp256k1_pubkey_save must use the same representation. */
secp256k1_ge_storage s;
memcpy(&s, &buf[0], sizeof(s));
secp256k1_ge_from_storage(ge, &s);
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
int ret = 1;

ret &= secp256k1_fe_set_b32_limit(&x, buf);
ret &= secp256k1_fe_set_b32_limit(&y, buf + 32);
VERIFY_CHECK(ret);
secp256k1_ge_set_xy(ge, &x, &y);
}
}

#endif /* SECP256K1_GROUP_IMPL_H */
30 changes: 2 additions & 28 deletions src/secp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,39 +237,13 @@ static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx,
}

static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation inside secp256k1_pubkey, as conversion is very fast.
* Note that secp256k1_pubkey_save must use the same representation. */
secp256k1_ge_storage s;
memcpy(&s, &pubkey->data[0], sizeof(s));
secp256k1_ge_from_storage(ge, &s);
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
int ret = 1;

ret &= secp256k1_fe_set_b32_limit(&x, pubkey->data);
ret &= secp256k1_fe_set_b32_limit(&y, pubkey->data + 32);
VERIFY_CHECK(ret);
secp256k1_ge_set_xy(ge, &x, &y);
}
secp256k1_ge_from_bytes(ge, pubkey->data);
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));
return 1;
}

static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge);
memcpy(&pubkey->data[0], &s, sizeof(s));
} else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(pubkey->data, &ge->x);
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
}
secp256k1_ge_to_bytes(pubkey->data, ge);
}

int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) {
Expand Down
20 changes: 20 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -4016,13 +4016,33 @@ static void test_add_neg_y_diff_x(void) {
CHECK(secp256k1_gej_eq_ge_var(&sumj, &res));
}

static void test_ge_bytes(void) {
unsigned char buf[64];
unsigned char expected_buf[64] = {
0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59,
0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02,
0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55,
0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79,
0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C,
0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD,
0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D,
0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48,
};
secp256k1_ge p, g = secp256k1_ge_const_g;
secp256k1_ge_to_bytes(buf, &g);
CHECK(memcmp(buf, expected_buf, sizeof(buf)) == 0);
secp256k1_ge_from_bytes(&p, buf);
CHECK(secp256k1_ge_eq_var(&p, &g));
}

static void run_ge(void) {
int i;
for (i = 0; i < COUNT * 32; i++) {
test_ge();
}
test_add_neg_y_diff_x();
test_intialized_inf();
test_ge_bytes();
}

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

0 comments on commit ecbbd24

Please sign in to comment.