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);
        }
Exemplo n.º 2
0
        //        //    /** 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);
        }
Exemplo n.º 3
0
        ///** 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]);
            }
        }
Exemplo n.º 4
0
        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;