private static bool Secp256K1EcdsaSigSign(EcmultGenContext ctx, Scalar sigr, Scalar sigs, Scalar seckey, Scalar message, Scalar nonce, out byte recid) { var numArray = new byte[32]; var r1 = new Ge(); var scalar = new Scalar(); var overflow = false; GeJ r2; EcMultGen.secp256k1_ecmult_gen(ctx, out r2, nonce); Group.SetGeJ(r1, r2); Field.Normalize(r1.X); Field.Normalize(r1.Y); Field.GetB32(numArray, r1.X); Scalar.SetB32(sigr, numArray, ref overflow); recid = (byte)((overflow ? 2 : 0) | (Field.IsOdd(r1.Y) ? 1 : 0)); Scalar.Mul(scalar, sigr, seckey); Scalar.Add(scalar, scalar, message); Scalar.Inverse(sigs, nonce); Scalar.Mul(sigs, sigs, scalar); Scalar.Clear(scalar); Group.secp256k1_gej_clear(r2); Group.secp256k1_ge_clear(r1); if (Scalar.IsZero(sigs)) { return(false); } if (Scalar.IsHigh(sigs)) { Scalar.Negate(sigs, sigs); recid ^= (byte)1; } return(true); }
public static void secp256k1_ecmult_gen(EcmultGenContext ctx, out GeJ r, Scalar gn) { Ge ge = new Ge(); GeStorage geStorage = new GeStorage(); r = ctx.Initial.Clone(); Scalar r1 = new Scalar(); Scalar.Add(r1, gn, ctx.Blind); ge.Infinity = false; for (int index1 = 0; index1 < 64; ++index1) { uint bits = r1.GetBits(index1 * 4, 4); for (int index2 = 0; index2 < 16; ++index2) { Group.StorageCmov(geStorage, ctx.Prec[index1][index2], (long)index2 == (long)bits); } Group.FromStorage(ge, geStorage); Group.GeJAddGe(r, r, ge); } Group.secp256k1_ge_clear(ge); Scalar.Clear(r1); }
public uint256 BlindMessage(uint256 message, PubKey rpubkey, PubKey signerPubKey) { var ctx = new ECMultGenContext(); int overflow; Span <byte> tmp = stackalloc byte[32]; if (!Context.Instance.TryCreatePubKey(signerPubKey.ToBytes(), out var signerECPubkey)) { throw new FormatException("Invalid signer pubkey."); } if (!Context.Instance.TryCreatePubKey(rpubkey.ToBytes(), out var rECPubKey)) { throw new FormatException("Invalid r pubkey."); } var P = signerECPubkey.Q; var R = rECPubKey.Q.ToGroupElementJacobian(); var t = FE.Zero; retry: RandomUtils.GetBytes(tmp); _v = new Scalar(tmp, out overflow); if (overflow != 0 || _v.IsZero) { goto retry; } RandomUtils.GetBytes(tmp); _w = new Scalar(tmp, out overflow); if (overflow != 0 || _v.IsZero) { goto retry; } var A1 = ctx.MultGen(_v); var A2 = _w * P; var A = R.AddVariable(A1, out _).AddVariable(A2, out _).ToGroupElement(); t = A.x.Normalize(); if (t.IsZero) { goto retry; } using (var sha = new SHA256()) { message.ToBytes(tmp, false); sha.Write(tmp); t.WriteToSpan(tmp); sha.Write(tmp); sha.GetHash(tmp); } _c = new Scalar(tmp, out overflow); if (overflow != 0 || _c.IsZero) { goto retry; } var cp = _c.Add(_w.Negate(), out overflow); // this is sent to the signer (blinded message) if (cp.IsZero || overflow != 0) { goto retry; } cp.WriteToSpan(tmp); return(new uint256(tmp)); }
// [Fact(Skip = "Abs is unmanaged currently")] public void AbsBigInteger() // => Assert.Equal(new BigInteger(5), Scalar.Abs(new BigInteger(-5))); [Fact] public void AddComplex() => Assert.Equal(new Complex(109, 5), Scalar.Add(new Complex(10, 5), 99));
[Fact] public void AddBigInteger() => Assert.Equal(new BigInteger(100), Scalar.Add(BigInteger.One, 99));
public void Process(MusigPubNonce combinedNonce) { if (processed_nonce) { throw new InvalidOperationException($"Nonce already processed"); } var combined_pk = this.SigningPubKey; MusigSessionCache session_cache = new MusigSessionCache(); Span <byte> noncehash = stackalloc byte[32]; Span <byte> sig_template_data = stackalloc byte[32]; Span <byte> combined_pk32 = stackalloc byte[32]; Span <GEJ> summed_nonces = stackalloc GEJ[2]; summed_nonces[0] = combinedNonce.K1.Q.ToGroupElementJacobian(); summed_nonces[1] = combinedNonce.K2.Q.ToGroupElementJacobian(); combined_pk.WriteToSpan(combined_pk32); /* Add public adaptor to nonce */ if (adaptor != null) { summed_nonces[0] = summed_nonces[0].AddVariable(adaptor.Q); } var combined_nonce = secp256k1_musig_process_nonces_internal( this.ctx.EcMultContext, noncehash, summed_nonces, combined_pk32, msg32); session_cache.B = new Scalar(noncehash); ECXOnlyPubKey.secp256k1_xonly_ge_serialize(sig_template_data, ref combined_nonce); var rx = combined_nonce.x; /* Negate nonce if Y coordinate is not square */ combined_nonce = combined_nonce.NormalizeYVariable(); /* Store nonce parity in session cache */ session_cache.CombinedNonceParity = combined_nonce.y.IsOdd; /* Compute messagehash and store in session cache */ ECXOnlyPubKey.secp256k1_musig_compute_messagehash(noncehash, sig_template_data, combined_pk32, msg32); session_cache.E = new Scalar(noncehash); /* If there is a tweak then set `msghash` times `tweak` to the `s`-part of the sig template.*/ Scalar s = Scalar.Zero; if (is_tweaked) { Scalar e = session_cache.E; if (!ECPrivKey.secp256k1_eckey_privkey_tweak_mul(ref e, scalar_tweak)) { throw new InvalidOperationException("Impossible to sign (secp256k1_eckey_privkey_tweak_mul is false)"); } if (pk_parity) { e = e.Negate(); } s = s.Add(e); } SessionCache = session_cache; Template = new SecpSchnorrSignature(rx, s); processed_nonce = true; this.combinedNonce = combinedNonce; }