/// Verify the transaction proof validity. Entails handling the commitment /// as a public key and checking the signature verifies with the fee as /// message. public void Verify(Secp256K1 secp) { var msg = Message.from_slice(TransactionHelper.kernel_sig_msg(Fee, LockHeight)); var sig = Signiture.from_der(secp, ExcessSig); secp.verify_from_commit(msg, sig, Excess); }
/// The verification for a MimbleWimble transaction involves getting the /// excess of summing all commitments and using it as a public key /// to verify the embedded signature. The rational is that if the values /// sum to zero as they should in r.G + v.H then only k.G the excess /// of the sum of r.G should be left. And r.G is the definition of a /// public key generated using r as a private key. public TxKernel verify_sig(Secp256K1 secp) { var rsum = this.sum_commitments(secp); var msg = Message.from_slice(TransactionHelper.kernel_sig_msg(Fee, LockHeight)); var sig = Signiture.from_der(secp, ExcessSig); // pretend the sum is a public key (which it is, being of the form r.G) and // verify the transaction sig with it // // we originally converted the commitment to a key_id here (commitment to zero) // and then passed the key_id to secp.verify() // the secp api no longer allows us to do this so we have wrapped the complexity // of generating a public key from a commitment behind verify_from_commit secp.verify_from_commit(msg, sig, rsum); var kernel = new TxKernel { Features = KernelFeatures.DefaultKernel, Excess = rsum, ExcessSig = ExcessSig, Fee = Fee, LockHeight = LockHeight }; Log.Debug( "tx verify_sig: fee - {fee}, lock_height - {lock_height}", kernel.Fee, kernel.LockHeight ); return(kernel); }
private static void Check_lax_sig(string expr) { var secp = Secp256K1.WithoutCaps(); var sigBytes = HexUtil.from_hex(expr); var sig = Signiture.from_der/*_lax*/ (secp, sigBytes); Assert.NotEmpty(sig.Value); }
/// <summary> /// Resolves the parameter indicated by the <paramref name="sequence"/> to it's defining type. /// </summary> /// <param name="sequence">The sequence in the parameter list.</param> /// <returns>Null if it could not be resolved otherwise the TypeRef for the parameter.</returns> public TypeRef ResolveParameter(int sequence) { TypeRef resolvedType = null; // zero indicates the return parameter for a method, this is handled differently if (sequence != 0) { ParamSignatureToken token = Signiture.GetParameterTokens()[sequence - 1]; return(token.ResolveParameter(Assembly, Parameters[sequence - 1])); } return(resolvedType); }
public void Test_bad_slice() { var s = Secp256K1.New(); var ex = Assert.Throws <Exception>(() => { Signiture.from_der(s, new byte[Constants.Constants.MaxSignatureSize + 1]); }); Assert.Equal("InvalidSignature", ex.Message); ex = Assert.Throws <Exception>(() => { Signiture.from_der(s, new byte[Constants.Constants.MaxSignatureSize]); }); Assert.Equal("InvalidSignature", ex.Message); ex = Assert.Throws <Exception>(() => { Message.from_slice(new byte[Constants.Constants.MessageSize - 1]); }); Assert.Equal("InvalidMessage", ex.Message); ex = Assert.Throws <Exception>(() => { Message.from_slice(new byte[Constants.Constants.MessageSize + 1]); }); Assert.Equal("InvalidMessage", ex.Message); Message.from_slice(new byte[Constants.Constants.MessageSize]); }
public void Signature_serialize_roundtrip() { var s = Secp256K1.New(); s.Randomize(RandomNumberGenerator.Create()); for (var i = 0; i <= 100; i++) { var msgBytes = ByteUtil.Get_random_bytes(RandomNumberGenerator.Create(), 32); var msg = Message.from_slice(msgBytes); var kp = s.generate_keypair(RandomNumberGenerator.Create()); var sk = kp.secretKey; var sig1 = s.Sign(msg, sk); var der = sig1.serialize_der(s); var sig2 = Signiture.from_der(s, der); Assert.Equal(sig1.Value, sig2.Value); var compact = sig1.serialize_compact(s); var sig3 = Signiture.from_compact(s, compact); Assert.Equal(sig1.Value, sig3.Value); //round_trip_serde!(sig1); var ex = Assert.Throws <Exception>(() => { Signiture.from_compact(s, der); }); Assert.Equal("InvalidSignature", ex.Message); ex = Assert.Throws <Exception>(() => { Signiture.from_compact(s, compact.Take(5).ToArray()); }); Assert.Equal("InvalidSignature", ex.Message); ex = Assert.Throws <Exception>(() => { Signiture.from_der(s, compact); }); Assert.Equal("InvalidSignature", ex.Message); ex = Assert.Throws <Exception>(() => { Signiture.from_der(s, der.Take(5).ToArray()); }); Assert.Equal("InvalidSignature", ex.Message); } }
public void Test_low_s() { // nb this is a transaction on testnet // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 // input number 3 var sigBytes = HexUtil.from_hex("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); var pkBytes = HexUtil.from_hex("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43"); var msgBytes = HexUtil.from_hex("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); var secp = Secp256K1.New(); var sig = Signiture.from_der(secp, sigBytes); var pk = PublicKey.from_slice(secp, pkBytes); var msg = Message.from_slice(msgBytes); // without normalization we expect this will fail var ex = Assert.Throws <Exception>(() => { secp.Verify(msg, sig, pk); }); Assert.Equal("IncorrectSignature", ex.Message); // after normalization it should pass sig.normalize_s(secp); secp.Verify(msg, sig, pk); }
/// *** This is a temporary work-around. *** /// We do not know which of the two possible public keys from the commit to use, /// so here we try both of them and succeed if either works. /// This is sub-optimal in terms of performance. /// I believe apoelstra has a strategy for fixing this in the secp256k1-zkp lib. public static void verify_from_commit(this Secp256K1 self, Message msg, Signiture sig, Commitment commit) { if (self.Caps != ContextFlag.Commit) { throw new Exception("IncapableContext"); } // If we knew which one we cared about here we would just use it, // but for now return both so we can try them both. var pubkeys = commit.to_two_pubkeys(self); // Attempt to verify with the first public key, // if verify fails try the other one. // The first will fail on average 50% of the time. try { self.Verify(msg, sig, pubkeys[0]); } catch (Exception) { self.Verify(msg, sig, pubkeys[1]); } }