public ECMultContext() { //secp256k1_ecmult_context_build /* get the generator */ GEJ gj = EC.G.ToGroupElementJacobian(); this.pre_g = new GEStorage[ArraySize]; /* precompute the tables with odd multiples */ secp256k1_ecmult_odd_multiples_table_storage_var(ArraySize, pre_g, gj); { GEJ g_128j; int i; this.pre_g_128 = new GEStorage[ArraySize]; /* calculate 2^128*generator */ g_128j = gj; for (i = 0; i < 128; i++) { g_128j = g_128j.DoubleVariable(); } secp256k1_ecmult_odd_multiples_table_storage_var(ArraySize, pre_g_128, g_128j); } }
public void Blind(byte[]?seed32 = null) { Scalar b; GEJ gb; FE s; Span <byte> nonce32 = stackalloc byte[32]; using RFC6979HMACSHA256 rng = new RFC6979HMACSHA256(); bool retry; Span <byte> keydata = stackalloc byte[64]; if (seed32 == null) { /* When seed is NULL, reset the initial point and blinding value. */ initial = EC.G.ToGroupElementJacobian(); initial = initial.Negate(); blind = new Scalar(1); } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ blind.WriteToSpan(nonce32); /* Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, * and guards against weak or adversarial seeds. This is a simpler and safer interface than * asking the caller for blinding values directly and expecting them to retry on failure. */ nonce32.CopyTo(keydata); if (seed32 != null) { seed32.AsSpan().CopyTo(keydata.Slice(32, 32)); } else { keydata = keydata.Slice(0, 32); } rng.Initialize(keydata); keydata.Clear(); /* Retry for out of range results to achieve uniformity. */ do { rng.Generate(nonce32); retry = !FE.TryCreate(nonce32, out s); retry |= s.IsZero; } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ /* Randomize the projection to defend against multiplier sidechannels. */ initial = initial.Rescale(s); FE.Clear(ref s); do { rng.Generate(nonce32); b = new Scalar(nonce32, out int overflow); retry = overflow == 1; /* A blinding value of 0 works, but would undermine the projection hardening. */ retry |= b.IsZero; } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ rng.Dispose(); nonce32.Fill(0); gb = MultGen(b); b = b.Negate(); blind = b; initial = gb; Scalar.Clear(ref b); GEJ.Clear(ref gb); }