public static void SetAllGroupElementJacobianVariable(Span <GE> r, ReadOnlySpan <GEJ> a, int len) { FE u; int i; int last_i = SIZE_MAX; for (i = 0; i < len; i++) { if (!a[i].infinity) { /* Use destination's x coordinates as scratch space */ if (last_i == SIZE_MAX) { r[i] = new GE(a[i].z, r[i].y, r[i].infinity); } else { FE rx = r[last_i].x * a[i].z; r[i] = new GE(rx, r[i].y, r[i].infinity); } last_i = i; } } if (last_i == SIZE_MAX) { return; } u = r[last_i].x.InverseVariable(); i = last_i; while (i > 0) { i--; if (!a[i].infinity) { FE rx = r[i].x * u; r[last_i] = new GE(rx, r[last_i].y, r[last_i].infinity); u = u * a[last_i].z; last_i = i; } } VERIFY_CHECK(!a[last_i].infinity); r[last_i] = new GE(u, r[last_i].y, r[last_i].infinity); for (i = 0; i < len; i++) { r[i] = new GE(r[i].x, r[i].y, a[i].infinity); if (!a[i].infinity) { r[i] = a[i].ToGroupElementZInv(r[i].x); } } }
public static bool TryCreateXOVariable(FE x, bool odd, out GE result) { if (!TryCreateXQuad(x, out result)) { return(false); } var ry = result.y.NormalizeVariable(); if (ry.IsOdd != odd) { ry = ry.Negate(1); } result = new GE(result.x, ry, result.infinity); return(true); }
public static bool TryCreateXQuad(FE x, out GE result) { result = GE.Zero; FE rx, ry; bool rinfinity; FE x2, x3, c; rx = x; x2 = x.Sqr(); x3 = x * x2; rinfinity = false; c = new FE(EC.CURVE_B); c += x3; if (!c.Sqrt(out ry)) { return(false); } result = new GE(rx, ry, rinfinity); return(true); }
public ECMultGenContext() { Span <GE> prec = stackalloc GE[1024]; GEJ gj; GEJ nums_gej; int i, j; this.prec = new GEStorage[64, 16]; gj = EC.G.ToGroupElementJacobian(); /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ { var nums_b32 = "The scalar for this x is unknown".ToCharArray().Select(b => (byte)b).ToArray(); FE nums_x; GE nums_ge; var r = FE.TryCreate(nums_b32, out nums_x); VERIFY_CHECK(r); r = GE.TryCreateXOVariable(nums_x, false, out nums_ge); VERIFY_CHECK(r); nums_gej = nums_ge.ToGroupElementJacobian(); /* Add G to make the bits in x uniformly distributed. */ nums_gej = nums_gej.AddVariable(EC.G, out _); } /* compute prec. */ { Span <GEJ> precj = stackalloc GEJ[1024]; /* Jacobian versions of prec. */ GEJ gbase; GEJ numsbase; gbase = gj; /* 16^j * G */ numsbase = nums_gej; /* 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; for (i = 1; i < 16; i++) { precj[j * 16 + i] = precj[j * 16 + i - 1].AddVariable(gbase, out _); } /* Multiply gbase by 16. */ for (i = 0; i < 4; i++) { gbase = gbase.DoubleVariable(); } /* Multiply numbase by 2. */ numsbase = numsbase.DoubleVariable(); if (j == 62) { /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ numsbase = numsbase.Negate(); numsbase = numsbase.AddVariable(nums_gej, out _); } } GE.SetAllGroupElementJacobianVariable(prec, precj, 1024); } for (j = 0; j < 64; j++) { for (i = 0; i < 16; i++) { this.prec[j, i] = prec[j * 16 + i].ToStorage(); } } Blind(); }