public void dlc_schnorr_test() { var arr = JArray.Parse(File.ReadAllText("Data/dlc_schnorr_test.json")); foreach (var vector in arr.OfType <JObject>()) { var privKey = Context.Instance.CreateECPrivKey(Encoders.Hex.DecodeData(vector["inputs"]["privKey"].Value <string>())); var privNonce = Context.Instance.CreateECPrivKey(Encoders.Hex.DecodeData(vector["inputs"]["privNonce"].Value <string>())); var hash = Encoders.Hex.DecodeData(vector["inputs"]["msgHash"].Value <string>()); var pubkey = Context.Instance.CreateXOnlyPubKey(Encoders.Hex.DecodeData(vector["pubKey"].Value <string>())); var nonce = new SchnorrNonce(Context.Instance.CreateXOnlyPubKey(Encoders.Hex.DecodeData(vector["pubNonce"].Value <string>()))); Assert.Equal(nonce, privNonce.CreateSchnorrNonce()); Assert.Equal(pubkey, privKey.CreateXOnlyPubKey()); Assert.True(new OracleInfo(pubkey, nonce).TryComputeSigpoint(new DiscreteOutcome(hash), out var sigpoint)); Assert.True(Context.Instance.TryCreatePubKey(Encoders.Hex.DecodeData(vector["sigPoint"].Value <string>()), out var expectedSigPoint)); Assert.Equal(expectedSigPoint, sigpoint); Assert.True(SecpSchnorrSignature.TryCreate(Encoders.Hex.DecodeData(vector["signature"].Value <string>()), out var expectedSig)); Assert.Equal(expectedSig.rx, nonce.PubKey.Q.x); var expectedAttestation = expectedSig.s; var sig = privKey.SignBIP340(hash, new PrecomputedNonceFunctionHardened(privNonce.ToBytes())); Assert.Equal(expectedSig.rx, sig.rx); Assert.Equal(expectedSig.s, sig.s); } }
public SecpSchnorrSignature CreateSchnorrSignature(ECPrivKey key) { if (!SecpSchnorrSignature.TryCreate(PubKey.Q.x, key.sec, out var sig) || sig is null) { throw new InvalidOperationException("Invalid schnorr signature"); } return(sig); }
public void BIP340Tests() { var content = File.ReadAllText("data/bip340_vectors.csv"); var lines = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray(); foreach (var line in lines) { var fields = line.Split(','); if (fields[0] == "5" || fields[0] == "14") // pubkey not on the field { Assert.False(Context.Instance.TryCreateXOnlyPubKey(Encoders.Hex.DecodeData(fields[2]), out _)); continue; } var expectedPubKey = Context.Instance.CreateXOnlyPubKey(Encoders.Hex.DecodeData(fields[2])); if (fields[1] != "") { var key = Context.Instance.CreateECPrivKey(Encoders.Hex.DecodeData(fields[1])); var actualPubKey = key.CreateXOnlyPubKey(); Assert.Equal(expectedPubKey, actualPubKey); } var msg = Encoders.Hex.DecodeData(fields[4]); if (fields[0] == "12" || fields[0] == "13") // invalid sig { Assert.False(SecpSchnorrSignature.TryCreate(Encoders.Hex.DecodeData(fields[5]), out _)); continue; } Assert.True(SecpSchnorrSignature.TryCreate(Encoders.Hex.DecodeData(fields[5]), out var sig)); var actual = expectedPubKey.SigVerifyBIP340(sig, msg); var expectedGoodSig = fields[6] == "TRUE"; Assert.Equal(expectedGoodSig, actual); if (fields[1] != "") { var aux = Encoders.Hex.DecodeData(fields[3]); var key = Context.Instance.CreateECPrivKey(Encoders.Hex.DecodeData(fields[1])); var actualSig = key.SignBIP340(msg, aux); Assert.True(expectedPubKey.SigVerifyBIP340(actualSig, msg)); if (expectedGoodSig) { var buf = new byte[64]; actualSig.WriteToSpan(buf); Assert.Equal(fields[5].ToLowerInvariant(), Encoders.Hex.EncodeData(buf)); } } } }
public ECPrivKey Extract(SecpSchnorrSignature signature, MusigPartialSignature[] partialSignatures) { if (partialSignatures == null) { throw new ArgumentNullException(nameof(partialSignatures)); } if (SessionCache is null) { throw new InvalidOperationException("You need to run MusigContext.Process first"); } var t = signature.s; t = t.Negate(); foreach (var sig in partialSignatures) { t = t + sig.E; } if (!SessionCache.FinalNonceParity) { t = t.Negate(); } return(new ECPrivKey(t, this.ctx, true)); }
public SecpSchnorrSignature Adapt(SecpSchnorrSignature signature, ECPrivKey adaptorSecret) { if (adaptorSecret == null) { throw new ArgumentNullException(nameof(adaptorSecret)); } if (signature == null) { throw new ArgumentNullException(nameof(signature)); } if (!processed_nonce || SessionCache is null) { throw new InvalidOperationException("You need to run MusigContext.Process first"); } var s = signature.s; var t = adaptorSecret.sec; if (SessionCache.FinalNonceParity) { t = t.Negate(); } s = s + t; return(new SecpSchnorrSignature(signature.rx, s)); }
public static bool TryExtractPrivateKey(this ECPubKey pubKey, ReadOnlySpan <byte> msg1, SecpSchnorrSignature sig1, ReadOnlySpan <byte> msg2, SecpSchnorrSignature sig2, out ECPrivKey?key) { key = null; if (msg1.Length != 32) { return(false); } if (msg2.Length != 32) { return(false); } if (msg1.SequenceCompareTo(msg2) == 0) { return(false); } Span <byte> sig64 = stackalloc byte[64]; sig1.WriteToSpan(sig64); Span <byte> pk_buf = stackalloc byte[32]; Span <byte> buf = stackalloc byte[32]; pubKey.Q.x.WriteToSpan(pk_buf); using var sha = new SHA256(); sha.InitializeTagged(TAG_BIP0340Challenge); sha.Write(sig64.Slice(0, 32)); sha.Write(pk_buf); sha.Write(msg1); sha.GetHash(buf); var n1 = new Scalar(buf, out _); sig2.WriteToSpan(sig64); sha.InitializeTagged(TAG_BIP0340Challenge); sha.Write(sig64.Slice(0, 32)); sha.Write(pk_buf); sha.Write(msg2); sha.GetHash(buf); var n2 = new Scalar(buf, out _); var s = sig2.s + sig1.s.Negate(); var n = (n2 + n1.Negate()); var sk = s * n.Inverse(); if (pubKey.Q.y.IsOdd) { sk = sk.Negate(); } if (!pubKey.ctx.TryCreateECPrivKey(sk, out key)) { return(false); } return(true); }