internal static bool Pubkey_parse(ReadOnlySpan <byte> pub, out bool compressed, out GE elem) { compressed = false; elem = default; if (pub.Length == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { compressed = true; return (FE.TryCreate(pub.Slice(1), out var x) && GE.TryCreateXOVariable(x, pub[0] == SECP256K1_TAG_PUBKEY_ODD, out elem)); } else if (pub.Length == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { if (!FE.TryCreate(pub.Slice(1), out var x) || !FE.TryCreate(pub.Slice(33), out var y)) { return(false); } elem = new GE(x, y); if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && y.IsOdd != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { return(false); } return(elem.IsValidVariable); } else { return(false); } }
internal static void secp256k1_xonly_ge_serialize(Span <byte> output32, ref GE ge) { if (ge.IsInfinity) { throw new InvalidOperationException("ge should not be infinite"); } ge = ge.NormalizeXVariable(); ge.x.WriteToSpan(output32); }
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); }
internal static bool Pubkey_parse(ReadOnlySpan <byte> pub, out GE elem) { return(Pubkey_parse(pub, out _, out elem)); }
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(); }