mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-09 10:43:19 -05:00
Merge pull request #9 from sipa/cify
Second step in converting to C: field
This commit is contained in:
commit
f6ec29d956
9 changed files with 558 additions and 545 deletions
10
bench.cpp
10
bench.cpp
|
@ -9,15 +9,17 @@
|
|||
using namespace secp256k1;
|
||||
|
||||
int main() {
|
||||
FieldElem x;
|
||||
secp256k1_num_start();
|
||||
secp256k1_fe_start();
|
||||
|
||||
secp256k1_fe_t x;
|
||||
const secp256k1_num_t &order = GetGroupConst().order;
|
||||
secp256k1_num_t r, s, m;
|
||||
secp256k1_num_start();
|
||||
secp256k1_num_init(&r);
|
||||
secp256k1_num_init(&s);
|
||||
secp256k1_num_init(&m);
|
||||
Signature sig;
|
||||
x.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||
secp256k1_fe_set_hex(&x, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
|
||||
int cnt = 0;
|
||||
int good = 0;
|
||||
for (int i=0; i<1000000; i++) {
|
||||
|
@ -35,5 +37,7 @@ int main() {
|
|||
secp256k1_num_free(&r);
|
||||
secp256k1_num_free(&s);
|
||||
secp256k1_num_free(&m);
|
||||
|
||||
secp256k1_fe_stop();
|
||||
return 0;
|
||||
}
|
||||
|
|
24
ecdsa.cpp
24
ecdsa.cpp
|
@ -8,15 +8,15 @@ namespace secp256k1 {
|
|||
|
||||
bool ParsePubKey(GroupElemJac &elem, const unsigned char *pub, int size) {
|
||||
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
|
||||
FieldElem x;
|
||||
x.SetBytes(pub+1);
|
||||
secp256k1_fe_t x;
|
||||
secp256k1_fe_set_b32(&x, pub+1);
|
||||
elem.SetCompressed(x, pub[0] == 0x03);
|
||||
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
|
||||
FieldElem x,y;
|
||||
x.SetBytes(pub+1);
|
||||
y.SetBytes(pub+33);
|
||||
secp256k1_fe_t x,y;
|
||||
secp256k1_fe_set_b32(&x, pub+1);
|
||||
secp256k1_fe_set_b32(&y, pub+33);
|
||||
elem = GroupElem(x,y);
|
||||
if ((pub[0] == 0x06 || pub[0] == 0x07) && y.IsOdd() != (pub[0] == 0x07))
|
||||
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07))
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -81,9 +81,9 @@ bool Signature::RecomputeR(secp256k1_num_t &r2, const GroupElemJac &pubkey, cons
|
|||
secp256k1_num_mod_mul(&u2, &sn, &r, &c.order);
|
||||
GroupElemJac pr; ECMult(pr, pubkey, u2, u1);
|
||||
if (!pr.IsInfinity()) {
|
||||
FieldElem xr; pr.GetX(xr);
|
||||
xr.Normalize();
|
||||
unsigned char xrb[32]; xr.GetBytes(xrb);
|
||||
secp256k1_fe_t xr; pr.GetX(xr);
|
||||
secp256k1_fe_normalize(&xr);
|
||||
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
|
||||
secp256k1_num_set_bin(&r2, xrb, 32);
|
||||
secp256k1_num_mod(&r2, &r2, &c.order);
|
||||
ret = true;
|
||||
|
@ -108,11 +108,11 @@ bool Signature::Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &messa
|
|||
|
||||
GroupElemJac rp;
|
||||
ECMultBase(rp, nonce);
|
||||
FieldElem rx;
|
||||
secp256k1_fe_t rx;
|
||||
rp.GetX(rx);
|
||||
unsigned char b[32];
|
||||
rx.Normalize();
|
||||
rx.GetBytes(b);
|
||||
secp256k1_fe_normalize(&rx);
|
||||
secp256k1_fe_get_b32(b, &rx);
|
||||
secp256k1_num_set_bin(&r, b, 32);
|
||||
secp256k1_num_mod(&r, &r, &c.order);
|
||||
secp256k1_num_t n;
|
||||
|
|
154
field.cpp
154
field.cpp
|
@ -1,25 +1,151 @@
|
|||
// just one implementation for now
|
||||
#include "field_5x52.cpp"
|
||||
|
||||
namespace secp256k1 {
|
||||
static const unsigned char secp256k1_fe_consts_p[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
|
||||
static const unsigned char field_p_[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F};
|
||||
|
||||
FieldConstants::FieldConstants() {
|
||||
secp256k1_num_init(&field_p);
|
||||
secp256k1_num_set_bin(&field_p, field_p_, sizeof(field_p_));
|
||||
void static secp256k1_fe_start(void) {
|
||||
if (secp256k1_fe_consts == NULL) {
|
||||
secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_t));
|
||||
secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p));
|
||||
secp256k1_fe_consts = ret;
|
||||
}
|
||||
}
|
||||
|
||||
FieldConstants::~FieldConstants() {
|
||||
secp256k1_num_free(&field_p);
|
||||
void static secp256k1_fe_stop(void) {
|
||||
if (secp256k1_fe_consts != NULL) {
|
||||
free((void*)secp256k1_fe_consts);
|
||||
secp256k1_fe_consts = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const FieldConstants &GetFieldConst() {
|
||||
static const FieldConstants field_const;
|
||||
return field_const;
|
||||
void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) {
|
||||
if (*rlen < 65) {
|
||||
*rlen = 65;
|
||||
return;
|
||||
}
|
||||
*rlen = 65;
|
||||
unsigned char tmp[32];
|
||||
secp256k1_fe_t b = *a;
|
||||
secp256k1_fe_normalize(&b);
|
||||
secp256k1_fe_get_b32(tmp, &b);
|
||||
for (int i=0; i<32; i++) {
|
||||
static const char *c = "0123456789ABCDEF";
|
||||
r[2*i] = c[(tmp[i] >> 4) & 0xF];
|
||||
r[2*i+1] = c[(tmp[i]) & 0xF];
|
||||
}
|
||||
r[64] = 0x00;
|
||||
}
|
||||
|
||||
void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
|
||||
unsigned char tmp[32] = {};
|
||||
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
|
||||
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0};
|
||||
for (int i=0; i<32; i++) {
|
||||
if (alen > i*2)
|
||||
tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]];
|
||||
}
|
||||
secp256k1_fe_set_b32(r, tmp);
|
||||
}
|
||||
|
||||
void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
|
||||
// calculate a^p, with p={15,780,1022,1023}
|
||||
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
|
||||
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
|
||||
secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3);
|
||||
secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6);
|
||||
secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3);
|
||||
secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15);
|
||||
secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30);
|
||||
secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60);
|
||||
secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120);
|
||||
secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15);
|
||||
secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255);
|
||||
secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240);
|
||||
secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30);
|
||||
secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510);
|
||||
secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2);
|
||||
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a);
|
||||
secp256k1_fe_t x = a15;
|
||||
for (int i=0; i<21; i++) {
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1022);
|
||||
for (int i=0; i<2; i++) {
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(r, &x, &a780);
|
||||
}
|
||||
|
||||
void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
|
||||
// calculate a^p, with p={45,63,1019,1023}
|
||||
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
|
||||
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
|
||||
secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2);
|
||||
secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a);
|
||||
secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5);
|
||||
secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a);
|
||||
secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10);
|
||||
secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21);
|
||||
secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3);
|
||||
secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21);
|
||||
secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63);
|
||||
secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126);
|
||||
secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252);
|
||||
secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504);
|
||||
secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11);
|
||||
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4);
|
||||
secp256k1_fe_t x = a63;
|
||||
for (int i=0; i<21; i++) {
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1019);
|
||||
for (int i=0; i<2; i++) {
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(&x, &x, &a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
|
||||
secp256k1_fe_mul(r, &x, &a45);
|
||||
}
|
||||
|
||||
void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
|
||||
#if defined(USE_FIELDINVERSE_BUILTIN)
|
||||
secp256k1_fe_inv(r, a);
|
||||
#else
|
||||
unsigned char b[32];
|
||||
secp256k1_fe_t c = *a;
|
||||
secp256k1_fe_normalize(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
secp256k1_num_free(&n);
|
||||
secp256k1_fe_set_b32(&c, b);
|
||||
#endif
|
||||
}
|
||||
|
|
85
field.h
85
field.h
|
@ -1,21 +1,88 @@
|
|||
#ifndef _SECP256K1_FIELD_
|
||||
#define _SECP256K1_FIELD_
|
||||
|
||||
/** Field element module.
|
||||
*
|
||||
* Field elements can be represented in several ways, but code accessing
|
||||
* it (and implementations) need to take certain properaties into account:
|
||||
* - Each field element can be normalized or not.
|
||||
* - Each field element has a magnitude, which represents how far away
|
||||
* its representation is away from normalization. Normalized elements
|
||||
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||||
* normality.
|
||||
*/
|
||||
|
||||
// just one implementation for now
|
||||
#include "field_5x52.h"
|
||||
|
||||
namespace secp256k1 {
|
||||
typedef struct {
|
||||
secp256k1_num_t p;
|
||||
} secp256k1_fe_consts_t;
|
||||
|
||||
class FieldConstants {
|
||||
public:
|
||||
secp256k1_num_t field_p;
|
||||
static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL;
|
||||
|
||||
FieldConstants();
|
||||
~FieldConstants();
|
||||
};
|
||||
/** Initialize field element precomputation data. */
|
||||
void static secp256k1_fe_start(void);
|
||||
|
||||
const FieldConstants &GetFieldConst();
|
||||
/** Unload field element precomputation data. */
|
||||
void static secp256k1_fe_stop(void);
|
||||
|
||||
}
|
||||
/** Normalize a field element. */
|
||||
void static secp256k1_fe_normalize(secp256k1_fe_t *r);
|
||||
|
||||
/** Set a field element equal to a small integer. Resulting field element is normalized. */
|
||||
void static secp256k1_fe_set_int(secp256k1_fe_t *r, int a);
|
||||
|
||||
/** Verify whether a field element is zero. Requires the input to be normalized. */
|
||||
int static secp256k1_fe_is_zero(const secp256k1_fe_t *a);
|
||||
|
||||
/** Check the "oddness" of a field element. Requires the input to be normalized. */
|
||||
int static secp256k1_fe_is_odd(const secp256k1_fe_t *a);
|
||||
|
||||
/** Compare two field elements. Requires both inputs to be normalized */
|
||||
int static secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
|
||||
|
||||
/** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */
|
||||
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a);
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a);
|
||||
|
||||
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
|
||||
* as an argument. The magnitude of the output is one higher. */
|
||||
void static secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m);
|
||||
|
||||
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
|
||||
* small integer. */
|
||||
void static secp256k1_fe_mul_int(secp256k1_fe_t *r, int a);
|
||||
|
||||
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
|
||||
void static secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a);
|
||||
|
||||
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b);
|
||||
|
||||
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a);
|
||||
|
||||
/** Sets a field element to be the (modular) square root of another. Requires the inputs' magnitude to
|
||||
* be at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a);
|
||||
|
||||
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
|
||||
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a);
|
||||
|
||||
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
|
||||
void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a);
|
||||
|
||||
|
||||
/** Convert a field element to a hexadecimal string. */
|
||||
void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a);
|
||||
|
||||
/** Convert a hexadecimal string to a field element. */
|
||||
void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
|
||||
|
||||
#endif
|
||||
|
|
453
field_5x52.cpp
453
field_5x52.cpp
|
@ -1,18 +1,12 @@
|
|||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef INLINE_ASM
|
||||
#include "lin64.h"
|
||||
#endif
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
||||
* represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular,
|
||||
* each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
|
||||
|
@ -21,30 +15,17 @@ namespace secp256k1 {
|
|||
* output.
|
||||
*/
|
||||
|
||||
FieldElem::FieldElem(int x) {
|
||||
n[0] = x;
|
||||
n[1] = n[2] = n[3] = n[4] = 0;
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude = 1;
|
||||
normalized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
FieldElem::FieldElem(const unsigned char *b32) {
|
||||
SetBytes(b32);
|
||||
}
|
||||
|
||||
void FieldElem::Normalize() {
|
||||
void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
|
||||
uint64_t c;
|
||||
c = n[0];
|
||||
c = r->n[0];
|
||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
|
||||
c = (c >> 52) + n[1];
|
||||
c = (c >> 52) + r->n[1];
|
||||
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL;
|
||||
c = (c >> 52) + n[2];
|
||||
c = (c >> 52) + r->n[2];
|
||||
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL;
|
||||
c = (c >> 52) + n[3];
|
||||
c = (c >> 52) + r->n[3];
|
||||
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL;
|
||||
c = (c >> 52) + n[4];
|
||||
c = (c >> 52) + r->n[4];
|
||||
uint64_t t4 = c & 0x0FFFFFFFFFFFFULL;
|
||||
c >>= 48;
|
||||
|
||||
|
@ -60,149 +41,166 @@ void FieldElem::Normalize() {
|
|||
c = (c >> 52) + t4;
|
||||
t4 = c & 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
// Replace n's with t's if one of the n's overflows.
|
||||
// If none of the n's overflow to begin with, the t's will just be the n's already and
|
||||
// we effectively ignore the results of the previous computations.
|
||||
n[0] = t0; n[1] = t1; n[2] = t2; n[3] = t3; n[4] = t4;
|
||||
|
||||
// Subtract p if result >= p
|
||||
uint64_t mask = -(int64_t)((n[4] < 0xFFFFFFFFFFFFULL) | (n[3] < 0xFFFFFFFFFFFFFULL) | (n[2] < 0xFFFFFFFFFFFFFULL) | (n[1] < 0xFFFFFFFFFFFFFULL) | (n[0] < 0xFFFFEFFFFFC2FULL));
|
||||
n[4] &= mask;
|
||||
n[3] &= mask;
|
||||
n[2] &= mask;
|
||||
n[1] &= mask;
|
||||
n[0] -= (~mask & 0xFFFFEFFFFFC2FULL);
|
||||
uint64_t mask = -(int64_t)((t4 < 0xFFFFFFFFFFFFULL) | (t3 < 0xFFFFFFFFFFFFFULL) | (t2 < 0xFFFFFFFFFFFFFULL) | (t1 < 0xFFFFFFFFFFFFFULL) | (t0 < 0xFFFFEFFFFFC2FULL));
|
||||
t4 &= mask;
|
||||
t3 &= mask;
|
||||
t2 &= mask;
|
||||
t1 &= mask;
|
||||
t0 -= (~mask & 0xFFFFEFFFFFC2FULL);
|
||||
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude = 1;
|
||||
normalized = true;
|
||||
// push internal variables back
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool inline FieldElem::IsZero() const {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(normalized);
|
||||
void static secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
|
||||
r->n[0] = a;
|
||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
#endif
|
||||
return (n[0] == 0 && n[1] == 0 && n[2] == 0 && n[3] == 0 && n[4] == 0);
|
||||
}
|
||||
|
||||
bool inline operator==(const FieldElem &a, const FieldElem &b) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(a.normalized);
|
||||
assert(b.normalized);
|
||||
// TODO: not constant time!
|
||||
int static secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
|
||||
#ifdef VERIFY
|
||||
assert(a->normalized);
|
||||
#endif
|
||||
return (a.n[0] == b.n[0] && a.n[1] == b.n[1] && a.n[2] == b.n[2] && a.n[3] == b.n[3] && a.n[4] == b.n[4]);
|
||||
return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0);
|
||||
}
|
||||
|
||||
void FieldElem::GetBytes(unsigned char *o) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(normalized);
|
||||
int static secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
|
||||
#ifdef VERIFY
|
||||
assert(a->normalized);
|
||||
#endif
|
||||
return a->n[0] & 1;
|
||||
}
|
||||
|
||||
// TODO: not constant time!
|
||||
int static secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
||||
#ifdef VERIFY
|
||||
assert(a->normalized);
|
||||
assert(b->normalized);
|
||||
#endif
|
||||
return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4]);
|
||||
}
|
||||
|
||||
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
|
||||
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
for (int i=0; i<32; i++) {
|
||||
for (int j=0; j<2; j++) {
|
||||
int limb = (8*i+4*j)/52;
|
||||
int shift = (8*i+4*j)%52;
|
||||
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
|
||||
}
|
||||
}
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
|
||||
#ifdef VERIFY
|
||||
assert(a->normalized);
|
||||
#endif
|
||||
for (int i=0; i<32; i++) {
|
||||
int c = 0;
|
||||
for (int j=0; j<2; j++) {
|
||||
int limb = (8*i+4*j)/52;
|
||||
int shift = (8*i+4*j)%52;
|
||||
c |= ((n[limb] >> shift) & 0xF) << (4 * j);
|
||||
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);
|
||||
}
|
||||
o[31-i] = c;
|
||||
r[31-i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
void FieldElem::SetBytes(const unsigned char *in) {
|
||||
n[0] = n[1] = n[2] = n[3] = n[4] = 0;
|
||||
for (int i=0; i<32; i++) {
|
||||
for (int j=0; j<2; j++) {
|
||||
int limb = (8*i+4*j)/52;
|
||||
int shift = (8*i+4*j)%52;
|
||||
n[limb] |= (uint64_t)((in[31-i] >> (4*j)) & 0xF) << shift;
|
||||
}
|
||||
}
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude = 1;
|
||||
normalized = true;
|
||||
void static secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
|
||||
#ifdef VERIFY
|
||||
assert(a->magnitude <= m);
|
||||
r->magnitude = m + 1;
|
||||
r->normalized = 0;
|
||||
#endif
|
||||
r->n[0] = 0xFFFFEFFFFFC2FULL * (m + 1) - a->n[0];
|
||||
r->n[1] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[1];
|
||||
r->n[2] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[2];
|
||||
r->n[3] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[3];
|
||||
r->n[4] = 0x0FFFFFFFFFFFFULL * (m + 1) - a->n[4];
|
||||
}
|
||||
|
||||
void inline FieldElem::SetNeg(const FieldElem &a, int magnitudeIn) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(a.magnitude <= magnitudeIn);
|
||||
magnitude = magnitudeIn + 1;
|
||||
normalized = false;
|
||||
void static secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
|
||||
#ifdef VERIFY
|
||||
r->magnitude *= a;
|
||||
r->normalized = false;
|
||||
#endif
|
||||
n[0] = 0xFFFFEFFFFFC2FULL * (magnitudeIn + 1) - a.n[0];
|
||||
n[1] = 0xFFFFFFFFFFFFFULL * (magnitudeIn + 1) - a.n[1];
|
||||
n[2] = 0xFFFFFFFFFFFFFULL * (magnitudeIn + 1) - a.n[2];
|
||||
n[3] = 0xFFFFFFFFFFFFFULL * (magnitudeIn + 1) - a.n[3];
|
||||
n[4] = 0x0FFFFFFFFFFFFULL * (magnitudeIn + 1) - a.n[4];
|
||||
r->n[0] *= a;
|
||||
r->n[1] *= a;
|
||||
r->n[2] *= a;
|
||||
r->n[3] *= a;
|
||||
r->n[4] *= a;
|
||||
}
|
||||
|
||||
void inline FieldElem::operator*=(int v) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude *= v;
|
||||
normalized = false;
|
||||
void static secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
|
||||
#ifdef VERIFY
|
||||
r->magnitude += a->magnitude;
|
||||
r->normalized = 0;
|
||||
#endif
|
||||
n[0] *= v;
|
||||
n[1] *= v;
|
||||
n[2] *= v;
|
||||
n[3] *= v;
|
||||
n[4] *= v;
|
||||
r->n[0] += a->n[0];
|
||||
r->n[1] += a->n[1];
|
||||
r->n[2] += a->n[2];
|
||||
r->n[3] += a->n[3];
|
||||
r->n[4] += a->n[4];
|
||||
}
|
||||
|
||||
void inline FieldElem::operator+=(const FieldElem &a) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude += a.magnitude;
|
||||
normalized = false;
|
||||
#endif
|
||||
n[0] += a.n[0];
|
||||
n[1] += a.n[1];
|
||||
n[2] += a.n[2];
|
||||
n[3] += a.n[3];
|
||||
n[4] += a.n[4];
|
||||
}
|
||||
|
||||
void FieldElem::SetMult(const FieldElem &a, const FieldElem &b) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(a.magnitude <= 8);
|
||||
assert(b.magnitude <= 8);
|
||||
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
|
||||
#ifdef VERIFY
|
||||
assert(a->magnitude <= 8);
|
||||
assert(b->magnitude <= 8);
|
||||
#endif
|
||||
|
||||
#ifdef INLINE_ASM
|
||||
ExSetMult((uint64_t *) a.n,(uint64_t *) b.n, (uint64_t *) n);
|
||||
ExSetMult((uint64_t*)a->n, (uint64_t*)b->n, (uint64_t*)r->n);
|
||||
#else
|
||||
unsigned __int128 c = (__int128)a.n[0] * b.n[0];
|
||||
unsigned __int128 c = (__int128)a->n[0] * b->n[0];
|
||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
|
||||
c = c + (__int128)a.n[0] * b.n[1] +
|
||||
(__int128)a.n[1] * b.n[0];
|
||||
c = c + (__int128)a->n[0] * b->n[1] +
|
||||
(__int128)a->n[1] * b->n[0];
|
||||
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
|
||||
c = c + (__int128)a.n[0] * b.n[2] +
|
||||
(__int128)a.n[1] * b.n[1] +
|
||||
(__int128)a.n[2] * b.n[0];
|
||||
c = c + (__int128)a->n[0] * b->n[2] +
|
||||
(__int128)a->n[1] * b->n[1] +
|
||||
(__int128)a->n[2] * b->n[0];
|
||||
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
|
||||
c = c + (__int128)a.n[0] * b.n[3] +
|
||||
(__int128)a.n[1] * b.n[2] +
|
||||
(__int128)a.n[2] * b.n[1] +
|
||||
(__int128)a.n[3] * b.n[0];
|
||||
c = c + (__int128)a->n[0] * b->n[3] +
|
||||
(__int128)a->n[1] * b->n[2] +
|
||||
(__int128)a->n[2] * b->n[1] +
|
||||
(__int128)a->n[3] * b->n[0];
|
||||
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
|
||||
c = c + (__int128)a.n[0] * b.n[4] +
|
||||
(__int128)a.n[1] * b.n[3] +
|
||||
(__int128)a.n[2] * b.n[2] +
|
||||
(__int128)a.n[3] * b.n[1] +
|
||||
(__int128)a.n[4] * b.n[0];
|
||||
c = c + (__int128)a->n[0] * b->n[4] +
|
||||
(__int128)a->n[1] * b->n[3] +
|
||||
(__int128)a->n[2] * b->n[2] +
|
||||
(__int128)a->n[3] * b->n[1] +
|
||||
(__int128)a->n[4] * b->n[0];
|
||||
uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
|
||||
c = c + (__int128)a.n[1] * b.n[4] +
|
||||
(__int128)a.n[2] * b.n[3] +
|
||||
(__int128)a.n[3] * b.n[2] +
|
||||
(__int128)a.n[4] * b.n[1];
|
||||
c = c + (__int128)a->n[1] * b->n[4] +
|
||||
(__int128)a->n[2] * b->n[3] +
|
||||
(__int128)a->n[3] * b->n[2] +
|
||||
(__int128)a->n[4] * b->n[1];
|
||||
uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
|
||||
c = c + (__int128)a.n[2] * b.n[4] +
|
||||
(__int128)a.n[3] * b.n[3] +
|
||||
(__int128)a.n[4] * b.n[2];
|
||||
c = c + (__int128)a->n[2] * b->n[4] +
|
||||
(__int128)a->n[3] * b->n[3] +
|
||||
(__int128)a->n[4] * b->n[2];
|
||||
uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
|
||||
c = c + (__int128)a.n[3] * b.n[4] +
|
||||
(__int128)a.n[4] * b.n[3];
|
||||
c = c + (__int128)a->n[3] * b->n[4] +
|
||||
(__int128)a->n[4] * b->n[3];
|
||||
uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
|
||||
c = c + (__int128)a.n[4] * b.n[4];
|
||||
c = c + (__int128)a->n[4] * b->n[4];
|
||||
uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
|
||||
uint64_t t9 = c;
|
||||
|
||||
|
@ -211,52 +209,52 @@ void FieldElem::SetMult(const FieldElem &a, const FieldElem &b) {
|
|||
c = c + t1 + (__int128)t6 * 0x1000003D10ULL;
|
||||
t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t2 + (__int128)t7 * 0x1000003D10ULL;
|
||||
n[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
r->n[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t3 + (__int128)t8 * 0x1000003D10ULL;
|
||||
n[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
r->n[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t4 + (__int128)t9 * 0x1000003D10ULL;
|
||||
n[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
r->n[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
c = t0 + (__int128)c * 0x1000003D1ULL;
|
||||
n[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
n[1] = t1 + c;
|
||||
r->n[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
r->n[1] = t1 + c;
|
||||
#endif
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
magnitude = 1;
|
||||
normalized = false;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FieldElem::SetSquare(const FieldElem &a) {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(a.magnitude <= 8);
|
||||
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
|
||||
#ifdef VERIFY
|
||||
assert(a->magnitude <= 8);
|
||||
#endif
|
||||
|
||||
#ifdef INLINE_ASM
|
||||
ExSetSquare((uint64_t *)a.n,(uint64_t *)n);
|
||||
ExSetSquare((uint64_t*)&a->n, (uint64_t*)&r->n);
|
||||
#else
|
||||
__int128 c = (__int128)a.n[0] * a.n[0];
|
||||
__int128 c = (__int128)a->n[0] * a->n[0];
|
||||
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
|
||||
c = c + (__int128)(a.n[0]*2) * a.n[1];
|
||||
c = c + (__int128)(a->n[0]*2) * a->n[1];
|
||||
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
|
||||
c = c + (__int128)(a.n[0]*2) * a.n[2] +
|
||||
(__int128)a.n[1] * a.n[1];
|
||||
c = c + (__int128)(a->n[0]*2) * a->n[2] +
|
||||
(__int128)a->n[1] * a->n[1];
|
||||
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
|
||||
c = c + (__int128)(a.n[0]*2) * a.n[3] +
|
||||
(__int128)(a.n[1]*2) * a.n[2];
|
||||
c = c + (__int128)(a->n[0]*2) * a->n[3] +
|
||||
(__int128)(a->n[1]*2) * a->n[2];
|
||||
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
|
||||
c = c + (__int128)(a.n[0]*2) * a.n[4] +
|
||||
(__int128)(a.n[1]*2) * a.n[3] +
|
||||
(__int128)a.n[2] * a.n[2];
|
||||
c = c + (__int128)(a->n[0]*2) * a->n[4] +
|
||||
(__int128)(a->n[1]*2) * a->n[3] +
|
||||
(__int128)a->n[2] * a->n[2];
|
||||
uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
|
||||
c = c + (__int128)(a.n[1]*2) * a.n[4] +
|
||||
(__int128)(a.n[2]*2) * a.n[3];
|
||||
c = c + (__int128)(a->n[1]*2) * a->n[4] +
|
||||
(__int128)(a->n[2]*2) * a->n[3];
|
||||
uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
|
||||
c = c + (__int128)(a.n[2]*2) * a.n[4] +
|
||||
(__int128)a.n[3] * a.n[3];
|
||||
c = c + (__int128)(a->n[2]*2) * a->n[4] +
|
||||
(__int128)a->n[3] * a->n[3];
|
||||
uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
|
||||
c = c + (__int128)(a.n[3]*2) * a.n[4];
|
||||
c = c + (__int128)(a->n[3]*2) * a->n[4];
|
||||
uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
|
||||
c = c + (__int128)a.n[4] * a.n[4];
|
||||
c = c + (__int128)a->n[4] * a->n[4];
|
||||
uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
|
||||
uint64_t t9 = c;
|
||||
c = t0 + (__int128)t5 * 0x1000003D10ULL;
|
||||
|
@ -264,149 +262,18 @@ void FieldElem::SetSquare(const FieldElem &a) {
|
|||
c = c + t1 + (__int128)t6 * 0x1000003D10ULL;
|
||||
t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t2 + (__int128)t7 * 0x1000003D10ULL;
|
||||
n[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
r->n[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t3 + (__int128)t8 * 0x1000003D10ULL;
|
||||
n[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
r->n[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
c = c + t4 + (__int128)t9 * 0x1000003D10ULL;
|
||||
n[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
r->n[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
c = t0 + (__int128)c * 0x1000003D1ULL;
|
||||
n[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
n[1] = t1 + c;
|
||||
r->n[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
r->n[1] = t1 + c;
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(a.magnitude <= 8);
|
||||
normalized = false;
|
||||
#ifdef VERIFY
|
||||
assert(a->magnitude <= 8);
|
||||
a->normalized = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FieldElem::SetSquareRoot(const FieldElem &a) {
|
||||
// calculate a^p, with p={15,780,1022,1023}
|
||||
FieldElem a2; a2.SetSquare(a);
|
||||
FieldElem a3; a3.SetMult(a2,a);
|
||||
FieldElem a6; a6.SetSquare(a3);
|
||||
FieldElem a12; a12.SetSquare(a6);
|
||||
FieldElem a15; a15.SetMult(a12,a3);
|
||||
FieldElem a30; a30.SetSquare(a15);
|
||||
FieldElem a60; a60.SetSquare(a30);
|
||||
FieldElem a120; a120.SetSquare(a60);
|
||||
FieldElem a240; a240.SetSquare(a120);
|
||||
FieldElem a255; a255.SetMult(a240,a15);
|
||||
FieldElem a510; a510.SetSquare(a255);
|
||||
FieldElem a750; a750.SetMult(a510,a240);
|
||||
FieldElem a780; a780.SetMult(a750,a30);
|
||||
FieldElem a1020; a1020.SetSquare(a510);
|
||||
FieldElem a1022; a1022.SetMult(a1020,a2);
|
||||
FieldElem a1023; a1023.SetMult(a1022,a);
|
||||
FieldElem x = a15;
|
||||
for (int i=0; i<21; i++) {
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1022);
|
||||
for (int i=0; i<2; i++) {
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
SetMult(x,a780);
|
||||
}
|
||||
|
||||
bool FieldElem::IsOdd() const {
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
assert(normalized);
|
||||
#endif
|
||||
return n[0] & 1;
|
||||
}
|
||||
|
||||
std::string FieldElem::ToString() {
|
||||
unsigned char tmp[32];
|
||||
Normalize();
|
||||
GetBytes(tmp);
|
||||
std::string ret;
|
||||
for (int i=0; i<32; i++) {
|
||||
static const char *c = "0123456789ABCDEF";
|
||||
ret += c[(tmp[i] >> 4) & 0xF];
|
||||
ret += c[(tmp[i]) & 0xF];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FieldElem::SetHex(const std::string &str) {
|
||||
unsigned char tmp[32] = {};
|
||||
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
|
||||
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0};
|
||||
for (unsigned int i=0; i<32; i++) {
|
||||
if (str.length() > i*2)
|
||||
tmp[32 - str.length()/2 + i] = (cvt[(unsigned char)str[2*i]] << 4) + cvt[(unsigned char)str[2*i+1]];
|
||||
}
|
||||
SetBytes(tmp);
|
||||
}
|
||||
|
||||
|
||||
// Nonbuiltin Field Inverse is not constant time.
|
||||
void FieldElem::SetInverse(FieldElem &a) {
|
||||
#if defined(USE_FIELDINVERSE_BUILTIN)
|
||||
// calculate a^p, with p={45,63,1019,1023}
|
||||
FieldElem a2; a2.SetSquare(a);
|
||||
FieldElem a3; a3.SetMult(a2,a);
|
||||
FieldElem a4; a4.SetSquare(a2);
|
||||
FieldElem a5; a5.SetMult(a4,a);
|
||||
FieldElem a10; a10.SetSquare(a5);
|
||||
FieldElem a11; a11.SetMult(a10,a);
|
||||
FieldElem a21; a21.SetMult(a11,a10);
|
||||
FieldElem a42; a42.SetSquare(a21);
|
||||
FieldElem a45; a45.SetMult(a42,a3);
|
||||
FieldElem a63; a63.SetMult(a42,a21);
|
||||
FieldElem a126; a126.SetSquare(a63);
|
||||
FieldElem a252; a252.SetSquare(a126);
|
||||
FieldElem a504; a504.SetSquare(a252);
|
||||
FieldElem a1008; a1008.SetSquare(a504);
|
||||
FieldElem a1019; a1019.SetMult(a1008,a11);
|
||||
FieldElem a1023; a1023.SetMult(a1019,a4);
|
||||
FieldElem x = a63;
|
||||
for (int i=0; i<21; i++) {
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1019);
|
||||
for (int i=0; i<2; i++) {
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
x.SetMult(x,a1023);
|
||||
}
|
||||
for (int j=0; j<10; j++) x.SetSquare(x);
|
||||
SetMult(x,a45);
|
||||
#else
|
||||
unsigned char b[32];
|
||||
a.Normalize();
|
||||
a.GetBytes(b);
|
||||
{
|
||||
const secp256k1_num_t &p = GetFieldConst().field_p;
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &p);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
secp256k1_num_free(&n);
|
||||
}
|
||||
SetBytes(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
73
field_5x52.h
73
field_5x52.h
|
@ -1,80 +1,15 @@
|
|||
#ifndef _SECP256K1_FIELD_5x52_
|
||||
#define _SECP256K1_FIELD_5x52_
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include "num.h"
|
||||
|
||||
// #define VERIFY_MAGNITUDE 1
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
||||
* represented as 5 uint64_t's in base 2^52. he values are allowed to contain >52 each. In particular,
|
||||
* each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
|
||||
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
|
||||
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their
|
||||
* output.
|
||||
*/
|
||||
class FieldElem {
|
||||
private:
|
||||
typedef struct {
|
||||
// X = sum(i=0..4, elem[i]*2^52) mod n
|
||||
uint64_t n[5];
|
||||
#ifdef VERIFY_MAGNITUDE
|
||||
#ifdef VERIFY
|
||||
int magnitude;
|
||||
bool normalized;
|
||||
int normalized;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
/** Creates a constant field element. Magnitude=1 */
|
||||
FieldElem(int x = 0);
|
||||
|
||||
FieldElem(const unsigned char *b32);
|
||||
|
||||
/** Normalizes the internal representation entries. Magnitude=1 */
|
||||
void Normalize();
|
||||
|
||||
bool IsZero() const;
|
||||
|
||||
bool friend operator==(const FieldElem &a, const FieldElem &b);
|
||||
|
||||
/** extract as 32-byte big endian array */
|
||||
void GetBytes(unsigned char *o);
|
||||
|
||||
/** set value of 32-byte big endian array */
|
||||
void SetBytes(const unsigned char *in);
|
||||
|
||||
/** Set a FieldElem to be the negative of another. Increases magnitude by one. */
|
||||
void SetNeg(const FieldElem &a, int magnitudeIn);
|
||||
|
||||
/** Multiplies this FieldElem with an integer constant. Magnitude is multiplied by v */
|
||||
void operator*=(int v);
|
||||
|
||||
void operator+=(const FieldElem &a);
|
||||
|
||||
/** Set this FieldElem to be the multiplication of two others. Magnitude=1 (variable time) */
|
||||
void SetMult(const FieldElem &a, const FieldElem &b);
|
||||
|
||||
/** Set this FieldElem to be the square of another. Magnitude=1 (variable time) */
|
||||
void SetSquare(const FieldElem &a);
|
||||
|
||||
/** Set this to be the (modular) square root of another FieldElem. Magnitude=1 */
|
||||
void SetSquareRoot(const FieldElem &a);
|
||||
|
||||
bool IsOdd() const;
|
||||
|
||||
/** Set this to be the (modular) inverse of another FieldElem. Magnitude=1 (variable time) */
|
||||
void SetInverse(FieldElem &a);
|
||||
|
||||
std::string ToString();
|
||||
|
||||
void SetHex(const std::string &str);
|
||||
};
|
||||
|
||||
}
|
||||
} secp256k1_fe_t;
|
||||
|
||||
#endif
|
||||
|
|
261
group.cpp
261
group.cpp
|
@ -10,7 +10,7 @@ GroupElem::GroupElem() {
|
|||
fInfinity = true;
|
||||
}
|
||||
|
||||
GroupElem::GroupElem(const FieldElem &xin, const FieldElem &yin) {
|
||||
GroupElem::GroupElem(const secp256k1_fe_t &xin, const secp256k1_fe_t &yin) {
|
||||
fInfinity = false;
|
||||
x = xin;
|
||||
y = yin;
|
||||
|
@ -22,30 +22,40 @@ bool GroupElem::IsInfinity() const {
|
|||
|
||||
void GroupElem::SetNeg(const GroupElem &p) {
|
||||
*this = p;
|
||||
y.Normalize();
|
||||
y.SetNeg(y, 1);
|
||||
secp256k1_fe_normalize(&y);
|
||||
secp256k1_fe_negate(&y, &y, 1);
|
||||
}
|
||||
|
||||
void GroupElem::GetX(FieldElem &xout) {
|
||||
void GroupElem::GetX(secp256k1_fe_t &xout) {
|
||||
xout = x;
|
||||
}
|
||||
|
||||
void GroupElem::GetY(FieldElem &yout) {
|
||||
void GroupElem::GetY(secp256k1_fe_t &yout) {
|
||||
yout = y;
|
||||
}
|
||||
|
||||
std::string GroupElem::ToString() const {
|
||||
if (fInfinity)
|
||||
return "(inf)";
|
||||
FieldElem xc = x, yc = y;
|
||||
return "(" + xc.ToString() + "," + yc.ToString() + ")";
|
||||
secp256k1_fe_t xc = x, yc = y;
|
||||
char xo[65], yo[65];
|
||||
int xl = 65, yl = 65;
|
||||
secp256k1_fe_get_hex(xo, &xl, &xc);
|
||||
secp256k1_fe_get_hex(yo, &yl, &yc);
|
||||
return "(" + std::string(xo) + "," + std::string(yo) + ")";
|
||||
}
|
||||
|
||||
GroupElemJac::GroupElemJac() : GroupElem(), z(1) {}
|
||||
GroupElemJac::GroupElemJac() : GroupElem() {
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
}
|
||||
|
||||
GroupElemJac::GroupElemJac(const FieldElem &xin, const FieldElem &yin) : GroupElem(xin,yin), z(1) {}
|
||||
GroupElemJac::GroupElemJac(const secp256k1_fe_t &xin, const secp256k1_fe_t &yin) : GroupElem(xin,yin) {
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
}
|
||||
|
||||
GroupElemJac::GroupElemJac(const GroupElem &in) : GroupElem(in), z(1) {}
|
||||
GroupElemJac::GroupElemJac(const GroupElem &in) : GroupElem(in) {
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
}
|
||||
|
||||
void GroupElemJac::SetJac(const GroupElemJac &jac) {
|
||||
*this = jac;
|
||||
|
@ -55,7 +65,7 @@ void GroupElemJac::SetAffine(const GroupElem &aff) {
|
|||
fInfinity = aff.fInfinity;
|
||||
x = aff.x;
|
||||
y = aff.y;
|
||||
z = FieldElem(1);
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
}
|
||||
|
||||
bool GroupElemJac::IsValid() const {
|
||||
|
@ -65,43 +75,38 @@ bool GroupElemJac::IsValid() const {
|
|||
// (Y/Z^3)^2 = (X/Z^2)^3 + 7
|
||||
// Y^2 / Z^6 = X^3 / Z^6 + 7
|
||||
// Y^2 = X^3 + 7*Z^6
|
||||
FieldElem y2; y2.SetSquare(y);
|
||||
FieldElem x3; x3.SetSquare(x); x3.SetMult(x3,x);
|
||||
FieldElem z2; z2.SetSquare(z);
|
||||
FieldElem z6; z6.SetSquare(z2); z6.SetMult(z6,z2);
|
||||
z6 *= 7;
|
||||
x3 += z6;
|
||||
y2.Normalize();
|
||||
x3.Normalize();
|
||||
return y2 == x3;
|
||||
secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &y);
|
||||
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &x); secp256k1_fe_mul(&x3, &x3, &x);
|
||||
secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &z);
|
||||
secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
|
||||
secp256k1_fe_mul_int(&z6, 7);
|
||||
secp256k1_fe_add(&x3, &z6);
|
||||
secp256k1_fe_normalize(&y2);
|
||||
secp256k1_fe_normalize(&x3);
|
||||
return secp256k1_fe_equal(&y2, &x3);
|
||||
}
|
||||
|
||||
void GroupElemJac::GetAffine(GroupElem &aff) {
|
||||
z.SetInverse(z);
|
||||
FieldElem z2;
|
||||
z2.SetSquare(z);
|
||||
FieldElem z3;
|
||||
z3.SetMult(z,z2);
|
||||
x.SetMult(x,z2);
|
||||
y.SetMult(y,z3);
|
||||
z = FieldElem(1);
|
||||
secp256k1_fe_inv(&z, &z);
|
||||
secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &z);
|
||||
secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &z, &z2);
|
||||
secp256k1_fe_mul(&x, &x, &z2);
|
||||
secp256k1_fe_mul(&y, &y, &z3);
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
aff.fInfinity = fInfinity;
|
||||
aff.x = x;
|
||||
aff.y = y;
|
||||
}
|
||||
|
||||
void GroupElemJac::GetX(FieldElem &xout) {
|
||||
FieldElem zi;
|
||||
zi.SetInverse(z);
|
||||
zi.SetSquare(zi);
|
||||
xout.SetMult(x, zi);
|
||||
void GroupElemJac::GetX(secp256k1_fe_t &xout) {
|
||||
secp256k1_fe_t zi2; secp256k1_fe_inv(&zi2, &z); secp256k1_fe_sqr(&zi2, &zi2);
|
||||
secp256k1_fe_mul(&xout, &x, &zi2);
|
||||
}
|
||||
|
||||
void GroupElemJac::GetY(FieldElem &yout) {
|
||||
FieldElem zi;
|
||||
zi.SetInverse(z);
|
||||
FieldElem zi3; zi3.SetSquare(zi); zi3.SetMult(zi, zi3);
|
||||
yout.SetMult(y, zi3);
|
||||
void GroupElemJac::GetY(secp256k1_fe_t &yout) {
|
||||
secp256k1_fe_t zi; secp256k1_fe_inv(&zi, &z);
|
||||
secp256k1_fe_t zi3; secp256k1_fe_sqr(&zi3, &zi); secp256k1_fe_mul(&zi3, &zi, &zi3);
|
||||
secp256k1_fe_mul(&yout, &y, &zi3);
|
||||
}
|
||||
|
||||
bool GroupElemJac::IsInfinity() const {
|
||||
|
@ -111,53 +116,53 @@ bool GroupElemJac::IsInfinity() const {
|
|||
|
||||
void GroupElemJac::SetNeg(const GroupElemJac &p) {
|
||||
*this = p;
|
||||
y.Normalize();
|
||||
y.SetNeg(y, 1);
|
||||
secp256k1_fe_normalize(&y);
|
||||
secp256k1_fe_negate(&y, &y, 1);
|
||||
}
|
||||
|
||||
void GroupElemJac::SetCompressed(const FieldElem &xin, bool fOdd) {
|
||||
void GroupElemJac::SetCompressed(const secp256k1_fe_t &xin, bool fOdd) {
|
||||
x = xin;
|
||||
FieldElem x2; x2.SetSquare(x);
|
||||
FieldElem x3; x3.SetMult(x,x2);
|
||||
secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, &x);
|
||||
secp256k1_fe_t x3; secp256k1_fe_mul(&x3, &x, &x2);
|
||||
fInfinity = false;
|
||||
FieldElem c(7);
|
||||
c += x3;
|
||||
y.SetSquareRoot(c);
|
||||
z = FieldElem(1);
|
||||
y.Normalize();
|
||||
if (y.IsOdd() != fOdd)
|
||||
y.SetNeg(y,1);
|
||||
secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
|
||||
secp256k1_fe_add(&c, &x3);
|
||||
secp256k1_fe_sqrt(&y, &c);
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
secp256k1_fe_normalize(&y);
|
||||
if (secp256k1_fe_is_odd(&y) != fOdd)
|
||||
secp256k1_fe_negate(&y, &y, 1);
|
||||
}
|
||||
|
||||
void GroupElemJac::SetDouble(const GroupElemJac &p) {
|
||||
FieldElem t5 = p.y;
|
||||
t5.Normalize();
|
||||
if (p.fInfinity || t5.IsZero()) {
|
||||
secp256k1_fe_t t5 = p.y;
|
||||
secp256k1_fe_normalize(&t5);
|
||||
if (p.fInfinity || secp256k1_fe_is_zero(&t5)) {
|
||||
fInfinity = true;
|
||||
return;
|
||||
}
|
||||
|
||||
FieldElem t1,t2,t3,t4;
|
||||
z.SetMult(t5,p.z);
|
||||
z *= 2; // Z' = 2*Y*Z (2)
|
||||
t1.SetSquare(p.x);
|
||||
t1 *= 3; // T1 = 3*X^2 (3)
|
||||
t2.SetSquare(t1); // T2 = 9*X^4 (1)
|
||||
t3.SetSquare(t5);
|
||||
t3 *= 2; // T3 = 2*Y^2 (2)
|
||||
t4.SetSquare(t3);
|
||||
t4 *= 2; // T4 = 8*Y^4 (2)
|
||||
t3.SetMult(p.x,t3); // T3 = 2*X*Y^2 (1)
|
||||
secp256k1_fe_t t1,t2,t3,t4;
|
||||
secp256k1_fe_mul(&z, &t5, &p.z);
|
||||
secp256k1_fe_mul_int(&z, 2); // Z' = 2*Y*Z (2)
|
||||
secp256k1_fe_sqr(&t1, &p.x);
|
||||
secp256k1_fe_mul_int(&t1, 3); // T1 = 3*X^2 (3)
|
||||
secp256k1_fe_sqr(&t2, &t1); // T2 = 9*X^4 (1)
|
||||
secp256k1_fe_sqr(&t3, &t5);
|
||||
secp256k1_fe_mul_int(&t3, 2); // T3 = 2*Y^2 (2)
|
||||
secp256k1_fe_sqr(&t4, &t3);
|
||||
secp256k1_fe_mul_int(&t4, 2); // T4 = 8*Y^4 (2)
|
||||
secp256k1_fe_mul(&t3, &p.x, &t3); // T3 = 2*X*Y^2 (1)
|
||||
x = t3;
|
||||
x *= 4; // X' = 8*X*Y^2 (4)
|
||||
x.SetNeg(x,4); // X' = -8*X*Y^2 (5)
|
||||
x += t2; // X' = 9*X^4 - 8*X*Y^2 (6)
|
||||
t2.SetNeg(t2,1); // T2 = -9*X^4 (2)
|
||||
t3 *= 6; // T3 = 12*X*Y^2 (6)
|
||||
t3 += t2; // T3 = 12*X*Y^2 - 9*X^4 (8)
|
||||
y.SetMult(t1,t3); // Y' = 36*X^3*Y^2 - 27*X^6 (1)
|
||||
t2.SetNeg(t4,2); // T2 = -8*Y^4 (3)
|
||||
y += t2; // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4)
|
||||
secp256k1_fe_mul_int(&x, 4); // X' = 8*X*Y^2 (4)
|
||||
secp256k1_fe_negate(&x, &x, 4); // X' = -8*X*Y^2 (5)
|
||||
secp256k1_fe_add(&x, &t2); // X' = 9*X^4 - 8*X*Y^2 (6)
|
||||
secp256k1_fe_negate(&t2, &t2, 1); // T2 = -9*X^4 (2)
|
||||
secp256k1_fe_mul_int(&t3, 6); // T3 = 12*X*Y^2 (6)
|
||||
secp256k1_fe_add(&t3, &t2); // T3 = 12*X*Y^2 - 9*X^4 (8)
|
||||
secp256k1_fe_mul(&y, &t1, &t3); // Y' = 36*X^3*Y^2 - 27*X^6 (1)
|
||||
secp256k1_fe_negate(&t2, &t4, 2); // T2 = -8*Y^4 (3)
|
||||
secp256k1_fe_add(&y, &t2); // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4)
|
||||
fInfinity = false;
|
||||
}
|
||||
|
||||
|
@ -171,36 +176,36 @@ void GroupElemJac::SetAdd(const GroupElemJac &p, const GroupElemJac &q) {
|
|||
return;
|
||||
}
|
||||
fInfinity = false;
|
||||
const FieldElem &x1 = p.x, &y1 = p.y, &z1 = p.z, &x2 = q.x, &y2 = q.y, &z2 = q.z;
|
||||
FieldElem z22; z22.SetSquare(z2);
|
||||
FieldElem z12; z12.SetSquare(z1);
|
||||
FieldElem u1; u1.SetMult(x1, z22);
|
||||
FieldElem u2; u2.SetMult(x2, z12);
|
||||
FieldElem s1; s1.SetMult(y1, z22); s1.SetMult(s1, z2);
|
||||
FieldElem s2; s2.SetMult(y2, z12); s2.SetMult(s2, z1);
|
||||
u1.Normalize();
|
||||
u2.Normalize();
|
||||
if (u1 == u2) {
|
||||
s1.Normalize();
|
||||
s2.Normalize();
|
||||
if (s1 == s2) {
|
||||
const secp256k1_fe_t &x1 = p.x, &y1 = p.y, &z1 = p.z, &x2 = q.x, &y2 = q.y, &z2 = q.z;
|
||||
secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &z2);
|
||||
secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &z1);
|
||||
secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &x1, &z22);
|
||||
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &x2, &z12);
|
||||
secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &y1, &z22); secp256k1_fe_mul(&s1, &s1, &z2);
|
||||
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &y2, &z12); secp256k1_fe_mul(&s2, &s2, &z1);
|
||||
secp256k1_fe_normalize(&u1);
|
||||
secp256k1_fe_normalize(&u2);
|
||||
if (secp256k1_fe_equal(&u1, &u2)) {
|
||||
secp256k1_fe_normalize(&s1);
|
||||
secp256k1_fe_normalize(&s2);
|
||||
if (secp256k1_fe_equal(&s1, &s2)) {
|
||||
SetDouble(p);
|
||||
} else {
|
||||
fInfinity = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
FieldElem h; h.SetNeg(u1,1); h += u2;
|
||||
FieldElem r; r.SetNeg(s1,1); r += s2;
|
||||
FieldElem r2; r2.SetSquare(r);
|
||||
FieldElem h2; h2.SetSquare(h);
|
||||
FieldElem h3; h3.SetMult(h,h2);
|
||||
z.SetMult(z1,z2); z.SetMult(z, h);
|
||||
FieldElem t; t.SetMult(u1,h2);
|
||||
x = t; x *= 2; x += h3; x.SetNeg(x,3); x += r2;
|
||||
y.SetNeg(x,5); y += t; y.SetMult(y,r);
|
||||
h3.SetMult(h3,s1); h3.SetNeg(h3,1);
|
||||
y += h3;
|
||||
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
||||
secp256k1_fe_t r; secp256k1_fe_negate(&r, &s1, 1); secp256k1_fe_add(&r, &s2);
|
||||
secp256k1_fe_t r2; secp256k1_fe_sqr(&r2, &r);
|
||||
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
|
||||
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
|
||||
secp256k1_fe_mul(&z, &z1, &z2); secp256k1_fe_mul(&z, &z, &h);
|
||||
secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
|
||||
x = t; secp256k1_fe_mul_int(&x, 2); secp256k1_fe_add(&x, &h3); secp256k1_fe_negate(&x, &x, 3); secp256k1_fe_add(&x, &r2);
|
||||
secp256k1_fe_negate(&y, &x, 5); secp256k1_fe_add(&y, &t); secp256k1_fe_mul(&y, &y, &r);
|
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
||||
secp256k1_fe_add(&y, &h3);
|
||||
}
|
||||
|
||||
void GroupElemJac::SetAdd(const GroupElemJac &p, const GroupElem &q) {
|
||||
|
@ -208,7 +213,7 @@ void GroupElemJac::SetAdd(const GroupElemJac &p, const GroupElem &q) {
|
|||
x = q.x;
|
||||
y = q.y;
|
||||
fInfinity = q.fInfinity;
|
||||
z = FieldElem(1);
|
||||
secp256k1_fe_set_int(&z, 1);
|
||||
return;
|
||||
}
|
||||
if (q.fInfinity) {
|
||||
|
@ -216,35 +221,35 @@ void GroupElemJac::SetAdd(const GroupElemJac &p, const GroupElem &q) {
|
|||
return;
|
||||
}
|
||||
fInfinity = false;
|
||||
const FieldElem &x1 = p.x, &y1 = p.y, &z1 = p.z, &x2 = q.x, &y2 = q.y;
|
||||
FieldElem z12; z12.SetSquare(z1);
|
||||
FieldElem u1 = x1; u1.Normalize();
|
||||
FieldElem u2; u2.SetMult(x2, z12);
|
||||
FieldElem s1 = y1; s1.Normalize();
|
||||
FieldElem s2; s2.SetMult(y2, z12); s2.SetMult(s2, z1);
|
||||
u1.Normalize();
|
||||
u2.Normalize();
|
||||
if (u1 == u2) {
|
||||
s1.Normalize();
|
||||
s2.Normalize();
|
||||
if (s1 == s2) {
|
||||
const secp256k1_fe_t &x1 = p.x, &y1 = p.y, &z1 = p.z, &x2 = q.x, &y2 = q.y;
|
||||
secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &z1);
|
||||
secp256k1_fe_t u1 = x1; secp256k1_fe_normalize(&u1);
|
||||
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &x2, &z12);
|
||||
secp256k1_fe_t s1 = y1; secp256k1_fe_normalize(&s1);
|
||||
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &y2, &z12); secp256k1_fe_mul(&s2, &s2, &z1);
|
||||
secp256k1_fe_normalize(&u1);
|
||||
secp256k1_fe_normalize(&u2);
|
||||
if (secp256k1_fe_equal(&u1, &u2)) {
|
||||
secp256k1_fe_normalize(&s1);
|
||||
secp256k1_fe_normalize(&s2);
|
||||
if (secp256k1_fe_equal(&s1, &s2)) {
|
||||
SetDouble(p);
|
||||
} else {
|
||||
fInfinity = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
FieldElem h; h.SetNeg(u1,1); h += u2;
|
||||
FieldElem r; r.SetNeg(s1,1); r += s2;
|
||||
FieldElem r2; r2.SetSquare(r);
|
||||
FieldElem h2; h2.SetSquare(h);
|
||||
FieldElem h3; h3.SetMult(h,h2);
|
||||
z = p.z; z.SetMult(z, h);
|
||||
FieldElem t; t.SetMult(u1,h2);
|
||||
x = t; x *= 2; x += h3; x.SetNeg(x,3); x += r2;
|
||||
y.SetNeg(x,5); y += t; y.SetMult(y,r);
|
||||
h3.SetMult(h3,s1); h3.SetNeg(h3,1);
|
||||
y += h3;
|
||||
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
||||
secp256k1_fe_t r; secp256k1_fe_negate(&r, &s1, 1); secp256k1_fe_add(&r, &s2);
|
||||
secp256k1_fe_t r2; secp256k1_fe_sqr(&r2, &r);
|
||||
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
|
||||
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
|
||||
z = p.z; secp256k1_fe_mul(&z, &z, &h);
|
||||
secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
|
||||
x = t; secp256k1_fe_mul_int(&x, 2); secp256k1_fe_add(&x, &h3); secp256k1_fe_negate(&x, &x, 3); secp256k1_fe_add(&x, &r2);
|
||||
secp256k1_fe_negate(&y, &x, 5); secp256k1_fe_add(&y, &t); secp256k1_fe_mul(&y, &y, &r);
|
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
||||
secp256k1_fe_add(&y, &h3);
|
||||
}
|
||||
|
||||
std::string GroupElemJac::ToString() const {
|
||||
|
@ -290,15 +295,19 @@ static const unsigned char a2_[] = {0x01,
|
|||
0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
|
||||
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8};
|
||||
|
||||
GroupConstants::GroupConstants() : g_x(g_x_), g_y(g_y_),
|
||||
g(g_x,g_y),
|
||||
beta(beta_) {
|
||||
GroupConstants::GroupConstants() {
|
||||
secp256k1_num_init(&order);
|
||||
secp256k1_num_init(&lambda);
|
||||
secp256k1_num_init(&a1b2);
|
||||
secp256k1_num_init(&b1);
|
||||
secp256k1_num_init(&a2);
|
||||
|
||||
secp256k1_fe_set_b32(&g_x, g_x_);
|
||||
secp256k1_fe_set_b32(&g_y, g_y_);
|
||||
secp256k1_fe_set_b32(&beta, beta_);
|
||||
|
||||
g = GroupElem(g_x, g_y);
|
||||
|
||||
secp256k1_num_set_bin(&order, order_, sizeof(order_));
|
||||
secp256k1_num_set_bin(&lambda, lambda_, sizeof(lambda_));
|
||||
secp256k1_num_set_bin(&a1b2, a1b2_, sizeof(a1b2_));
|
||||
|
@ -320,9 +329,9 @@ const GroupConstants &GetGroupConst() {
|
|||
}
|
||||
|
||||
void GroupElemJac::SetMulLambda(const GroupElemJac &p) {
|
||||
FieldElem beta = GetGroupConst().beta;
|
||||
const secp256k1_fe_t &beta = GetGroupConst().beta;
|
||||
*this = p;
|
||||
x.SetMult(x, beta);
|
||||
secp256k1_fe_mul(&x, &x, &beta);
|
||||
}
|
||||
|
||||
void SplitExp(const secp256k1_num_t &exp, secp256k1_num_t &exp1, secp256k1_num_t &exp2) {
|
||||
|
|
28
group.h
28
group.h
|
@ -14,8 +14,8 @@ class GroupElemJac;
|
|||
class GroupElem {
|
||||
protected:
|
||||
bool fInfinity;
|
||||
FieldElem x;
|
||||
FieldElem y;
|
||||
secp256k1_fe_t x;
|
||||
secp256k1_fe_t y;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -23,16 +23,16 @@ public:
|
|||
GroupElem();
|
||||
|
||||
/** Creates the point with given affine coordinates */
|
||||
GroupElem(const FieldElem &xin, const FieldElem &yin);
|
||||
GroupElem(const secp256k1_fe_t &xin, const secp256k1_fe_t &yin);
|
||||
|
||||
/** Checks whether this is the point at infinity */
|
||||
bool IsInfinity() const;
|
||||
|
||||
void SetNeg(const GroupElem &p);
|
||||
|
||||
void GetX(FieldElem &xout);
|
||||
void GetX(secp256k1_fe_t &xout);
|
||||
|
||||
void GetY(FieldElem &yout);
|
||||
void GetY(secp256k1_fe_t &yout);
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
|
@ -44,14 +44,14 @@ public:
|
|||
/** Represents a point on the secp256k1 curve, with jacobian coordinates */
|
||||
class GroupElemJac : private GroupElem {
|
||||
protected:
|
||||
FieldElem z;
|
||||
secp256k1_fe_t z;
|
||||
|
||||
public:
|
||||
/** Creates the point at infinity */
|
||||
GroupElemJac();
|
||||
|
||||
/** Creates the point with given affine coordinates */
|
||||
GroupElemJac(const FieldElem &xin, const FieldElem &yin);
|
||||
GroupElemJac(const secp256k1_fe_t &xin, const secp256k1_fe_t &yin);
|
||||
|
||||
GroupElemJac(const GroupElem &in);
|
||||
|
||||
|
@ -65,15 +65,15 @@ public:
|
|||
/** Returns the affine coordinates of this point */
|
||||
void GetAffine(GroupElem &aff);
|
||||
|
||||
void GetX(FieldElem &xout);
|
||||
void GetY(FieldElem &yout);
|
||||
void GetX(secp256k1_fe_t &xout);
|
||||
void GetY(secp256k1_fe_t &yout);
|
||||
|
||||
bool IsInfinity() const;
|
||||
|
||||
void SetNeg(const GroupElemJac &p);
|
||||
|
||||
/** Sets this point to have a given X coordinate & given Y oddness */
|
||||
void SetCompressed(const FieldElem &xin, bool fOdd);
|
||||
void SetCompressed(const secp256k1_fe_t &xin, bool fOdd);
|
||||
|
||||
/** Sets this point to be the EC double of another */
|
||||
void SetDouble(const GroupElemJac &p);
|
||||
|
@ -91,13 +91,13 @@ public:
|
|||
|
||||
class GroupConstants {
|
||||
private:
|
||||
const FieldElem g_x;
|
||||
const FieldElem g_y;
|
||||
secp256k1_fe_t g_x;
|
||||
secp256k1_fe_t g_y;
|
||||
|
||||
public:
|
||||
secp256k1_num_t order;
|
||||
const GroupElem g;
|
||||
const FieldElem beta;
|
||||
GroupElem g;
|
||||
secp256k1_fe_t beta;
|
||||
secp256k1_num_t lambda, a1b2, b1, a2;
|
||||
|
||||
GroupConstants();
|
||||
|
|
15
tests.cpp
15
tests.cpp
|
@ -13,8 +13,8 @@ using namespace secp256k1;
|
|||
|
||||
void test_run_ecmult_chain() {
|
||||
// random starting point A (on the curve)
|
||||
FieldElem ax; ax.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004");
|
||||
FieldElem ay; ay.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||
secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64);
|
||||
secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
|
||||
GroupElemJac a(ax,ay);
|
||||
// two random initial factors xn and gn
|
||||
secp256k1_num_t xn;
|
||||
|
@ -85,13 +85,15 @@ void test_point_times_order(const GroupElemJac &point) {
|
|||
}
|
||||
|
||||
void test_run_point_times_order() {
|
||||
FieldElem x; x.SetHex("02");
|
||||
secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2);
|
||||
for (int i=0; i<500; i++) {
|
||||
GroupElemJac j; j.SetCompressed(x, true);
|
||||
test_point_times_order(j);
|
||||
x.SetSquare(x);
|
||||
secp256k1_fe_sqr(&x, &x);
|
||||
}
|
||||
assert(x.ToString() == "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45"); // 0x02 ^ (2^500)
|
||||
char c[65]; int cl=65;
|
||||
secp256k1_fe_get_hex(c, &cl, &x);
|
||||
assert(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
|
||||
}
|
||||
|
||||
void test_wnaf(const secp256k1_num_t &number, int w) {
|
||||
|
@ -173,10 +175,13 @@ void test_run_ecdsa_sign_verify() {
|
|||
|
||||
int main(void) {
|
||||
secp256k1_num_start();
|
||||
secp256k1_fe_start();
|
||||
|
||||
test_run_wnaf();
|
||||
test_run_point_times_order();
|
||||
test_run_ecmult_chain();
|
||||
test_run_ecdsa_sign_verify();
|
||||
|
||||
secp256k1_fe_stop();
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue