private static bool secp256k1_ecdsa_sig_sign(secp256k1_ecmult_gen_context ctx, secp256k1_scalar sigr, secp256k1_scalar sigs, secp256k1_scalar seckey, secp256k1_scalar message, secp256k1_scalar nonce, out byte recid) { var b = new byte[32]; secp256k1_gej rp; secp256k1_ge r = new secp256k1_ge(); secp256k1_scalar n = new secp256k1_scalar(); bool overflow = false; ECMultGen.secp256k1_ecmult_gen(ctx, out rp, nonce); Group.secp256k1_ge_set_gej(r, rp); Field.secp256k1_fe_normalize(r.x); Field.secp256k1_fe_normalize(r.y); Field.secp256k1_fe_get_b32(b, r.x); Scalar.secp256k1_scalar_set_b32(sigr, b, ref overflow); /* These two conditions should be checked before calling */ Util.VERIFY_CHECK(!Scalar.secp256k1_scalar_is_zero(sigr)); Util.VERIFY_CHECK(!overflow); // The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log // of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. recid = (byte)((overflow ? 2 : 0) | (Field.secp256k1_fe_is_odd(r.y) ? 1 : 0)); Scalar.secp256k1_scalar_mul(n, sigr, seckey); Scalar.secp256k1_scalar_add(n, n, message); Scalar.secp256k1_scalar_inverse(sigs, nonce); Scalar.secp256k1_scalar_mul(sigs, sigs, n); Scalar.secp256k1_scalar_clear(n); Group.secp256k1_gej_clear(rp); Group.secp256k1_ge_clear(r); if (Scalar.secp256k1_scalar_is_zero(sigs)) { return(false); } if (Scalar.secp256k1_scalar_is_high(sigs)) { Scalar.secp256k1_scalar_negate(sigs, sigs); recid ^= 1; } return(true); }
// // /** Double multiply: R = na*A + ng*G */ // // static void secp256k1_ecmult(const secp256k1_ecmult_context* ctx, secp256k1_gej* r, const secp256k1_gej* a, const secp256k1_scalar* na, const secp256k1_scalar* ng); //#if defined(EXHAUSTIVE_TEST_ORDER) ///* We need to lower these values for exhaustive tests because // * the tables cannot have infinities in them (this breaks the // * affine-isomorphism stuff which tracks z-ratios) */ //#if EXHAUSTIVE_TEST_ORDER > 128 //#define WINDOW_A 5 //#define WINDOW_G 8 //#elif EXHAUSTIVE_TEST_ORDER > 8 //#define WINDOW_A 4 //#define WINDOW_G 4 //#else //#define WINDOW_A 2 //#define WINDOW_G 2 //#endif //#else // /* optimal for 128-bit and 256-bit exponents. */ //#define WINDOW_A 5 // /** larger numbers may result in slightly better performance, at the cost of // exponentially larger precomputed tables. */ //# ifdef USE_ENDOMORPHISM // /** Two tables for window size 15: 1.375 MiB. */ //#define WINDOW_G 15 //#else // /** One table for window size 16: 1.375 MiB. */ //#define WINDOW_G 16 //#endif //#endif /** The number of entries a table with precomputed multiples needs to have. */ //#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) /// <summary> /// Fill a table 'prej' with precomputed odd multiples of a. Prej will contain /// the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will /// contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. /// Prej's Z values are undefined, except for the last value. /// </summary> /// <param name="n"></param> /// <param name="prej"></param> /// <param name="zr"></param> /// <param name="a"></param> static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej[] prej, secp256k1_fe[] zr, secp256k1_gej a) { Util.VERIFY_CHECK(!a.infinity); secp256k1_gej d = new secp256k1_gej(); Group.secp256k1_gej_double_var(d, a, null); /* * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. */ secp256k1_ge d_ge = new secp256k1_ge(); d_ge.x = d.x.Clone(); d_ge.y = d.y.Clone(); d_ge.infinity = false; secp256k1_ge a_ge = new secp256k1_ge(); Group.secp256k1_ge_set_gej_zinv(a_ge, a, d.z); prej[0].x = a_ge.x.Clone(); prej[0].y = a_ge.y.Clone(); prej[0].z = a.z.Clone(); prej[0].infinity = false; zr[0] = d.z.Clone(); for (var i = 1; i < n; i++) { Group.secp256k1_gej_add_ge_var(prej[i], prej[i - 1], d_ge, zr[i]); } /* * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only * the final point's z coordinate is actually used though, so just update that. */ Field.secp256k1_fe_mul(prej[n - 1].z, prej[n - 1].z, d.z); }
///** 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;