public void Invalid_secret_key() { var s = Secp256K1.New(); // Zero var ex = Assert.Throws <Exception>(() => { SecretKey.From_slice(s, ByteUtil.Get_bytes(0, 32)); }); Assert.Equal("InvalidSecretKey", ex.Message); // -1 ex = Assert.Throws <Exception>(() => { SecretKey.From_slice(s, ByteUtil.Get_bytes(0xff, 32)); }); Assert.Equal("InvalidSecretKey", ex.Message); // Top of range var sk1 = SecretKey.From_slice(s, new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40 }); Assert.NotEmpty(sk1.Value); // One past top of range Assert.Throws <Exception>(() => { SecretKey.From_slice(s, new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }); }); }
protected override void ValidateMessage(ChannelAnnouncementMessage message, byte[] rawData) { var witness = SHA256.ComputeHash(SHA256.ComputeHash(rawData.SubArray(258, rawData.Length - 258))); if (!Secp256K1.VerifySignature(witness, message.NodeSignature1, message.NodeId1)) { throw new MessageValidationException(message, "ChannelAnnouncementMessage: Invalid Signature (Node 1)", true); } if (!Secp256K1.VerifySignature(witness, message.NodeSignature2, message.NodeId2)) { throw new MessageValidationException(message, "ChannelAnnouncementMessage: Invalid Signature (Node 2)", true); } if (!Secp256K1.VerifySignature(witness, message.BitcoinSignature1, message.BitcoinKey1)) { throw new MessageValidationException(message, "ChannelAnnouncementMessage: Invalid Signature (Bitcoin Key 1)", true); } if (!Secp256K1.VerifySignature(witness, message.BitcoinSignature2, message.BitcoinKey2)) { throw new MessageValidationException(message, "ChannelAnnouncementMessage: Invalid Signature (Bitcoin Key 2)", true); } if (!message.ChainHash.SequenceEqual(_networkParameters.ChainHash)) { throw new MessageValidationException(message, "ChannelAnnouncementMessage: Invalid chain hash (ChannelAnnouncementMessage)"); } }
public static ProofInfo range_proof_info(this Secp256K1 self, RangeProof proof) { var exp = 0; var mantissa = 0; ulong min = 0; ulong max = 0; var extraCommit = new byte [33]; var success = Proxy.secp256k1_rangeproof_info( self.Ctx, ref exp, ref mantissa, ref min, ref max, proof.Proof, proof.Plen, extraCommit, 0, Constants.Constants.GeneratorH ) == 1; return(new ProofInfo { Success = success, Value = 0, Message = ProofMessage.Empty(), Mlen = 0, Min = min, Max = max, Exp = exp, Mantissa = mantissa }); }
public void Pubkey_from_slice() { var secp256K1 = Secp256K1.New(); var ex = Assert.Throws <Exception>(() => { PublicKey.from_slice(secp256K1, null); }); Assert.Equal("InvalidPublicKey", ex.Message); ex = Assert.Throws <Exception>(() => { PublicKey.from_slice(secp256K1, new byte[] { 1, 2, 3 }); }); Assert.Equal("InvalidPublicKey", ex.Message); var uncompressed = PublicKey.from_slice(secp256K1, new byte[] { 4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188 }); Assert.NotEmpty(uncompressed.Value); var compressed = PublicKey.from_slice(secp256K1, new byte[] { 3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78 }); Assert.NotEmpty(compressed.Value); }
public static ProofRange verify_range_proof(this Secp256K1 self, Commitment commit, RangeProof proof) { ulong min = 0; ulong max = 0; var extraCommit = ByteUtil.Get_bytes(0, 33); var success = Proxy.secp256k1_rangeproof_verify( self.Ctx, ref min, ref max, commit.Value, proof.Proof, proof.Plen, extraCommit, 0, Constants.Constants.GeneratorH ) == 1; if (success) { return new ProofRange { Min = min, Max = max } } ; throw new Exception("InvalidRangeProof"); }
/// Computes the sum of multiple positive and negative blinding factors. public static SecretKey blind_sum(this Secp256K1 self, SecretKey[] positive, SecretKey[] negative) { //var neg = new byte[negative.Length][]; var all = new byte[positive.Length + negative.Length][]; for (var i = 0; i < positive.Length; i++) { all[i] = positive[i].Value; } for (var i = 0; i < negative.Length; i++) { all[positive.Length + i] = negative[i].Value; } var ret = new byte[32]; var err = Proxy.secp256k1_pedersen_blind_sum( self.Ctx, ret, all, all.Length, positive.Length); if (err == 1) { return(SecretKey.From_slice(self, ret)); } // secp256k1 should never return an invalid private throw new Exception("This should never happen!"); }
/// Computes the sum of multiple positive and negative pedersen commitments. public static Commitment commit_sum(this Secp256K1 self, Commitment[] positive, Commitment[] negative) { var pos = new byte[positive.Length][]; for (var i = 0; i < positive.Length; i++) { pos[i] = positive[i].Value; } var neg = new byte[negative.Length][]; for (var i = 0; i < negative.Length; i++) { neg[i] = negative[i].Value; } var ret = Commitment.Blank(); var err = Proxy.secp256k1_pedersen_commit_sum( self.Ctx, ret.Value, pos, pos.Length, neg, neg.Length); if (err == 1) { return(ret); } throw new Exception("IncorrectCommitSum"); }
public void Sign() { var s = Secp256K1.New(); s.Randomize(RandomNumberGenerator.Create()); var one = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; var sk = SecretKey.From_slice(s, one); var msg = Message.from_slice(one); var sig = s.sign_recoverable(msg, sk); var rsig = RecoverableSigniture.From_compact(s, new byte[] { 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89 }, RecoveryId.from_i32(1)); Assert.Equal(sig.Value, rsig.Value); }
public void Test_sign_with_pubkey_from_commitment() { var secp = Secp256K1.WithCaps(ContextFlag.Commit); var blinding = SecretKey.New(secp, RandomNumberGenerator.Create()); var commit = secp.Commit(0, blinding); var msgBytes = ByteUtil.Get_random_bytes(RandomNumberGenerator.Create(), 32); var msg = Message.from_slice(msgBytes); var sig = secp.Sign(msg, blinding); var pubkeys = commit.to_two_pubkeys(secp); // check that we can successfully verify the signature with one of the public keys try { secp.Verify(msg, sig, pubkeys[0]); } catch (Exception) { try { secp.Verify(msg, sig, pubkeys[1]); } catch (Exception ex) { throw new Exception("this is not good", ex); } } }
/// 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); }
/// Return the identifier of the key /// which is the blake2b (10 byte) digest of the PublicKey // corresponding to the underlying SecretKey public Identifier Identifier(Secp256K1 secp) { // get public key from private var keyId = PublicKey.from_secret_key(secp, Key); return(ExtKey.Identifier.From_key_id(secp, keyId)); }
public static ExtendedKey from_slice(Secp256K1 secp, byte[] slice) { // TODO change when ser. ext. size is fixed if (slice.Length != 79) { throw new Exception("InvalidSliceSize"); } var ext = new ExtendedKey { Depth = slice[0] }; var rootKeyBytes = slice.Skip(1).Take(10).ToArray(); ext.RootKeyId = ExtKey.Identifier.From_bytes(rootKeyBytes); var nchildBytes = slice.Skip(11).Take(4).ToArray(); Array.Reverse(nchildBytes); ext.NChild = BitConverter.ToUInt32(nchildBytes, 0); ext.Chaincode = slice.Skip(15).Take(32).ToArray(); var keyBytes = slice.Skip(47).Take(32).ToArray(); ext.Key = SecretKey.From_slice(secp, keyBytes); return(ext); }
/// 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); }
public void GenerateKeyPairTest() { var ecKeyPair = Secp256K1.GenerateKeyPair(); Assert.True(ecKeyPair.HasPrivateKey); Assert.Equal(33, ecKeyPair.PublicKeyCompressed.Length); }
/// Multiplies one secret key by another, modulo the curve order public void Mul_assign(Secp256K1 secp, SecretKey other) { if (Proxy.secp256k1_ec_privkey_tweak_mul(secp.Ctx, Value, other.Value) != 1) { throw new Exception("InvalidSecretKey"); } }
public void Test_commit_sum() { var secp = Secp256K1.WithCaps(ContextFlag.Commit); Commitment Commit(ulong value, SecretKey blinding) { return(secp.Commit(value, blinding)); } var blindA = SecretKey.New(secp, RandomNumberGenerator.Create()); var blindB = SecretKey.New(secp, RandomNumberGenerator.Create()); var commitA = Commit(3, blindA); var commitB = Commit(2, blindB); var blindC = secp.blind_sum(new [] { blindA, blindB }, new SecretKey[] {}); var commitC = Commit(3 + 2, blindC); var commitD = secp.commit_sum(new[] { commitA, commitB }, new Commitment[] { }); Assert.Equal(commitC.Value, commitD.Value); var blindE = secp.blind_sum(new[] { blindA }, new[] { blindB }); var commitE = Commit(3 - 2, blindE); var commitF = secp.commit_sum(new[] { commitA }, new[] { commitB }); Assert.Equal(commitE.Value, commitF.Value); }
public void Sign_and_verify_extreme() { var s = Secp256K1.New(); s.Randomize(RandomNumberGenerator.Create()); // Wild keys: 1, CURVE_ORDER - 1 // Wild msgs: 0, 1, CURVE_ORDER - 1, CURVE_ORDER var wildKeys = new byte[32, 2]; // [[0; 32]; 2]; var wildMsgs = new byte[32, 4]; // [[0; 32]; 4]; wildKeys[0, 0] = 1; wildMsgs[1, 0] = 1; //TODO: Finish here //use constants; //wild_keys[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); //wild_msgs[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); //wild_msgs[2][..].copy_from_slice(&constants::CURVE_ORDER[..]); //wild_keys[1][0] -= 1; //wild_msgs[1][0] -= 1; //for key in wild_keys.iter().map(| k | SecretKey::from_slice(&s, &k[..]).unwrap()) { // for msg in wild_msgs.iter().map(| m | Message::from_slice(&m[..]).unwrap()) { // var sig = s.sign(&msg, &key).unwrap(); // var pk = PublicKey::from_secret_key(&s, &key).unwrap(); // assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); // } //} }
public void Test_verify_commit_sum_one_keys() { var secp = Secp256K1.WithCaps(ContextFlag.Commit); Commitment Commit(ulong value, SecretKey blinding) { return(secp.Commit(value, blinding)); } Assert.True(secp.verify_commit_sum( new[] { Commit(5, SecretKey.OneKey) }, new[] { Commit(5, SecretKey.OneKey) } )); //// we expect this not to verify //// even though the values add up to 0 //// the keys themselves do not add to 0 Assert.False(secp.verify_commit_sum( new[] { Commit(3, SecretKey.OneKey), Commit(2, SecretKey.OneKey) }, new[] { Commit(5, SecretKey.OneKey) })); //// to get these to verify we need to //// use the same "sum" of blinding factors on both sides var twoKey = secp.blind_sum(new [] { SecretKey.OneKey, SecretKey.OneKey }, new SecretKey[] {}); Assert.True(secp.verify_commit_sum( new[] { Commit(3, SecretKey.OneKey), Commit(2, SecretKey.OneKey) }, new[] { Commit(5, twoKey) })); }
/// Taking vectors of positive and negative commitments as well as an /// expected excess, verifies that it all sums to zero. public static bool verify_commit_sum(this Secp256K1 self, Commitment[] positive, Commitment[] negative) { var pos = new byte[positive.Length][]; for (var i = 0; i < positive.Length; i++) { pos[i] = positive[i].Value; } var neg = new byte[negative.Length][]; for (var i = 0; i < negative.Length; i++) { neg[i] = negative[i].Value; } return(Proxy.secp256k1_pedersen_verify_tally( self.Ctx, pos, pos.Length, neg, neg.Length ) == 1); }
public void Test_verify_commit_sum_zero_keys() { var secp = Secp256K1.WithCaps(ContextFlag.Commit); Commitment Commit(ulong value) { var blinding = SecretKey.ZeroKey; return(secp.Commit(value, blinding)); } Assert.True(secp.verify_commit_sum( new Commitment[] {}, new Commitment[] { } )); Assert.True(secp.verify_commit_sum( new[] { Commit(5) }, new[] { Commit(5) })); Assert.True(secp.verify_commit_sum( new[] { Commit(3), Commit(2) }, new[] { Commit(5) } )); Assert.True(secp.verify_commit_sum( new[] { Commit(2), Commit(4) }, new[] { Commit(1), Commit(5) } )); }
public void Test_debug_output() { var s = Secp256K1.New(); var sig = RecoverableSigniture.From_compact(s, new byte[] { 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89 }, RecoveryId.from_i32(1)); //TODO: Finish here Assert.Equal("RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)", $"{sig}"); var msg = Message.from_slice(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 255 }); //TODO: Finish here Assert.Equal("Message(0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fff)", $"{msg}"); }
public void Sign_and_verify_fail() { var s = Secp256K1.New(); s.Randomize(RandomNumberGenerator.Create()); var msgBytes = ByteUtil.Get_random_bytes(RandomNumberGenerator.Create(), 32); var msg = Message.from_slice(msgBytes); var(sk, pk) = s.generate_keypair(RandomNumberGenerator.Create()); var sigr = s.sign_recoverable(msg, sk); var sig = sigr.To_standard(s); var msgBytes2 = ByteUtil.Get_random_bytes(RandomNumberGenerator.Create(), 32); var msg2 = Message.from_slice(msgBytes2); var ex = Assert.Throws <Exception>(() => { s.Verify(msg2, sig, pk); }); Assert.Equal("IncorrectSignature", ex.Message); var recoveredKey = s.Recover(msg2, sigr); Assert.NotEqual(recoveredKey.Value, pk.Value); }
/// Derive an extended key from an extended key public ExtendedKey Derive(Secp256K1 secp, uint n) { var nBytes = BitConverter.GetBytes(n); if (BitConverter.IsLittleEndian) { Array.Reverse(nBytes); } var seed = ByteUtil.Combine(Key.Value, nBytes); var blake2B = new HMACBlake2B(Chaincode, 64 * 8); var derived = blake2B.ComputeHash(seed); var secretKey = SecretKey.From_slice(secp, derived.Take(32).ToArray()); secretKey.Add_assign(secp, Key); // TODO check if key != 0 ? var chainCode = derived.Skip(32).Take(32).ToArray(); return(new ExtendedKey { Depth = (byte)(Depth + 1), RootKeyId = Identifier(secp), NChild = n, Chaincode = chainCode, Key = secretKey }); }
public void Extkey_derivation() { // TODO More test vectors var s = Secp256K1.New(); var seed = HexUtil.from_hex("000102030405060708090a0b0c0d0e0f"); var extk = ExtendedKey.from_seed(s, seed); var derived = extk.Derive(s, 0); var sec = HexUtil.from_hex("d75f70beb2bd3b56f9b064087934bdedee98e4b5aae6280c58b4eff38847888f" ); var secretKey = SecretKey.From_slice(s, sec); var chaincode = HexUtil.from_hex("243cb881e1549e714db31d23af45540b13ad07941f64a786bbf3313b4de1df52"); var rootKeyId = HexUtil.from_hex("83e59c48297b78b34b73"); var identifier = HexUtil.from_hex("0185adb4d8b730099c93"); const int depth = 1; const uint nChild = 0; Assert.Equal(derived.Key.Value, secretKey.Value); Assert.Equal( derived.Identifier(s).Value, Identifier.From_bytes(identifier).Value ); Assert.Equal( derived.RootKeyId.Value, Identifier.From_bytes(rootKeyId).Value ); Assert.Equal(derived.Chaincode, chaincode); Assert.Equal(derived.Depth, depth); Assert.Equal(derived.NChild, nChild); }
private Keychain(Secp256K1 secp, ExtendedKey extkey, Dictionary <string, SecretKey> keyOverrides, ConcurrentDictionary <string, uint> keyDerivationCache) { Secp = secp; Extkey = extkey; KeyOverrides = keyOverrides; KeyDerivationCache = keyDerivationCache; }
public void Test_to_two_pubkeys() { var secp = Secp256K1.WithCaps(ContextFlag.Commit); var blinding = SecretKey.New(secp, RandomNumberGenerator.Create()); var commit = secp.Commit(5, blinding); Assert.Equal(2, commit.to_two_pubkeys(secp).Length); }
public void VerifyInvalidSignatureTest() { byte[] witness = "6b32bec9a3aeda57863bdc41d880f47944bf234a2628b084b46d4351d88195d2".HexToByteArray(); byte[] signature = "fe531b7551494341543459bce877275b7c4f2e7ad416279fc7aa732af90ccb9339fa3c2d59dd2c8b4cc68957d59bfc5186d164739a8b37d450ab1fcb50700322".HexToByteArray(); ECKeyPair publicKey = new ECKeyPair("03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134", false); Assert.False(Secp256K1.VerifySignature(witness, signature, publicKey)); }
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); }
protected override void ValidateMessage(NodeAnnouncementMessage message, byte[] rawData) { var witness = SHA256.ComputeHash(SHA256.ComputeHash(rawData.SubArray(66, rawData.Length - 66))); if (!Secp256K1.VerifySignature(witness, message.Signature, message.NodeId)) { throw new MessageValidationException(message, "NodeAnnouncementMessage: Invalid Signature", true); } }
/// Validates all the elements in a block that can be checked without /// additional data. Includes commitment sums and kernels, Merkle /// trees, reward, etc. /// /// TODO - performs various verification steps - discuss renaming this to "verify" public void Validate(Secp256K1 secp) { if (Consensus.Exceeds_weight((uint)Inputs.Length, (uint)Outputs.Length, (uint)Kernels.Length)) { throw new BlockErrorException(BlockError.WeightExceeded); } verify_coinbase(); verify_kernels(secp, false); }