예제 #1
0
        public static void ge_scalarmult_p3(out GroupElementP3 r3, byte[] a, ref GroupElementP3 A)
        {
            sbyte[] e = new sbyte[64];
            int     carry, carry2, i;

            GroupElementCached[] Ai = new GroupElementCached[8]; /* 1 * A, 2 * A, ..., 8 * A */
            GroupElementP1P1     t;
            GroupElementP3       u;
            GroupElementP2       r;

            carry = 0; /* 0..1 */
            for (i = 0; i < 31; i++)
            {
                carry       += a[i];                           /* 0..256 */
                carry2       = (carry + 8) >> 4;               /* 0..16 */
                e[2 * i]     = (sbyte)(carry - (carry2 << 4)); /* -8..7 */
                carry        = (carry2 + 8) >> 4;              /* 0..1 */
                e[2 * i + 1] = (sbyte)(carry2 - (carry << 4)); /* -8..7 */
            }
            carry += a[31];                                    /* 0..128 */
            carry2 = (carry + 8) >> 4;                         /* 0..8 */
            e[62]  = (sbyte)(carry - (carry2 << 4));           /* -8..7 */
            e[63]  = (sbyte)carry2;                            /* 0..8 */

            ge_p3_to_cached(out Ai[0], ref A);
            for (i = 0; i < 7; i++)
            {
                ge_add(out t, ref A, ref Ai[i]);
                ge_p1p1_to_p3(out u, ref t);
                ge_p3_to_cached(out Ai[i + 1], ref u);
            }

            ge_p2_0(out r);
            GroupElementP3 resP3;

            ge_p3_0(out resP3);
            for (i = 63; i >= 0; i--)
            {
                sbyte b = e[i];
                byte  bnegative = negative(b);
                byte  babs = (byte)(b - (((-bnegative) & b) << 1));
                GroupElementCached cur, minuscur;
                ge_p2_dbl(out t, ref r);
                ge_p1p1_to_p2(out r, ref t);
                ge_p2_dbl(out t, ref r);
                ge_p1p1_to_p2(out r, ref t);
                ge_p2_dbl(out t, ref r);
                ge_p1p1_to_p2(out r, ref t);
                ge_p2_dbl(out t, ref r);
                ge_p1p1_to_p3(out u, ref t);
                ge_cached_0(out cur);
                ge_cached_cmov(ref cur, ref Ai[0], equal(babs, 1));
                ge_cached_cmov(ref cur, ref Ai[1], equal(babs, 2));
                ge_cached_cmov(ref cur, ref Ai[2], equal(babs, 3));
                ge_cached_cmov(ref cur, ref Ai[3], equal(babs, 4));
                ge_cached_cmov(ref cur, ref Ai[4], equal(babs, 5));
                ge_cached_cmov(ref cur, ref Ai[5], equal(babs, 6));
                ge_cached_cmov(ref cur, ref Ai[6], equal(babs, 7));
                ge_cached_cmov(ref cur, ref Ai[7], equal(babs, 8));
                FieldOperations.fe_copy(out minuscur.YplusX, ref cur.YminusX);
                FieldOperations.fe_copy(out minuscur.YminusX, ref cur.YplusX);
                FieldOperations.fe_copy(out minuscur.Z, ref cur.Z);
                FieldOperations.fe_neg(out minuscur.T2d, ref cur.T2d);
                ge_cached_cmov(ref cur, ref minuscur, bnegative);
                ge_add(out t, ref u, ref cur);
                if (i == 0)
                {
                    ge_p1p1_to_p3(out resP3, ref t);
                }
                else
                {
                    ge_p1p1_to_p2(out r, ref t);
                }
            }

            r3 = resP3;
        }
예제 #2
0
        public static void ge_fromfe_frombytes_vartime(out GroupElementP2 r, byte[] s, int offset)
        {
            FieldElement u, v, w, x, y, z;
            byte         sign;

            FieldOperations.fe_frombytes(out u, s, offset);
            FieldOperations.fe_sq2(out v, ref u); /* 2 * u^2 */

            FieldOperations.fe_1(out w);
            FieldOperations.fe_add(out w, ref v, ref w);                      /* w = 2 * u^2 + 1 */
            FieldOperations.fe_sq(out x, ref w);                              /* w^2 */
            FieldOperations.fe_mul(out y, ref FieldOperations.fe_ma2, ref v); /* -2 * A^2 * u^2 */
            FieldOperations.fe_add(out x, ref x, ref y);                      /* x = w^2 - 2 * A^2 * u^2 */
            FieldOperations.fe_divpowm1(out r.X, ref w, ref x);               /* (w / x)^(m + 1) */
            FieldOperations.fe_sq(out y, ref r.X);
            FieldOperations.fe_mul(out x, ref y, ref x);
            FieldOperations.fe_sub(out y, ref w, ref x);
            FieldOperations.fe_copy(out z, ref FieldOperations.fe_ma);
            if (FieldOperations.fe_isnonzero(ref y) != 0)
            {
                FieldOperations.fe_add(out y, ref w, ref x);
                if (FieldOperations.fe_isnonzero(ref y) != 0)
                {
                    goto negative;
                }
                else
                {
                    FieldOperations.fe_mul(out r.X, ref r.X, ref FieldOperations.fe_fffb1);
                }
            }
            else
            {
                FieldOperations.fe_mul(out r.X, ref r.X, ref FieldOperations.fe_fffb2);
            }
            FieldOperations.fe_mul(out r.X, ref r.X, ref u); /* u * sqrt(2 * A * (A + 2) * w / x) */
            FieldOperations.fe_mul(out z, ref z, ref v);     /* -2 * A * u^2 */
            sign = 0;
            goto setsign;
negative:
            FieldOperations.fe_mul(out x, ref x, ref FieldOperations.fe_sqrtm1);
            FieldOperations.fe_sub(out y, ref w, ref x);
            if (FieldOperations.fe_isnonzero(ref y) != 0)
            {
                //assert((fe_add(y, w, x), !fe_isnonzero(y)));
                FieldOperations.fe_mul(out r.X, ref r.X, ref FieldOperations.fe_fffb3);
            }
            else
            {
                FieldOperations.fe_mul(out r.X, ref r.X, ref FieldOperations.fe_fffb4);
            }
            /* r->X = sqrt(A * (A + 2) * w / x) */
            /* z = -A */
            sign = 1;
setsign:
            if (FieldOperations.fe_isnegative(ref r.X) != sign)
            {
                //assert(fe_isnonzero(r->X));
                FieldOperations.fe_neg(out r.X, ref r.X);
            }
            FieldOperations.fe_add(out r.Z, ref z, ref w);
            FieldOperations.fe_sub(out r.Y, ref z, ref w);
            FieldOperations.fe_mul(out r.X, ref r.X, ref r.Z);
        }