//#if defined HAVE_CONFIG_H //# include "libsecp256k1-config.h" //#endif //# include "util.h" //#if defined(USE_FIELD_10X26) //# include "field_10x26_impl.h" //#elif defined(USE_FIELD_5X52) //# include "field_5x52_impl.h" //#else //#error "Please select field implementation" //#endif public static bool secp256k1_fe_equal(secp256k1_fe a, secp256k1_fe b) { secp256k1_fe na = new secp256k1_fe(); secp256k1_fe_negate(na, a, 1); secp256k1_fe_add(na, b); return(secp256k1_fe_normalizes_to_zero(na)); }
///** Fill a table 'pre' with precomputed odd multiples of a. // * // * There are two versions of this function: // * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its // * resulting point set to a single constant Z denominator, stores the X and Y // * coordinates as ge_storage points in pre, and stores the global Z in rz. // * It only operates on tables sized for WINDOW_A wnaf multiples. // * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its // * resulting point set to actually affine points, and stores those in pre. // * It operates on tables of any size, but uses heap-allocated temporaries. // * // * To compute a*P + b*G, we compute a table for P using the first function, // * and for G using the second (which requires an inverse, but it only needs to // * happen once). // */ //static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge* pre, secp256k1_fe* globalz, const secp256k1_gej* a) //{ // secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; // secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; // /* Compute the odd multiples in Jacobian form. */ // secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); // /* Bring them to the same Z denominator. */ // secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); //} public static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage[] pre, secp256k1_gej a, EventHandler <secp256k1_callback> cb) { secp256k1_gej[] prej = new secp256k1_gej[n]; secp256k1_ge[] prea = new secp256k1_ge[n]; secp256k1_fe[] zr = new secp256k1_fe[n]; for (int i = 0; i < n; i++) { prej[i] = new secp256k1_gej(); prea[i] = new secp256k1_ge(); zr[i] = new secp256k1_fe(); } /* Compute the odd multiples in Jacobian form. */ secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); /* Convert them in batch to affine coordinates. */ Group.secp256k1_ge_set_table_gej_var(prea, prej, zr, n); /* Convert them to compact storage form. */ for (var i = 0; i < n; i++) { Group.secp256k1_ge_to_storage(pre[i], prea[i]); } }
public static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context ctx, EventHandler <secp256k1_callback> cb) { #if !USE_ECMULT_STATIC_PRECOMPUTATION secp256k1_ge[] prec = new secp256k1_ge[1024]; secp256k1_gej gj = new secp256k1_gej(); secp256k1_gej nums_gej = new secp256k1_gej(); int i, j; #endif if (ctx.prec != null) { return; } #if !USE_ECMULT_STATIC_PRECOMPUTATION ctx.PrecInit(); /* get the generator */ Group.secp256k1_gej_set_ge(gj, Group.secp256k1_ge_const_g); /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ { var nums_b32 = Encoding.UTF8.GetBytes("The scalar for this x is unknown"); secp256k1_fe nums_x = new secp256k1_fe(); secp256k1_ge nums_ge = new secp256k1_ge(); var r = Field.secp256k1_fe_set_b32(nums_x, nums_b32); //(void)r; Util.VERIFY_CHECK(r); r = Group.secp256k1_ge_set_xo_var(nums_ge, nums_x, false); //(void)r; Util.VERIFY_CHECK(r); Group.secp256k1_gej_set_ge(nums_gej, nums_ge); /* Add G to make the bits in x uniformly distributed. */ Group.secp256k1_gej_add_ge_var(nums_gej, nums_gej, Group.secp256k1_ge_const_g, null); } /* compute prec. */ { secp256k1_gej[] precj = new secp256k1_gej[1024]; /* Jacobian versions of prec. */ for (int k = 0; k < precj.Length; k++) { precj[k] = new secp256k1_gej(); } secp256k1_gej gbase; secp256k1_gej numsbase; gbase = gj.Clone(); /* 16^j * G */ numsbase = nums_gej.Clone(); /* 2^j * nums. */ for (j = 0; j < 64; j++) { /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ precj[j * 16] = numsbase.Clone(); for (i = 1; i < 16; i++) { Group.secp256k1_gej_add_var(precj[j * 16 + i], precj[j * 16 + i - 1], gbase, null); } /* Multiply gbase by 16. */ for (i = 0; i < 4; i++) { Group.secp256k1_gej_double_var(gbase, gbase, null); } /* Multiply numbase by 2. */ Group.secp256k1_gej_double_var(numsbase, numsbase, null); if (j == 62) { /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ Group.secp256k1_gej_neg(numsbase, numsbase); Group.secp256k1_gej_add_var(numsbase, numsbase, nums_gej, null); } } for (int k = 0; k < prec.Length; k++) { prec[k] = new secp256k1_ge(); } Group.secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); } for (j = 0; j < 64; j++) { for (i = 0; i < 16; i++) { Group.secp256k1_ge_to_storage(ctx.prec[j][i], prec[j * 16 + i]); } } #else (void)cb; ctx.prec = (secp256k1_ge_storage(*)[64][16])secp256k1_ecmult_static_context;
// SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe* a, const secp256k1_fe* b) // { // secp256k1_fe na; // secp256k1_fe_negate(na, a, 1); // secp256k1_fe_add(na, b); // return secp256k1_fe_normalizes_to_zero_var(na); // } public static bool secp256k1_fe_sqrt(secp256k1_fe r, secp256k1_fe a) { /** Given that p is congruent to 3 mod 4, we can compute the square root of * a mod p as the (p+1)/4'th power of a. * * As (p+1)/4 is an even number, it will have the same result for a and for * (-a). Only one of these two numbers actually has a square root however, * so we test at the end by squaring and comparing to the input. * Also because (p+1)/4 is an even number, the computed square root is * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). */ secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; int j; /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ x2 = new secp256k1_fe(); secp256k1_fe_sqr(x2, a); secp256k1_fe_mul(x2, x2, a); x3 = new secp256k1_fe(); secp256k1_fe_sqr(x3, x2); secp256k1_fe_mul(x3, x3, a); x6 = x3.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x6, x6); } secp256k1_fe_mul(x6, x6, x3); x9 = x6.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x9, x9); } secp256k1_fe_mul(x9, x9, x3); x11 = x9.Clone(); for (j = 0; j < 2; j++) { secp256k1_fe_sqr(x11, x11); } secp256k1_fe_mul(x11, x11, x2); x22 = x11.Clone(); for (j = 0; j < 11; j++) { secp256k1_fe_sqr(x22, x22); } secp256k1_fe_mul(x22, x22, x11); x44 = x22.Clone(); for (j = 0; j < 22; j++) { secp256k1_fe_sqr(x44, x44); } secp256k1_fe_mul(x44, x44, x22); x88 = x44.Clone(); for (j = 0; j < 44; j++) { secp256k1_fe_sqr(x88, x88); } secp256k1_fe_mul(x88, x88, x44); x176 = x88.Clone(); for (j = 0; j < 88; j++) { secp256k1_fe_sqr(x176, x176); } secp256k1_fe_mul(x176, x176, x88); x220 = x176.Clone(); for (j = 0; j < 44; j++) { secp256k1_fe_sqr(x220, x220); } secp256k1_fe_mul(x220, x220, x44); x223 = x220.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x223, x223); } secp256k1_fe_mul(x223, x223, x3); /* The final result is then assembled using a sliding window over the blocks. */ t1 = x223.Clone(); for (j = 0; j < 23; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(t1, t1, x22); for (j = 0; j < 6; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(t1, t1, x2); secp256k1_fe_sqr(t1, t1); secp256k1_fe_sqr(r, t1); /* Check that a square root was actually calculated */ secp256k1_fe_sqr(t1, r); return(secp256k1_fe_equal(t1, a)); }
public static void secp256k1_fe_inv_var(secp256k1_fe r, secp256k1_fe a) { #if USE_FIELD_INV_BUILTIN secp256k1_fe_inv(r, a); #elif USE_FIELD_INV_NUM secp256k1_num n, m;
public static void secp256k1_fe_inv(secp256k1_fe r, secp256k1_fe a) { secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; int j; /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ x2 = new secp256k1_fe(); secp256k1_fe_sqr(x2, a); secp256k1_fe_mul(x2, x2, a); x3 = new secp256k1_fe(); secp256k1_fe_sqr(x3, x2); secp256k1_fe_mul(x3, x3, a); x6 = x3.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x6, x6); } secp256k1_fe_mul(x6, x6, x3); x9 = x6.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x9, x9); } secp256k1_fe_mul(x9, x9, x3); x11 = x9.Clone(); for (j = 0; j < 2; j++) { secp256k1_fe_sqr(x11, x11); } secp256k1_fe_mul(x11, x11, x2); x22 = x11.Clone(); for (j = 0; j < 11; j++) { secp256k1_fe_sqr(x22, x22); } secp256k1_fe_mul(x22, x22, x11); x44 = x22.Clone(); for (j = 0; j < 22; j++) { secp256k1_fe_sqr(x44, x44); } secp256k1_fe_mul(x44, x44, x22); x88 = x44.Clone(); for (j = 0; j < 44; j++) { secp256k1_fe_sqr(x88, x88); } secp256k1_fe_mul(x88, x88, x44); x176 = x88.Clone(); for (j = 0; j < 88; j++) { secp256k1_fe_sqr(x176, x176); } secp256k1_fe_mul(x176, x176, x88); x220 = x176.Clone(); for (j = 0; j < 44; j++) { secp256k1_fe_sqr(x220, x220); } secp256k1_fe_mul(x220, x220, x44); x223 = x220.Clone(); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(x223, x223); } secp256k1_fe_mul(x223, x223, x3); /* The final result is then assembled using a sliding window over the blocks. */ t1 = x223.Clone(); for (j = 0; j < 23; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(t1, t1, x22); for (j = 0; j < 5; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(t1, t1, a); for (j = 0; j < 3; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(t1, t1, x2); for (j = 0; j < 2; j++) { secp256k1_fe_sqr(t1, t1); } secp256k1_fe_mul(r, a, t1); }