Example #1
0
    def test_msgsign_p2pkh(self):
        msg = 'test message'
        # sigs are taken from (Electrum and) Bitcoin Core

        # first private key
        q1 = 91634880152443617534842621287039938041581081254914058002978601050179556493499
        # uncompressed
        wif1u = wif_from_prvkey(q1, False)
        self.assertEqual(
            wif1u, b'5KMWWy2d3Mjc8LojNoj8Lcz9B1aWu8bRofUgGwQk959Dw5h2iyw')
        add1u = p2pkh_from_wif(wif1u)
        self.assertEqual(add1u, b'1HUBHMij46Hae75JPdWjeZ5Q7KaL7EFRSD')
        sig1u = btcmsg.sign(msg, wif1u)
        self.assertTrue(btcmsg.verify(msg, add1u, sig1u))
        self.assertEqual(sig1u[0], 27)
        exp_sig1u = b'G/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4='
        self.assertEqual(btcmsg.serialize(*sig1u), exp_sig1u)
        # compressed
        wif1c = wif_from_prvkey(q1, True)
        self.assertEqual(
            wif1c, b'L41XHGJA5QX43QRG3FEwPbqD5BYvy6WxUxqAMM9oQdHJ5FcRHcGk')
        add1c = p2pkh_from_wif(wif1c)
        self.assertEqual(add1c, b'14dD6ygPi5WXdwwBTt1FBZK3aD8uDem1FY')
        sig1c = btcmsg.sign(msg, wif1c)
        self.assertTrue(btcmsg.verify(msg, add1c, sig1c))
        self.assertEqual(sig1c[0], 31)
        exp_sig1c = b'H/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4='
        self.assertEqual(btcmsg.serialize(*sig1c), exp_sig1c)

        self.assertFalse(btcmsg.verify(msg, add1c, sig1u))
        self.assertFalse(btcmsg.verify(msg, add1u, sig1c))

        rf, r, s, = sig1c
        sig1c_malleated_rf = btcmsg.serialize(rf + 1, r, s)
        self.assertFalse(btcmsg.verify(msg, add1c, sig1c_malleated_rf))
        sig1c_malleated_s = btcmsg.serialize(rf, r, ec.n - s)
        self.assertFalse(btcmsg.verify(msg, add1c, sig1c_malleated_s))
        sig1c_malleated_rf_s = btcmsg.serialize(rf + 1, r, ec.n - s)
        self.assertTrue(btcmsg.verify(msg, add1c, sig1c_malleated_rf_s))
Example #2
0
    def test_p2pkh_from_wif(self):
        seed = b"00" * 32  # better be random
        rxprv = bip32.rootxprv_from_seed(seed)
        path = "m/0h/0h/12"
        xprv = bip32.derive(rxprv, path)
        wif = wif_from_xprv(xprv)
        self.assertEqual(
            wif, b'KyLk7s6Z1FtgYEVp3bPckPVnXvLUWNCcVL6wNt3gaT96EmzTKZwP')
        address = p2pkh_from_wif(wif)
        xpub = bip32.xpub_from_xprv(xprv)
        address2 = slip32.address_from_xpub(xpub)
        self.assertEqual(address, address2)

        self.assertRaises(ValueError, wif_from_xprv, xpub)
Example #3
0
    def test_segwit(self):

        msg = 'test'
        wif = 'L4xAvhKR35zFcamyHME2ZHfhw5DEyeJvEMovQHQ7DttPTM8NLWCK'
        p2pkh = p2pkh_from_wif(wif)
        p2wpkh = p2wpkh_from_wif(wif)
        p2wpkh_p2sh = p2wpkh_p2sh_from_wif(wif)

        # p2pkh base58 address (Core, Electrum, BIP137)
        exp_sig = b'IBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU='
        self.assertTrue(btcmsg.verify(msg, p2pkh, exp_sig))
        sig = btcmsg.sign(msg, wif)  # no address: p2pkh assumed
        self.assertTrue(btcmsg.verify(msg, p2pkh, sig))
        self.assertEqual(btcmsg.serialize(*sig), exp_sig)

        # p2wpkh-p2sh base58 address (Electrum)
        self.assertTrue(btcmsg.verify(msg, p2wpkh_p2sh, sig))

        # p2wpkh bech32 address (Electrum)
        self.assertTrue(btcmsg.verify(msg, p2wpkh, sig))

        # p2wpkh-p2sh base58 address (BIP137)
        # different first letter in sig because of different rf
        exp_sig = b'JBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU='
        self.assertTrue(btcmsg.verify(msg, p2wpkh_p2sh, exp_sig))
        sig = btcmsg.sign(msg, wif, p2wpkh_p2sh)
        self.assertTrue(btcmsg.verify(msg, p2wpkh_p2sh, sig))
        self.assertEqual(btcmsg.serialize(*sig), exp_sig)

        # p2wpkh bech32 address (BIP137)
        # different first letter in sig because of different rf
        exp_sig = b'KBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU='
        self.assertTrue(btcmsg.verify(msg, p2wpkh, exp_sig))
        sig = btcmsg.sign(msg, wif, p2wpkh)
        self.assertTrue(btcmsg.verify(msg, p2wpkh, sig))
        self.assertEqual(btcmsg.serialize(*sig), exp_sig)
Example #4
0
    def test_exceptions(self):

        msg = 'test'
        wif = 'KwELaABegYxcKApCb3kJR9ymecfZZskL9BzVUkQhsqFiUKftb4tu'
        address = p2pkh_from_wif(wif)
        exp_sig = b'IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hSNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLNtoVc='
        self.assertTrue(btcmsg.verify(msg, address, exp_sig))

        # Invalid recovery flag: 26
        rf, r, s = btcmsg.deserialize(exp_sig)
        self.assertRaises(ValueError, btcmsg.serialize, 26, r, s)
        #btcmsg.serialize(26, r, s)

        # short exp_sig
        exp_sig = b'IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLoVc='
        self.assertRaises(ValueError, btcmsg._verify, msg, address, exp_sig)
        self.assertFalse(btcmsg.verify(msg, address, exp_sig))

        # Invalid recovery flag: 26
        exp_sig = b'GpNLHqEKSzwXV+KwwBfQthQ848mn5qSkmGDXpqshDuPYJELOnSuRYGQQgBR4PpI+w2tJdD4v+hxElvAaUSqv2eU='
        self.assertRaises(ValueError, btcmsg._verify, msg, address, exp_sig)
        self.assertFalse(btcmsg.verify(msg, address, exp_sig))
        #btcmsg._verify(msg, address, exp_sig)

        # Invalid recovery flag: 66
        exp_sig = b'QpNLHqEKSzwXV+KwwBfQthQ848mn5qSkmGDXpqshDuPYJELOnSuRYGQQgBR4PpI+w2tJdD4v+hxElvAaUSqv2eU='
        self.assertRaises(ValueError, btcmsg._verify, msg, address, exp_sig)
        self.assertFalse(btcmsg.verify(msg, address, exp_sig))
        #btcmsg._verify(msg, address, exp_sig)

        # Pubkey mismatch: compressed wif, uncompressed address
        wif = 'Ky1XfDK2v6wHPazA6ECaD8UctEoShXdchgABjpU9GWGZDxVRDBMJ'
        address = '19f7adDYqhHSJm2v7igFWZAqxXHj1vUa3T'
        self.assertRaises(ValueError, btcmsg.sign, msg, wif, address)
        #btcmsg.sign(msg, wif, address)

        # Pubkey mismatch: uncompressed wif, compressed address
        wif = '5JDopdKaxz5bXVYXcAnfno6oeSL8dpipxtU1AhfKe3Z58X48srn'
        address = '1DAag8qiPLHh6hMFVu9qJQm9ro1HtwuyK5'
        self.assertRaises(ValueError, btcmsg.sign, msg, wif, address)
        #btcmsg.sign(msg, wif, address)

        msg = 'test'
        wif = 'L4xAvhKR35zFcamyHME2ZHfhw5DEyeJvEMovQHQ7DttPTM8NLWCK'
        p2pkh = p2pkh_from_wif(wif)
        p2wpkh = p2wpkh_from_wif(wif)
        p2wpkh_p2sh = p2wpkh_p2sh_from_wif(wif)
        wif = 'Ky1XfDK2v6wHPazA6ECaD8UctEoShXdchgABjpU9GWGZDxVRDBMJ'
        # Mismatch between p2pkh address and key pair
        self.assertRaises(ValueError, btcmsg.sign, msg, wif, p2pkh)
        # btcmsg.sign(msg, wif, p2pkh)

        # Mismatch between p2wpkh address and key pair
        self.assertRaises(ValueError, btcmsg.sign, msg, wif, p2wpkh)
        # btcmsg.sign(msg, wif, p2wpkh)

        # Mismatch between p2wpkh_p2sh address and key pair
        self.assertRaises(ValueError, btcmsg.sign, msg, wif, p2wpkh_p2sh)
        # btcmsg.sign(msg, wif, p2wpkh_p2sh)

        # Invalid recovery flag (39) for base58 address
        exp_sig = b'IHdKsFF1bUrapA8GMoQUbgI+Ad0ZXyX1c/yAZHmJn5hSNBi7J+TrI1615FG3g9JEOPGVvcfDWIFWrg2exLNtoVc='
        _, r, s = btcmsg.deserialize(exp_sig)
        sig = btcmsg.serialize(39, r, s)
        self.assertRaises(ValueError, btcmsg._verify, msg, p2pkh, sig)
        #btcmsg._verify(msg, p2pkh, sig)

        # Invalid recovery flag (35) for bech32 address
        exp_sig = b'IBFyn+h9m3pWYbB4fBFKlRzBD4eJKojgCIZSNdhLKKHPSV2/WkeV7R7IOI0dpo3uGAEpCz9eepXLrA5kF35MXuU='
        _, r, s = btcmsg.deserialize(exp_sig)
        sig = btcmsg.serialize(35, r, s)
        self.assertRaises(ValueError, btcmsg._verify, msg, p2wpkh, sig)
Example #5
0
    def test_address_from_wif(self):
        # uncompressed mainnet
        wif1 = "5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW"
        b58 = p2pkh_from_wif(wif1)
        self.assertEqual(b58, b'1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig')
        self.assertRaises(ValueError, p2wpkh_from_wif, wif1)
        self.assertRaises(ValueError, p2wpkh_p2sh_from_wif, wif1)

        # compressed mainnet
        wif2 = "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162"
        b58 = p2pkh_from_wif(wif2)
        self.assertEqual(b58, b'1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB')
        b32 = p2wpkh_from_wif(wif2)
        self.assertEqual(
            h160_from_b58address(b58)[1:],
            witness_from_b32address(b32)[1:])
        h160 = h160_from_b58address(b58)[1]
        b = p2wpkh_p2sh_from_wif(wif2)
        self.assertEqual(hash160(b'\x00\x14' + h160),
                         h160_from_b58address(b)[1])

        self.assertEqual(
            prvkeytuple_from_wif(wif1)[0],
            prvkeytuple_from_wif(wif2)[0])

        # uncompressed testnet
        wif1 = "91gGn1HgSap6CbU12F6z3pJri26xzp7Ay1VW6NHCoEayNXwRpu2"
        b58 = p2pkh_from_wif(wif1)
        self.assertEqual(b58, b'mvgbzkCSgKbYgaeG38auUzR7otscEGi8U7')
        self.assertRaises(ValueError, p2wpkh_from_wif, wif1)
        self.assertRaises(ValueError, p2wpkh_p2sh_from_wif, wif1)

        # compressed testnet
        wif2 = "cMzLdeGd5vEqxB8B6VFQoRopQ3sLAAvEzDAoQgvX54xwofSWj1fx"
        b58 = p2pkh_from_wif(wif2)
        self.assertEqual(b58, b'n1KSZGmQgB8iSZqv6UVhGkCGUbEdw8Lm3Q')
        b32 = p2wpkh_from_wif(wif2)
        self.assertEqual(
            h160_from_b58address(b58)[1:],
            witness_from_b32address(b32)[1:])
        h160 = h160_from_b58address(b58)[1]
        b = p2wpkh_p2sh_from_wif(wif2)
        self.assertEqual(hash160(b'\x00\x14' + h160),
                         h160_from_b58address(b)[1])

        self.assertEqual(
            prvkeytuple_from_wif(wif1)[0],
            prvkeytuple_from_wif(wif2)[0])

        # uncompressed mainnet, trailing/leading spaces in string
        wif1 = "  5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW"
        b58 = p2pkh_from_wif(wif1)
        self.assertEqual(b58, b'1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig')
        self.assertRaises(ValueError, p2wpkh_from_wif, wif1)
        self.assertRaises(ValueError, p2wpkh_p2sh_from_wif, wif1)

        # compressed mainnet, trailing/leading spaces in string
        wif2 = "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162  "
        b58 = p2pkh_from_wif(wif2)
        self.assertEqual(b58, b'1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB')
        b32 = p2wpkh_from_wif(wif2)
        self.assertEqual(
            h160_from_b58address(b58)[1:],
            witness_from_b32address(b32)[1:])
        h160 = h160_from_b58address(b58)[1]
        b = p2wpkh_p2sh_from_wif(wif2)
        self.assertEqual(hash160(b'\x00\x14' + h160),
                         h160_from_b58address(b)[1])