public void EncryptedSecretNoECmultiply() { var tests = new[] { new { Passphrase= "TestingOneTwoThree", Encrypted = "6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg", Unencrypted = "5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR", Compressed = false }, new { Passphrase= "Satoshi", Encrypted = "6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq", Unencrypted = "5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5", Compressed = false }, new { Passphrase= "TestingOneTwoThree", Encrypted = "6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo", Unencrypted = "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP", Compressed = true }, new { Passphrase= "Satoshi", Encrypted = "6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7", Unencrypted = "KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7", Compressed = true } }; //Slow test, run in parallel Parallel.ForEach(tests, test => { var secret = new BitcoinSecret(test.Unencrypted, Network.Main); var encryptedKey = secret.PrivateKey.GetEncryptedBitcoinSecret(test.Passphrase, Network.Main); Assert.Equal(test.Encrypted, encryptedKey.ToString()); var actualSecret = encryptedKey.GetKey(test.Passphrase); Assert.Equal(test.Unencrypted, actualSecret.GetBitcoinSecret(Network.Main).ToString()); Assert.Equal(test.Compressed, actualSecret.IsCompressed); }); }
public void CanReadTestVectorPayments() { var tests = new[] { "data/payreq1_sha256_omitteddefault.paymentrequest", "data/payreq1_sha256.paymentrequest", "data/payreq2_sha256_omitteddefault.paymentrequest", "data/payreq2_sha256.paymentrequest", "data/payreq1_sha1_omitteddefault.paymentrequest", "data/payreq1_sha1.paymentrequest", "data/payreq2_sha1_omitteddefault.paymentrequest", "data/payreq2_sha1.paymentrequest", }; foreach(var provider in new ICertificateServiceProvider[] { #if WIN new WindowsCertificateServiceProvider(X509VerificationFlags.IgnoreNotTimeValid | X509VerificationFlags.AllowUnknownCertificateAuthority | X509VerificationFlags.IgnoreRootRevocationUnknown | X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown) #endif }) { PaymentRequest.DefaultCertificateServiceProvider = provider; foreach(var test in tests) { var bytes = File.ReadAllBytes(test); var request = PaymentRequest.Load(bytes); AssertEx.Equal(request.ToBytes(), bytes); Assert.True(request.VerifySignature()); request = PaymentRequest.Load(PaymentRequest.Load(bytes).ToBytes()); Assert.True(request.VerifySignature()); Assert.True(request.VerifyChain()); } } }
public void EncryptedSecretECmultiplyNoLot() { var tests = new[] { new { Passphrase= "TestingOneTwoThree", PassphraseCode= "passphrasepxFy57B9v8HtUsszJYKReoNDV6VHjUSGt8EVJmux9n1J3Ltf1gRxyDGXqnf9qm", Encrypted = "6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX", Address = "1PE6TQi6HTVNz5DLwB1LcpMBALubfuN2z2", Unencrypted = "5K4caxezwjGCGfnoPTZ8tMcJBLB7Jvyjv4xxeacadhq8nLisLR2", Compressed = false }, new { Passphrase= "Satoshi", PassphraseCode= "passphraseoRDGAXTWzbp72eVbtUDdn1rwpgPUGjNZEc6CGBo8i5EC1FPW8wcnLdq4ThKzAS", Encrypted = "6PfLGnQs6VZnrNpmVKfjotbnQuaJK4KZoPFrAjx1JMJUa1Ft8gnf5WxfKd", Address = "1CqzrtZC6mXSAhoxtFwVjz8LtwLJjDYU3V", Unencrypted = "5KJ51SgxWaAYR13zd9ReMhJpwrcX47xTJh2D3fGPG9CM8vkv5sH", Compressed = false } }; foreach(var test in tests) { //Can generate unencrypted key with password and encrypted key var encryptedKey = new BitcoinEncryptedSecretEC(test.Encrypted, Network.Main); Assert.Null(encryptedKey.LotSequence); var actualKey = encryptedKey.GetKey(test.Passphrase); Assert.Equal(test.Unencrypted, actualKey.GetBitcoinSecret(Network.Main).ToString()); Assert.Equal(test.Address, actualKey.PubKey.GetAddress(Network.Main).ToString()); Assert.Equal(test.Compressed, actualKey.IsCompressed); //Can generate same BitcoinPassphraseCode with by using same ownerentropy var passCode = new BitcoinPassphraseCode(test.PassphraseCode, Network.Main); Assert.Null(passCode.LotSequence); var actualPassCode = new BitcoinPassphraseCode(test.Passphrase, Network.Main, null, passCode.OwnerEntropy); Assert.Equal(passCode.ToString(), actualPassCode.ToString()); //Can generate encrypted key from passcode var generatedEncryptedKey = passCode.GenerateEncryptedSecret(test.Compressed).EncryptedKey; AssertEx.CollectionEquals(passCode.OwnerEntropy, generatedEncryptedKey.OwnerEntropy); Assert.Equal(test.Compressed, generatedEncryptedKey.IsCompressed); } }
public void EncryptedSecretECmultiplyNoLotSimple() { var compressedValues = new[] { false, true }; foreach(var compressed in compressedValues) { var code = new BitcoinPassphraseCode("test", Network.Main, null); Assert.Null(code.LotSequence); var result = code.GenerateEncryptedSecret(compressed); Assert.True(result.ConfirmationCode.Check("test", result.GeneratedAddress)); Assert.False(result.ConfirmationCode.Check("toto", result.GeneratedAddress)); Assert.False(result.ConfirmationCode.Check("test", new Key().PubKey.GetAddress(Network.Main))); var decryptedKey = result.EncryptedKey.GetKey("test"); Assert.Equal(result.GeneratedAddress.ToString(), decryptedKey.PubKey.GetAddress(Network.Main).ToString()); Assert.Throws<SecurityException>(() => result.EncryptedKey.GetKey("wrong")); //Can regenerate same result with same seed var result2 = code.GenerateEncryptedSecret(compressed, seedb: result.Seed); var decryptedKey2 = result.EncryptedKey.GetKey("test"); AssertEx.CollectionEquals(decryptedKey2.ToBytes(), decryptedKey.ToBytes()); } }
public void EncryptedSecretECmultiplyLotSequence() { var tests = new[] { new { Passphrase= "ΜΟΛΩΝ ΛΑΒΕ", PassphraseCode= "passphrased3z9rQJHSyBkNBwTRPkUGNVEVrUAcfAXDyRU1V28ie6hNFbqDwbFBvsTK7yWVK", Encrypted = "6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH", Address = "1Lurmih3KruL4xDB5FmHof38yawNtP9oGf", Unencrypted = "5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D", ConfirmationCode = "cfrm38V8G4qq2ywYEFfWLD5Cc6msj9UwsG2Mj4Z6QdGJAFQpdatZLavkgRd1i4iBMdRngDqDs51", LotSequence = new LotSequence(806938,1), Compressed = false } ,new { Passphrase= "MOLON LABE", PassphraseCode= "passphraseaB8feaLQDENqCgr4gKZpmf4VoaT6qdjJNJiv7fsKvjqavcJxvuR1hy25aTu5sX", Encrypted = "6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j", Address = "1Jscj8ALrYu2y9TD8NrpvDBugPedmbj4Yh", Unencrypted = "5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8", ConfirmationCode = "cfrm38V8aXBn7JWA1ESmFMUn6erxeBGZGAxJPY4e36S9QWkzZKtaVqLNMgnifETYw7BPwWC9aPD", LotSequence = new LotSequence(263183,1), Compressed = false } }; foreach(var test in tests) { //Can generate unencrypted key with password and encrypted key var encryptedKey = new BitcoinEncryptedSecretEC(test.Encrypted, Network.Main); AssertSequenceEquals(test.LotSequence, encryptedKey.LotSequence); var actualKey = encryptedKey.GetKey(test.Passphrase); Assert.Equal(test.Unencrypted, actualKey.GetBitcoinSecret(Network.Main).ToString()); Assert.Equal(test.Address, actualKey.PubKey.GetAddress(Network.Main).ToString()); Assert.Equal(test.Compressed, actualKey.IsCompressed); //Can generate same BitcoinPassphraseCode with by using same ownerentropy var passCode = new BitcoinPassphraseCode(test.PassphraseCode, Network.Main); AssertSequenceEquals(test.LotSequence, passCode.LotSequence); var actualPassCode = new BitcoinPassphraseCode(test.Passphrase, Network.Main, test.LotSequence, passCode.OwnerEntropy); Assert.Equal(passCode.ToString(), actualPassCode.ToString()); //Can verify confirmation var confirmation = new BitcoinConfirmationCode(test.ConfirmationCode, Network.Main); AssertSequenceEquals(confirmation.LotSequence, test.LotSequence); Assert.True(confirmation.Check(test.Passphrase, new BitcoinAddress(test.Address, Network.Main))); //Can generate encrypted key from passcode var generatedEncryptedKey = passCode.GenerateEncryptedSecret(test.Compressed).EncryptedKey; AssertEx.CollectionEquals(passCode.OwnerEntropy, generatedEncryptedKey.OwnerEntropy); Assert.Equal(test.Compressed, generatedEncryptedKey.IsCompressed); } }
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()); } }
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); }
public void CanConvertText() { string testPhrase = "é ^ç hello \"12345\" wooorld"; var tests = new[] { new { Encoder = Encoders.Hex, Input = testPhrase, Expected = "c3a9205ec3a72068656c6c6f20223132333435222020776f6f6f726c64", }, new { Encoder = Encoders.Base58, Input = testPhrase, Expected = "9tBRc991GhmZNsV5qSyynUsnRCNvxdvvWDmj3nAP" }, new { Encoder = Encoders.Base58Check, Input = testPhrase, //Different from brainwallet, because brainwallet code convert the data to bitcoin address instead of directely formating in base58check (ie : the data followed be the 4 hash bytes) Expected = "2189xoVGsHC6VbVPUrKeH3fhT429VDruzdgUJFk37PNskG" }, new { Encoder = Encoders.Base64, Input = testPhrase, Expected = "w6kgXsOnIGhlbGxvICIxMjM0NSIgIHdvb29ybGQ=" }, //Not yet implemented //new //{ // Encoder = Encoders.Bin, // Input = testPhrase, // Expected = "11000011 10101001 00100000 01011110 11000011 10100111 00100000 01101000 01100101 01101100 01101100 01101111 00100000 00100010 00110001 00110010 00110011 00110100 00110101 00100010 00100000 00100000 01110111 01101111 01101111 01101111 01110010 01101100 01100100" //}, //Not yet implemented //new //{ // Encoder = Encoders.Dec, // Input = testPhrase, // Expected = "5275000693703128425041367611933003709099386868005962673424426230508644" //}, //Useless for bitcoin //new //{ // Encoder = Encoders.RFC1751, // Input = testPhrase, // Expected = "A A OWE BANG BAN BUST KITE ARK HAT SEEN OBOE GRIM KIN GASH GLOB COAT BANE DUN JO MILL SIGH SLID MAD PAR" //}, //Useless for bitcoin //new //{ // Encoder = Encoders.Poetry, // Input = testPhrase, // Expected = "perfect perfect perfect soul stone royal fault companion sharp cross build leap possess possibly yet bone magic beam illuminate moonlight foul juice darkness universe" //}, //Useless for bitcoin //new //{ // Encoder = Encoders.Rot13, // Input = testPhrase, // Expected = "é ^ç uryyb \"12345\" jbbbeyq" //}, //Useless for bitcoin //new //{ // Encoder = Encoders.Easy16, // Input = testPhrase, // Expected = "aaaa aauf reda houf rkda jwjh juju jnda eriu\r\nddfs fdff fgfh ddda dakk jnjn jnkd jujg euhs" //}, }; foreach(var test in tests) { var input = Encoding.UTF8.GetBytes(test.Input); var encoded = test.Encoder.EncodeData(input); Assert.Equal(test.Expected, encoded); try { var decoded = test.Encoder.DecodeData(encoded); AssertEx.CollectionEquals(input, decoded); } catch(NotSupportedException) { } } var expectedText = "2189xoVGsHC6VbVPUrKeH3fhT429VDruzdgUJFk37PNskG"; var input1 = Encoding.UTF8.GetBytes("---é ^ç hello \"12345\" wooorld---"); var encoded1 = Encoders.Base58Check.EncodeData(input1, 3, input1.Length-6); Assert.Equal(expectedText, encoded1); var decoded1 = Encoders.Base58Check.DecodeData(encoded1); AssertEx.CollectionEquals(input1.SafeSubarray(3, input1.Length-6), decoded1); }