Esempio n. 1
1
		//https://github.com/libbitcoin/libbitcoin/blob/master/test/stealth.cpp
		public void BitFieldCorrectlyMatchData()
		{
			var bit = (uint)1358086238;
			var o = new BitField(bit, 32);
			var tests = new[]
			{
				new
				{
					Encoded = (uint)0x691cf48b,
					BitCount = 27,
					Data = "8bf42c79",
					Match = false
				},
				new
				{
					Encoded = (uint)0x691cf48b,
					BitCount = 27,
					//Data miss match (1 instead of 2)
					Data = "8bf41c79",
					Match = true
				}
			};
			foreach(var test in tests)
			{
				BitField field = new BitField(test.Encoded, test.BitCount);
				Assert.Equal(test.Match, field.Match(Utils.ToUInt32(TestUtils.ParseHex(test.Data), true)));
			}
		}
Esempio n. 2
0
		public void CanVerifySignature()
		{
			var tests = new[]
			{
				new
				{
					Address = "15jZVzLc9cXz5PUFFda5A4Z7kZDYPg2NnL",
					PrivateKey = "L3TiCqmvPkXJpzCCZJuhy6wQtJZWDkR1AuqFY4Utib5J5XLuvLdZ",
					Message = "This is an example of a signed message.",
					Signature = "H6sliOnVrD9r+J8boZAKHZwBIW2zLiD72IfTIF94bfZhBI0JdMu9AM9rrF7P6eH+866YvM4H9xWGVN4jMJZycFU="
				},
				new
				{
					Address = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ",
					PrivateKey = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj",
					Message = "hello world",
					Signature = "G+dnSEywl3v1ijlWXvpY6zpu+AKNNXJcVmrdE35m0mMlzwFzXDiNg+uZrG9k8mpQL6sjHKrlBoDNSA+yaPW7PEA="
				},
				new
				{
					Address = "1Q1wVsNNiUo68caU7BfyFFQ8fVBqxC2DSc",
					PrivateKey = null as string,
					Message = "Localbitcoins.com will change the world",
					Signature = "IJ/17TjGGUqmEppAliYBUesKHoHzfY4gR4DW0Yg7QzrHUB5FwX1uTJ/H21CF8ncY8HHNB5/lh8kPAOeD5QxV8Xc="
				},
				new
				{
					Address = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
					PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
					Message = "This is an example of a signed message2",
					Signature = "G8YNwlo+I36Ct+hZKGSBFl3q8Kbx1pxPpwQmwdsG85io76+DUOHXqh/DfBq+Cn2R3C3dI//g3koSjxy7yNxJ9m8="
				},
				new
				{
					Address = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
					PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
					Message = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
					Signature = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
				},
			};


			foreach(var test in tests)
			{
				if(test.PrivateKey != null)
				{
					var secret = Network.Main.CreateBitcoinSecret(test.PrivateKey);
					var signature = secret.PrivateKey.SignMessage(test.Message);
					Assert.True(((BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.Address)).VerifyMessage(test.Message, signature));
					Assert.True(secret.PubKey.VerifyMessage(test.Message, signature));
				}
				BitcoinPubKeyAddress address = (BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.Address);
				Assert.True(address.VerifyMessage(test.Message, test.Signature));
				Assert.True(!address.VerifyMessage("bad message", test.Signature));
			}
		}
Esempio n. 3
0
		//https://wiki.unsystem.net/index.php/DarkWallet/Stealth#Bitfield_value
		public void BitFieldCorrectlyInterpreted()
		{

			var tests = new[]
			{
				new
				{
					Encoded = (uint)1763505291,
					BitCount = 32,
					Raw = "8bf41c69"
				},
				new
				{
					Encoded = (uint)1,
					BitCount = 8,
					Raw = "0100"
				},
				new
				{
					Encoded = (uint)1,
					BitCount = 7,
					Raw = "01"
				}
			};

			foreach(var test in tests)
			{
				var bitField = new BitField(test.Encoded, test.BitCount);
				Assert.Equal(TestUtils.ParseHex(test.Raw), bitField.GetRawForm());
				Assert.Equal(test.Encoded, bitField.GetEncodedForm());

				bitField = new BitField(TestUtils.ParseHex(test.Raw), test.BitCount);
				Assert.Equal(test.Encoded, bitField.GetEncodedForm());
				Assert.Equal(TestUtils.ParseHex(test.Raw), bitField.GetRawForm());
			}
		}
Esempio n. 4
0
		//https://github.com/libbitcoin/libbitcoin/blob/master/test/stealth.cpp
		public void BitFieldCanFetchTransaction()
		{
			var tests = new[]
			{
				new
				{
					Encoded = "deadbeef",
					BitCount = 5,
					Transaction = "0100000001bd365d65c6eeee2d3ae29c6e1b0fb22f70f0135220eac1273c92a13b6039ecdf000000006b48304502202551626a52a088ea585f2aaa8afe1c1b7bc52ea8e577e149f20f0f5f2fc54485022100913643c6a1e54b5284d1c108519d9243213373256ff95ab6c7e3d162175c9e28012102881c1427e826f230246197f7f693f1c923ad2afea1dad901d1c870f7e310c895ffffffff020000000000000000286a2606ab3099ae0359222b4a2dd9a21ebd70331794fb05b0bd605bd9660fdf895906b1a227edcbec306c3402000000001976a9142f62432f367dc3cf67e68f814cc2a3ed5b2e8cec88ac00000000",
				}
				,new
				{
					Encoded = "deadbeef",
					BitCount = 5,
					Transaction = "01000000028d8d968818e464db9dc876eb4edd59e62913d849603ba10afe033159b55652dc010000006b483045022100992e7ce4516cdabffae823557f5854c6ca7a424cc2fe7a9b94f439ecca839f84022025b871cf499f7b0eebcf751a83e7ffe9473b6c5227f95d9989ef8e98937112760121038795ff1d07ef7092e03d612f187d1281705b36d0c11ecf4b11167beb7efc3437ffffffff723372d920d8eaa6bd1fe6ec5adaf913b6d8a48655acded49a3f09191cdf9f3a010000006a47304402206f6ca054242fe5b410d743ae238049799eccdd88637d555ad48d8da1a854bd0802201b13217d0a6a7cf3467074aa8964f3f365541304142503d91813baa0117d1a8101210258cedc6e590493838c612a394d53ffbb283638f9d1d49e1c571b15a885f405d9ffffffff05f0874b00000000001976a914cd08dcd94ba88488b4c02c82fc11fc63fee4e30c88acc0e1e400000000001976a9148784cbfe99e86135d40d276c58fcbbf37af1b48e88ac0000000000000000286a260689d0267d021cc402cf764f2c88138028b6d5c0f06d5caa34edffc1d2286048f0162756ebf1f0874b00000000001976a914923d77bbdd3d29dd4844a51629514bac9e8a2c4d88aca30c0000000000001976a9143aaa9db7a3fbc5dcc9d121a157bf63aaaee9d8f588ac00000000",
				},
				new
				{
					Encoded = "deadbeef",
					BitCount = 5,
					Transaction = "010000000288b6952f8357b5a8271f6c0608ea779549bf0a9ae72213ce433f7a9c90190be6000000006b4830450221008b1b7369d7bf8a1dd99e6a260ef969840d633ba81fc379bf4f5469afd3b288e2022077e21dd12c1d8b2a4ab2e58fb0113b9e3bb77db4439483f7a8311cac3ad6ce9a012102b0c2eb0cc505a4c9fb62df8a7fcdcc00ddab43ff5752ebc51a0dae11fbfb0648ffffffff4ca2f8960e17b56e690739158994ed23427ffc08445ba3223edacb322db12d4b000000006b483045022100f94d50d846d85a545693574f9e1a680a858f085257c827cd8b211df8d27c558202201bca0407ad67960937999a88c95e52417442703a16036bbe55f071cdff804f69012102884d0c845bff3158e88033bce236cdbfeadba0a7e7381258379612f355681d6dffffffff052f750000000000001976a914a34a179dc97cbb84992d2960ee240b56f1b2ae3088acbca15400000000001976a914139e314f94a8e4fc2864ef2544e7640ba033725b88ac0000000000000000286a26061d6b629c024c7daf682da4afd61aadf401fae316a265c3244d912b375a75b55551d52a583f2f750000000000001976a9142888cb9f0b0f489106bc13f56fdd2ceec1b6883788ac51c30000000000001976a91404316e7db781481d1419feda2c8d7fa9f7b68a6e88ac00000000",
				},
				
			};



			foreach(var test in tests)
			{
				var field = new BitField(TestUtils.ParseHex(test.Encoded), test.BitCount);
				Transaction transaction = new Transaction();
				transaction.FromBytes(TestUtils.ParseHex(test.Transaction));

				var stealthOutput = field.GetPayments(transaction).FirstOrDefault();
				Assert.NotNull(stealthOutput);

				Assert.True(field.Match(stealthOutput.Metadata.BitField));
			}
		}
Esempio n. 5
0
		public void CanCreatePayment()
		{
			var tests = new[]
			{
				new CanCreatePaymentData
				{
					//sx stealth-newkey
					StealthAddress = "vJmtjxSDxNPXL4RNapp9ARdqKz3uJyf1EDGjr1Fgqs9c8mYsVH82h8wvnA4i5rtJ57mr3kor1EVJrd4e5upACJd588xe52yXtzumxj",

					ScanSecret = "3e49e7257cb31db997edb1cf8299af0f37e2663e2260e4b8033e49d39a6d02f2",
					ScanPubKey = "025e58a31122b38c86abc119b9379fe247410aee87a533f9c07b189aef6c3c1f52",

					SpendSecret = "aa3db0cfb3edc94de4d10f873f8190843f2a17484f6021a95a7742302c744748",
					SpendPubKey = "03616562c98e7d7b74be409a787cec3a912122f3fb331a9bee9b0b73ce7b9f50af",

					//sx newkey | sx wif-to-secret
					EphemSecret = "9e63abaf8dcd5ea3919e6de0b6c544e00bf51bf92496113a01d6e369944dc091",
					EphemPubKey = "03403d306ec35238384c7e340393335f9bc9bb4a2e574eb4e419452c4ea19f14b0",

					//sx steatlh-uncover-secret [EphemPubKey] [ScanSecret] [SpendSecret] 
					StealthSecret = "4e422fb1e5e1db6c1f6ab32a7706d368ceb385e7fab098e633c5c5949c3b97cd",
					//sx stealth-initiate [EphemSecret] [ScanPubKey] [SpendPubKey] (for sender)
					//or 
					//sx stealth-uncover [EphemPubKey] [ScanSecret] [SpendPubKey]  (for receiver)
					StealthPubKey = "02726112ad39cb6bf848b1b1ef30b88e35286bf99f746c2be575f96c0e02a9357c",
				},

				//Need padding for to find the stealth secret
				new CanCreatePaymentData{
					StealthAddress = "vJmyTEybwCKz7W8y6vP62jo7RoyfLneiANcPLBBNYwn98EXzQRStMKqKGRiZhqscuQ6WKy2J3U3zfx72V3b2J6YvxxBcxUj4XMDsw7",
					ScanSecret = "2f517d81cf30e47dbf4809321275bbfd92192af81a6141a17aa53e40bd28fe36",
					ScanPubKey = "039d91ae0eebea6dc500fb57b704abce3d3fa700cc762a52bc5dcaee27770a8402",
					SpendSecret = "71e33219884fc27011f8da9adcc730f0c2e940759bdb1b615764492bce04fcea",
					SpendPubKey = "021a3d5b40ec83fc58b5a23207eb9c99b741d8f0e9f8b80f04f49cec915b540c40",
					EphemSecret = "578ffe42c0fbfb324a31f41dbbcd8b1f910ce2f4d803444a83b18ae9f8ccd97e",
					EphemPubKey = "03c190be0a1c6e50577b3dd637b1fff9344de31c2544ff3d815535c0515711150f",
					StealthSecret = "006d138b4bcef0f09c8784c0cc68f2be4497a1a822d8d7b0519c5c0378b5cb45",
					StealthPubKey = "0223a99278a5279ea93718503a42377067e72960eb808d8bff6defdd95d4feff76"
				}
			};

			foreach(var test in tests)
			{
				var scan = AssertKeys(test.ScanSecret, test.ScanPubKey);
				var spend = AssertKeys(test.SpendSecret, test.SpendPubKey);
				var ephem = AssertKeys(test.EphemSecret, test.EphemPubKey);
				var stealth = AssertKeys(test.StealthSecret, test.StealthPubKey);

				var address = spend.PubKey.CreateStealthAddress(scan.PubKey, Network.Main);
				Assert.Equal(test.StealthAddress, address.ToString());
				//Try roundtrip
				address = new BitcoinStealthAddress(address.ToBytes(), Network.Main);
				Assert.Equal(test.StealthAddress, address.ToString());

				var payment = address.CreatePayment(ephem);
				var generatedKey = spend.Uncover(scan, payment.Metadata.EphemKey);
				if(stealth != null)
				{
					Assert.Equal(stealth.PubKey.Hash, payment.StealthKeys[0].ID);
					Assert.Equal(stealth.ToBytes(), generatedKey.ToBytes());
				}
				var uncoveredSender = spend.PubKey.UncoverSender(ephem, scan.PubKey);
				var uncovertedReceiver = spend.PubKey.UncoverReceiver(scan, ephem.PubKey);

				AssertEx.CollectionEquals(uncoveredSender.ToBytes(), uncovertedReceiver.ToBytes());
				AssertEx.CollectionEquals(generatedKey.PubKey.ToBytes(), uncovertedReceiver.ToBytes());

				var transaction = new Transaction();
				payment.AddToTransaction(transaction, 100);
			}
		}
Esempio n. 6
0
		public void CanParseStealthAddress()
		{
			var tests = new[] 
			{ 
				//Test vector created with sx
				//sx stealth-newkey -> ScanSecret,SpendSecret,StealthAddress
				//sx stealth-show-addr StealthAddress -> ScanPubKey,SpendPubKey,RequiredSignature...
				new
				{
					ScanSecret = "9ac9fdee7c2c19611bcbed8959e1c61d00cdc27cf17bb50a1f4d29db7f953632",
					SpendSecrets = new[]{
											"4e2fa767cc241c3fa4c512d572b2758a3960a06d374f2c819fe409b161d72ad4"
										},
					StealthAddress = "vJmsmwE8cVt9ytJxBuY2jayh8RAfvpG42CyNVYpeVZAkHaiwASobUEzskpXMwbH1TZNBLoxWWYem5WuZewTL8xz3upJ75zKcdVmTfg",
					ScanPubKey = "021ce89be99a229d123e8bc13ffbcb66722d6200bbeb1d90ddddbf97df82ed2672",
					SpendPubKeys = new[]
										{ 
											"03c197525241d3d70bbf33bb2b54d41e6b9595a92a2c6b7bf7157727c017f0154a"
										},
					RequiredSignature = 1,
					Options = 0,
					PrefixLength = 0,
					PrefixValue = "",
				}
			};
			foreach(var test in tests)
			{
				var scanSecret = new Key(TestUtils.ParseHex(test.ScanSecret));
				AssertEx.CollectionEquals(scanSecret.PubKey.ToBytes(), TestUtils.ParseHex(test.ScanPubKey));

				var stealth = new BitcoinStealthAddress(test.StealthAddress, Network.Main);
				Assert.Equal(test.RequiredSignature, stealth.SignatureCount);
				Assert.Equal(test.PrefixLength, stealth.Prefix.BitCount);
				AssertEx.CollectionEquals(stealth.Prefix.GetRawForm(), TestUtils.ParseHex(test.PrefixValue));
				Assert.Equal(test.Options, stealth.Options);

				AssertEx.CollectionEquals(stealth.ScanPubKey.ToBytes(),
											  TestUtils.ParseHex(test.ScanPubKey));
				for(int i = 0 ; i < test.SpendPubKeys.Length ; i++)
				{
					AssertEx.CollectionEquals(stealth.SpendPubKeys[i].ToBytes(),
											  TestUtils.ParseHex(test.SpendPubKeys[i]));

					var spendSecret = new Key(TestUtils.ParseHex(test.SpendSecrets[i]));
					AssertEx.CollectionEquals(stealth.SpendPubKeys[i].ToBytes(), TestUtils.ParseHex(test.SpendPubKeys[i]));
				}
			}
		}
Esempio n. 7
0
		public void script_combineSigs()
		{
			Key[] keys = new[] { new Key(), new Key(), new Key() };
			var txFrom = CreateCreditingTransaction(keys[0].PubKey.Hash.ScriptPubKey);
			var txTo = CreateSpendingTransaction(new Script(), txFrom);

			Script scriptPubKey = txFrom.Outputs[0].ScriptPubKey;
			Script scriptSig = txTo.Inputs[0].ScriptSig;

			Script empty = new Script();
			Script combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, empty);
			Assert.True(combined.ToBytes().Length == 0);

			// Single signature case:
			SignSignature(keys, txFrom, txTo, 0); // changes scriptSig
			scriptSig = txTo.Inputs[0].ScriptSig;
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
			Assert.True(combined == scriptSig);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
			Assert.True(combined == scriptSig);
			Script scriptSigCopy = scriptSig.Clone();
			// Signing again will give a different, valid signature:
			SignSignature(keys, txFrom, txTo, 0);
			scriptSig = txTo.Inputs[0].ScriptSig;

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
			Assert.True(combined == scriptSigCopy || combined == scriptSig);


			// P2SH, single-signature case:
			Script pkSingle = PayToPubkeyTemplate.Instance.GenerateScriptPubKey(keys[0].PubKey);
			scriptPubKey = pkSingle.Hash.ScriptPubKey;
			txFrom.Outputs[0].ScriptPubKey = scriptPubKey;
			txTo.Inputs[0].PrevOut = new OutPoint(txFrom, 0);

			SignSignature(keys, txFrom, txTo, 0, pkSingle);
			scriptSig = txTo.Inputs[0].ScriptSig;

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
			Assert.True(combined == scriptSig);

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
			scriptSig = txTo.Inputs[0].ScriptSig;
			Assert.True(combined == scriptSig);
			scriptSigCopy = scriptSig.Clone();

			SignSignature(keys, txFrom, txTo, 0);
			scriptSig = txTo.Inputs[0].ScriptSig;

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
			Assert.True(combined == scriptSigCopy || combined == scriptSig);
			// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
			scriptSigCopy = new Script(OpcodeType.OP_0, Op.GetPushOp(pkSingle.ToBytes()));
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
			Assert.True(combined == scriptSig);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy);
			Assert.True(combined == scriptSig);

			// Hardest case:  Multisig 2-of-3
			scriptPubKey = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, keys.Select(k => k.PubKey).ToArray());
			txFrom.Outputs[0].ScriptPubKey = scriptPubKey;
			txTo.Inputs[0].PrevOut = new OutPoint(txFrom, 0);

			SignSignature(keys, txFrom, txTo, 0);
			scriptSig = txTo.Inputs[0].ScriptSig;

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
			Assert.True(combined == scriptSig);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
			Assert.True(combined == scriptSig);

			// A couple of partially-signed versions:
			uint256 hash1 = scriptPubKey.SignatureHash(txTo, 0, SigHash.All);
			var sig1 = new TransactionSignature(keys[0].Sign(hash1), SigHash.All);

			uint256 hash2 = scriptPubKey.SignatureHash(txTo, 0, SigHash.None);
			var sig2 = new TransactionSignature(keys[1].Sign(hash2), SigHash.None);


			uint256 hash3 = scriptPubKey.SignatureHash(txTo, 0, SigHash.Single);
			var sig3 = new TransactionSignature(keys[2].Sign(hash3), SigHash.Single);


			// Not fussy about order (or even existence) of placeholders or signatures:
			Script partial1a = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + OpcodeType.OP_0;
			Script partial1b = new Script() + OpcodeType.OP_0 + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes());
			Script partial2a = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig2.ToBytes());
			Script partial2b = new Script() + Op.GetPushOp(sig2.ToBytes()) + OpcodeType.OP_0;
			Script partial3a = new Script() + Op.GetPushOp(sig3.ToBytes());
			Script partial3b = new Script() + OpcodeType.OP_0 + OpcodeType.OP_0 + Op.GetPushOp(sig3.ToBytes());
			Script partial3c = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig3.ToBytes()) + OpcodeType.OP_0;
			Script complete12 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + Op.GetPushOp(sig2.ToBytes());
			Script complete13 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + Op.GetPushOp(sig3.ToBytes());
			Script complete23 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig2.ToBytes()) + Op.GetPushOp(sig3.ToBytes());

			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
			Assert.True(combined == partial1a);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
			Assert.True(combined == complete12);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a);
			Assert.True(combined == complete12);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b);
			Assert.True(combined == complete12);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b);
			Assert.True(combined == complete13);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a);
			Assert.True(combined == complete23);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b);
			Assert.True(combined == complete23);
			combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a);
			Assert.True(combined == partial3c);
		}
Esempio n. 8
0
		public void CanUseCompactVarInt()
		{
			var tests = new[]{
				new object[]{0UL, new byte[]{0}},
				new object[]{1UL, new byte[]{1}},
				new object[]{127UL, new byte[]{0x7F}},
				new object[]{128UL, new byte[]{0x80, 0x00}},
				new object[]{255UL, new byte[]{0x80, 0x7F}},
				new object[]{256UL, new byte[]{0x81, 0x00}},
				new object[]{16383UL, new byte[]{0xFE, 0x7F}},
				//new object[]{16384UL, new byte[]{0xFF, 0x00}},
				//new object[]{16511UL, new byte[]{0x80, 0xFF, 0x7F}},
				//new object[]{65535UL, new byte[]{0x82, 0xFD, 0x7F}},
				new object[]{(ulong)1 << 32, new byte[]{0x8E, 0xFE, 0xFE, 0xFF, 0x00}},
			};
			foreach(var test in tests)
			{
				ulong val = (ulong)test[0];
				byte[] expectedBytes = (byte[])test[1];

				AssertEx.CollectionEquals(new CompactVarInt(val, sizeof(ulong)).ToBytes(), expectedBytes);
				AssertEx.CollectionEquals(new CompactVarInt(val, sizeof(uint)).ToBytes(), expectedBytes);

				var compact = new CompactVarInt(sizeof(ulong));
				compact.ReadWrite(expectedBytes);
				Assert.Equal(val, compact.ToLong());

				compact = new CompactVarInt(sizeof(uint));
				compact.ReadWrite(expectedBytes);
				Assert.Equal(val, compact.ToLong());
			}

			foreach(var i in Enumerable.Range(0, 65535 * 4))
			{
				var compact = new CompactVarInt((ulong)i, sizeof(ulong));
				var bytes = compact.ToBytes();
				compact = new CompactVarInt(sizeof(ulong));
				compact.ReadWrite(bytes);
				Assert.Equal((ulong)i, compact.ToLong());
			}
		}
Esempio n. 9
0
		//https://en.bitcoin.it/wiki/List_of_address_prefixes
		public void CanDetectBase58NetworkAndType()
		{
			var tests = new[]
				{
					new
					{
						Base58 = "bWqaKUZETiECYgmJNbNZUoanBxnAzoVjCNx",
						ExpectedType = typeof(BitcoinColoredAddress),
						Network = Network.TestNet
					},
					new
					{
						Base58 = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem",
						ExpectedType = typeof(BitcoinPubKeyAddress),
						Network = Network.Main
					},
					new
					{
						Base58 = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem",
						ExpectedType = typeof(BitcoinPubKeyAddress),
						Network = Network.Main
					},
					new
					{
						Base58 = "T7nYdHtL34xLZ2S5KwqgySNNzGxovhszhtDM3wQRUEfUbUVvRZzTW",
						ExpectedType = typeof(BitcoinWitScriptAddress),
						Network = Network.SegNet
					},
					new
					{
						Base58 = "p2y9AsuyBkVj4fpF6capRJKhVCPno6QFRfrx",
						ExpectedType = typeof(BitcoinWitPubKeyAddress),
						Network = Network.SegNet
					},
					new
					{
						Base58 = "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX",
						ExpectedType = typeof(BitcoinScriptAddress),
						Network = Network.Main
					},
					new
					{
						Base58 = "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn",
						ExpectedType = typeof(BitcoinPubKeyAddress),
						Network = Network.TestNet
					},
					new
					{
						Base58 = "5Hwgr3u458GLafKBgxtssHSPqJnYoGrSzgQsPwLFhLNYskDPyyA",
						ExpectedType = typeof(BitcoinSecret),
						Network = Network.Main
					},
					new
					{
						Base58 = "92Pg46rUhgTT7romnV7iGW6W1gbGdeezqdbJCzShkCsYNzyyNcc",
						ExpectedType = typeof(BitcoinSecret),
						Network = Network.TestNet
					},
					new
					{
						Base58 = "3qdi7TXgRo1qR",
						ExpectedType = (Type)null,
						Network = (Network)null
					},
					new
					{
						Base58 = "6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7",
						ExpectedType = typeof(BitcoinEncryptedSecretNoEC),
						Network = (Network)null
					},
					new
					{
						Base58 = "6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX",
						ExpectedType = typeof(BitcoinEncryptedSecretEC),
						Network = (Network)null
					},
					new
					{
						Base58 = "passphrasepxFy57B9v8HtUsszJYKReoNDV6VHjUSGt8EVJmux9n1J3Ltf1gRxyDGXqnf9qm",
						ExpectedType = typeof(BitcoinPassphraseCode),
						Network = (Network)null
					},
					new
					{
						Base58 = "cfrm38V8aXBn7JWA1ESmFMUn6erxeBGZGAxJPY4e36S9QWkzZKtaVqLNMgnifETYw7BPwWC9aPD",
						ExpectedType = typeof(BitcoinConfirmationCode),
						Network = (Network)null
					},
					new
					{
						Base58 = "xprv9s21ZrQH143K3Gx1VAAD1ueDmwoPQUApekxWYSJ1f4W4m1nUPpRGdV5sTVhixZJT5cP2NqtEMZ2mrwHdW5RWpohCwspWidCpcLALvioXDyz",
						ExpectedType = typeof(BitcoinExtKey),
						Network = Network.Main
					},
					new
					{
						Base58 = "xpub661MyMwAqRbcEhHavVcryjNF2uA5woK6JCNRNJB8Z3dxPU8VNBd9E8GP7fusw2bhgYe7BXt6izr5iUaYo483919jjdtfEpG8j97djnEgJqo",
						ExpectedType = typeof(BitcoinExtPubKey),
						Network = Network.Main
					},
					new
					{
						Base58 = "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy",
						ExpectedType = typeof(BitcoinColoredAddress),
						Network = Network.Main
					}					
				};

			foreach(var test in tests)
			{
				if(test.ExpectedType == null)
				{
					Assert.Throws<FormatException>(() => Network.CreateFromBase58Data(test.Base58));
				}
				else
				{
					var result = Network.CreateFromBase58Data(test.Base58);
					Assert.True(test.ExpectedType == result.GetType());
					if(test.Network != null)
						Assert.True(test.Network == result.Network);
					Network.CreateFromBase58Data(test.Base58, test.Network);

					if(test.Network != null)
						foreach(var network in Network.GetNetworks())
						{
							if(network == test.Network)
								break;
							Assert.Throws<FormatException>(() => Network.CreateFromBase58Data(test.Base58, network));
						}
				}
			}
		}
Esempio n. 10
0
		public void CanConvertMoney()
		{
			var tests = new[]
			{
				new object[]{ 1.23456789m, MoneyUnit.BTC, 123456789m, MoneyUnit.Satoshi  },
				new object[]{ 1.23456789m, MoneyUnit.BTC, 1234.56789m, MoneyUnit.MilliBTC  },
				new object[]{ 1.23456789m, MoneyUnit.BTC, 1234567.89m, MoneyUnit.Bit  },
				new object[]{ 1.23456789m, MoneyUnit.BTC, 1.23456789m, MoneyUnit.BTC  },
			};

			foreach(var test in tests)
			{
				var inputAmount = (decimal)test[0];
				var inputUnit = (MoneyUnit)test[1];
				var outputAmount = (decimal)test[2];
				var outputUnit = (MoneyUnit)test[3];

				var result = new Money(inputAmount, inputUnit);
				var actual = result.ToUnit(outputUnit);

				Assert.Equal(outputAmount, actual);

				result = new Money(outputAmount, outputUnit);
				actual = result.ToUnit(inputUnit);

				Assert.Equal(inputAmount, actual);
			}
		}
Esempio n. 11
0
		public void CanGeneratePubKeysAndAddress()
		{
			//Took from http://brainwallet.org/ and http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript
			var tests = new[]
			{
				new 
				{
					PrivateKeyWIF = "5Hx15HFGyep2CfPxsJKe2fXJsCVn5DEiyoeGGF6JZjGbTRnqfiD",
					CompressedPrivateKeyWIF = "KwomKti1X3tYJUUMb1TGSM2mrZk1wb1aHisUNHCQXTZq5auC2qc3",
					PubKey = "04d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6fbdd594388756a7beaf73b4822bc22d36e9bda7db82df2b8b623673eefc0b7495",
					CompressedPubKey = "03d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6f",
					Address =           "16UjcYNBG9GTK4uq2f7yYEbuifqCzoLMGS",
					CompressedAddress = "1FkKMsKNJqWSDvTvETqcCeHcUQQ64kSC6s",
					Hash160 = "3c176e659bea0f29a3e9bf7880c112b1b31b4dc8",
					CompressedHash160 = "a1c2f92a9dacbd2991c3897724a93f338e44bdc1",
					DER = "3082011302010104201184cd2cdd640ca42cfc3a091c51d549b2f016d454b2774019c2b2d2e08529fda081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a14403420004d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6fbdd594388756a7beaf73b4822bc22d36e9bda7db82df2b8b623673eefc0b7495",
					CompressedDER = "3081d302010104201184cd2cdd640ca42cfc3a091c51d549b2f016d454b2774019c2b2d2e08529fda08185308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a12403220003d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6f"
				},
				new
				{
					PrivateKeyWIF = "5J7WTMRn1vjZ9udUxNCLq7F9DYEJiqRCjstiBrY6mDjnaomd6kZ",
					CompressedPrivateKeyWIF = "KxXj1KAMh6ApvKJ2PNZ4XLZRGLqjDehppFdEnueGSBDrC2Hfe7vt",
					PubKey = "0493e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd105500897eb030c033cdab160f31c36df0ea38330fdd69677df49cd14826902022d17f3f",
					CompressedPubKey = "0393e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089",
					Address =           "1MZmwgyMyjM11uA6ZSpgn1uK3LBWCzvV6e",
					CompressedAddress = "1AECNr2TDye8dpC1TeDH3eJpGoZ7dNPy4g",
					Hash160 = "e19557c8f8fb53a964c5dc7bfde86d806709f7c5",
					CompressedHash160 = "6538094af65453ea279f14d1a04b408e3adfebd7",
					DER = "308201130201010420271ac4d7056937c156abd828850d05df0697dd662d3c1b0107f53a387b4c176ca081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a1440342000493e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd105500897eb030c033cdab160f31c36df0ea38330fdd69677df49cd14826902022d17f3f",
					CompressedDER = "3081d30201010420271ac4d7056937c156abd828850d05df0697dd662d3c1b0107f53a387b4c176ca08185308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a1240322000393e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089"
				}
			};

			foreach(var test in tests)
			{
				BitcoinSecret secret = Network.Main.CreateBitcoinSecret(test.PrivateKeyWIF);
				Assert.Equal(test.PubKey, secret.PrivateKey.PubKey.ToHex());

				TestDERCoherence(secret);
				TestDEREqual(test.DER, secret);

				var address = Network.Main.CreateBitcoinAddress(test.Address);
				Assert.Equal(new KeyId(test.Hash160), address.Hash);
				Assert.Equal(new KeyId(test.Hash160), secret.PrivateKey.PubKey.Hash);
				Assert.Equal(address.Hash, secret.PrivateKey.PubKey.GetAddress(Network.Main).Hash);

				var compressedSec = secret.Copy(true);
				TestDERCoherence(compressedSec);
				TestDEREqual(test.CompressedDER, compressedSec);

				var a = secret.PrivateKey.PubKey;
				var b = compressedSec.PrivateKey.PubKey;

				Assert.Equal(test.CompressedPrivateKeyWIF, compressedSec.ToWif());
				Assert.Equal(test.CompressedPubKey, compressedSec.PrivateKey.PubKey.ToHex());
				Assert.True(compressedSec.PrivateKey.PubKey.IsCompressed);

				var compressedAddr = Network.Main.CreateBitcoinAddress(test.CompressedAddress);
				Assert.Equal(new KeyId(test.CompressedHash160), compressedAddr.Hash);
				Assert.Equal(new KeyId(test.CompressedHash160), compressedSec.PrivateKey.PubKey.Hash);


			}
		}
Esempio n. 12
0
		public void CanGeneratePubKeysAndAddress()
		{
			//Took from http://brainwallet.org/ and http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript
			var tests = new[]
			{
				new 
				{
					PrivateKeyWIF = "5Hx15HFGyep2CfPxsJKe2fXJsCVn5DEiyoeGGF6JZjGbTRnqfiD",
					CompressedPrivateKeyWIF = "KwomKti1X3tYJUUMb1TGSM2mrZk1wb1aHisUNHCQXTZq5auC2qc3",
					PubKey = "04d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6fbdd594388756a7beaf73b4822bc22d36e9bda7db82df2b8b623673eefc0b7495",
					CompressedPubKey = "03d0988bfa799f7d7ef9ab3de97ef481cd0f75d2367ad456607647edde665d6f6f",
					Address =           "16UjcYNBG9GTK4uq2f7yYEbuifqCzoLMGS",
					CompressedAddress = "1FkKMsKNJqWSDvTvETqcCeHcUQQ64kSC6s",
					Hash160 = "3c176e659bea0f29a3e9bf7880c112b1b31b4dc8",
					CompressedHash160 = "a1c2f92a9dacbd2991c3897724a93f338e44bdc1"
				},
				new
				{
					PrivateKeyWIF = "5J7WTMRn1vjZ9udUxNCLq7F9DYEJiqRCjstiBrY6mDjnaomd6kZ",
					CompressedPrivateKeyWIF = "KxXj1KAMh6ApvKJ2PNZ4XLZRGLqjDehppFdEnueGSBDrC2Hfe7vt",
					PubKey = "0493e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd105500897eb030c033cdab160f31c36df0ea38330fdd69677df49cd14826902022d17f3f",
					CompressedPubKey = "0393e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089",
					Address =           "1MZmwgyMyjM11uA6ZSpgn1uK3LBWCzvV6e",
					CompressedAddress = "1AECNr2TDye8dpC1TeDH3eJpGoZ7dNPy4g",
					Hash160 = "e19557c8f8fb53a964c5dc7bfde86d806709f7c5",
					CompressedHash160 = "6538094af65453ea279f14d1a04b408e3adfebd7"
				}
			};

			foreach(var test in tests)
			{
				BitcoinSecret secret = Network.Main.CreateBitcoinSecret(test.PrivateKeyWIF);
				Assert.Equal(test.PubKey, secret.PrivateKey.PubKey.ToHex());
				
				var address = (BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.Address);
				Assert.Equal(new KeyId(test.Hash160), address.Hash);
				Assert.Equal(new KeyId(test.Hash160), secret.PrivateKey.PubKey.Hash);
				Assert.Equal(address.Hash, secret.PrivateKey.PubKey.GetAddress(Network.Main).Hash);

				var compressedSec = secret.Copy(true);
			
				var a = secret.PrivateKey.PubKey;
				var b = compressedSec.PrivateKey.PubKey;

				Assert.Equal(test.CompressedPrivateKeyWIF, compressedSec.ToWif());
				Assert.Equal(test.CompressedPubKey, compressedSec.PrivateKey.PubKey.ToHex());
				Assert.True(compressedSec.PrivateKey.PubKey.IsCompressed);

				var compressedAddr = (BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.CompressedAddress);
				Assert.Equal(new KeyId(test.CompressedHash160), compressedAddr.Hash);
				Assert.Equal(new KeyId(test.CompressedHash160), compressedSec.PrivateKey.PubKey.Hash);


			}
		}
Esempio n. 13
0
		public EncryptedKeyResult GenerateEncryptedSecret(bool isCompressed = true, byte[] seedb = null)
		{
			//Set flagbyte.
			byte flagByte = 0;
			//Turn on bit 0x20 if the Bitcoin address will be formed by hashing the compressed public key
			flagByte |= isCompressed ? (byte)0x20 : (byte)0x00;
			flagByte |= LotSequence != null ? (byte)0x04 : (byte)0x00;

			//Generate 24 random bytes, call this seedb. Take SHA256(SHA256(seedb)) to yield 32 bytes, call this factorb.
			seedb = seedb ?? RandomUtils.GetBytes(24);

			var factorb = Hashes.Hash256(seedb).ToBytes();

			//ECMultiply passpoint by factorb.
			var curve = ECKey.Secp256k1;
			var passpoint = curve.Curve.DecodePoint(Passpoint);
			var pubPoint = passpoint.Multiply(new BigInteger(1, factorb));

			//Use the resulting EC point as a public key
			var pubKey = new PubKey(pubPoint.GetEncoded());

			//and hash it into a Bitcoin address using either compressed or uncompressed public key
			//This is the generated Bitcoin address, call it generatedaddress.
			pubKey = isCompressed ? pubKey.Compress() : pubKey.Decompress();

			//call it generatedaddress.
			var generatedaddress = pubKey.GetAddress(Network);

			//Take the first four bytes of SHA256(SHA256(generatedaddress)) and call it addresshash.
			var addresshash = BitcoinEncryptedSecretEC.HashAddress(generatedaddress);

			//Derive a second key from passpoint using scrypt
			//salt is addresshash + ownerentropy
			var derived = BitcoinEncryptedSecretEC.CalculateDecryptionKey(Passpoint, addresshash, OwnerEntropy);

			//Now we will encrypt seedb.
			var encrypted = BitcoinEncryptedSecret.EncryptSeed
							(seedb,
							derived);

			//0x01 0x43 + flagbyte + addresshash + ownerentropy + encryptedpart1[0...7] + encryptedpart2 which totals 39 bytes
			var bytes =
				new[] { flagByte }
				.Concat(addresshash)
				.Concat(this.OwnerEntropy)
				.Concat(encrypted.Take(8).ToArray())
				.Concat(encrypted.Skip(16).ToArray())
				.ToArray();

			var encryptedSecret = new BitcoinEncryptedSecretEC(bytes, Network);

			return new EncryptedKeyResult(encryptedSecret, generatedaddress, seedb, () =>
			{
				//ECMultiply factorb by G, call the result pointb. The result is 33 bytes.
				var pointb = new Key(factorb).PubKey.ToBytes();
				//The first byte is 0x02 or 0x03. XOR it by (derivedhalf2[31] & 0x01), call the resulting byte pointbprefix.
				var pointbprefix = (byte)(pointb[0] ^ (byte)(derived[63] & 0x01));
				var pointbx = BitcoinEncryptedSecret.EncryptKey(pointb.Skip(1).ToArray(), derived);
				var encryptedpointb = new byte[] { pointbprefix }.Concat(pointbx).ToArray();

				var confirmBytes =
					Network.GetVersionBytes(Base58Type.CONFIRMATION_CODE)
					.Concat(new[] { flagByte })
					.Concat(addresshash)
					.Concat(OwnerEntropy)
					.Concat(encryptedpointb)
					.ToArray();

				return new BitcoinConfirmationCode(Encoders.Base58Check.EncodeData(confirmBytes), Network);
			});
		}