示例#1
0
    def test_rfc6979_tv(self):

        fname = "rfc6979.json"
        filename = path.join(path.dirname(__file__), "test_data", fname)
        with open(filename, "r") as f:
            test_dict = json.load(f)

        for ec_name in test_dict:
            ec = CURVES[ec_name]
            test_vectors = test_dict[ec_name]
            for x, x_U, y_U, hf, msg, k, r, s in test_vectors:
                x = int(x, 16)
                # test RFC6979 implementation
                k2 = rfc6979(msg, x, ec, eval("hashlib." + hf))
                self.assertEqual(k, hex(k2))
                # test RFC6979 usage in DSA
                sig = dsa.sign(msg, x, k2, ec, eval("hashlib." + hf))
                self.assertEqual(r, hex(sig[0]))
                self.assertIn(s, (hex(sig[1]), hex(ec.n - sig[1])))
                # test that RFC6979 is the default nonce for DSA
                sig = dsa.sign(msg, x, k=None, ec=ec, hf=eval("hashlib." + hf))
                self.assertEqual(r, hex(sig[0]))
                self.assertIn(s, (hex(sig[1]), hex(ec.n - sig[1])))
                # test key-pair coherence
                U = mult(x, ec.G, ec)
                self.assertEqual((int(x_U, 16), int(y_U, 16)), U)
                # test signature validity
                dsa._verify(msg, U, sig, ec, hf=eval("hashlib." + hf))
示例#2
0
    def test_signature(self):
        ec = secp256k1
        hf = sha256
        q = 0x1
        Q = mult(ec, q, ec.G)
        msg = 'Satoshi Nakamoto'.encode()
        sig = dsa.sign(ec, hf, msg, q)
        # https://bitcointalk.org/index.php?topic=285142.40
        # Deterministic Usage of DSA and ECDSA (RFC 6979)
        exp_sig = (
            0x934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d8,
            0x2442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5)
        r, s = sig
        self.assertEqual(sig[0], exp_sig[0])
        self.assertIn(sig[1], (exp_sig[1], ec.n - exp_sig[1]))

        self.assertTrue(dsa.verify(ec, hf, msg, Q, sig))
        self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))

        # malleability
        malleated_sig = (r, ec.n - s)
        self.assertTrue(dsa.verify(ec, hf, msg, Q, malleated_sig))
        self.assertTrue(dsa._verify(ec, hf, msg, Q, malleated_sig))

        keys = dsa.pubkey_recovery(ec, hf, msg, sig)
        self.assertTrue(len(keys) == 2)
        self.assertIn(Q, keys)

        fmsg = 'Craig Wright'.encode()
        self.assertFalse(dsa.verify(ec, hf, fmsg, Q, sig))
        self.assertFalse(dsa._verify(ec, hf, fmsg, Q, sig))

        fdsasig = (sig[0], sig[1], sig[1])
        self.assertFalse(dsa.verify(ec, hf, msg, Q, fdsasig))
        self.assertRaises(TypeError, dsa._verify, ec, hf, msg, Q, fdsasig)

        fq = 0x4
        fQ = mult(ec, fq, ec.G)
        self.assertFalse(dsa.verify(ec, hf, msg, fQ, sig))
        self.assertFalse(dsa._verify(ec, hf, msg, fQ, sig))

        # r not in [1, n-1]
        invalid_dassig = 0, sig[1]
        self.assertFalse(dsa.verify(ec, hf, msg, Q, invalid_dassig))

        # s not in [1, n-1]
        invalid_dassig = sig[0], 0
        self.assertFalse(dsa.verify(ec, hf, msg, Q, invalid_dassig))

        # pubkey = Inf
        self.assertRaises(ValueError, dsa._verify, ec, hf, msg, (1, 0), sig)
        #dsa._verify(ec, hf, msg, (1, 0), sig)

        # private key not in [1, n-1]
        self.assertRaises(ValueError, dsa.sign, ec, hf, msg, 0)
        #dsa.sign(ec, hf, msg, 0)

        # ephemeral key not in [1, n-1]
        self.assertRaises(ValueError, dsa.sign, ec, hf, msg, 1, 0)
    def test_gec(self):
        """ GEC 2: Test Vectors for SEC 1, section 2

            http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
        """
        # 2.1.1 Scheme setup
        ec = secp160r1
        hf = sha1

        # 2.1.2 Key Deployment for U
        dU = 971761939728640320549601132085879836204587084162
        self.assertEqual(format(dU,
                                str(ec.psize) + 'x'),
                         'aa374ffc3ce144e6b073307972cb6d57b2a4e982')
        QU = mult(ec, dU, ec.G)
        self.assertEqual(QU,
                         (466448783855397898016055842232266600516272889280,
                          1110706324081757720403272427311003102474457754220))
        self.assertEqual(
            octets_from_point(ec, QU, True).hex(),
            '0251b4496fecc406ed0e75a24a3c03206251419dc0')

        # 2.1.3 Signing Operation for U
        msg = 'abc'.encode()
        k = 702232148019446860144825009548118511996283736794
        exp_sig = (0xCE2873E5BE449563391FEB47DDCBA2DC16379191,
                   0x3480EC1371A091A464B31CE47DF0CB8AA2D98B54)
        sig = dsa.sign(ec, hf, msg, dU, k)
        r, s = sig
        self.assertEqual(r, exp_sig[0])
        self.assertIn(s, (exp_sig[1], ec.n - exp_sig[1]))

        # 2.1.4 Verifying Operation for V
        self.assertTrue(dsa.verify(ec, hf, msg, QU, sig))
        self.assertTrue(dsa._verify(ec, hf, msg, QU, sig))
    def test_pubkey_recovery(self):
        ec = secp112r2
        hf = sha256
        q = 0x1
        Q = mult(ec, q, ec.G)
        msg = 'Satoshi Nakamoto'.encode()
        sig = dsa.sign(ec, hf, msg, q)

        self.assertTrue(dsa.verify(ec, hf, msg, Q, sig))
        self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))

        keys = dsa.pubkey_recovery(ec, hf, msg, sig)
        self.assertIn(Q, keys)
        for Q in keys:
            self.assertTrue(dsa.verify(ec, hf, msg, Q, sig))
            self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))
示例#5
0
    def test_pubkey_recovery(self):
        ec = secp112r2
        q = 0x10
        Q = mult(q, ec.G, ec)
        msg = b'Satoshi Nakamoto'
        sig = dsa.sign(msg, q, None, ec)

        self.assertTrue(dsa.verify(msg, Q, sig, ec))
        self.assertTrue(dsa._verify(msg, Q, sig, ec))

        keys = dsa.pubkey_recovery(msg, sig, ec)
        self.assertEqual(len(keys), 4)
        self.assertIn(Q, keys)
        for Q in keys:
            self.assertTrue(dsa.verify(msg, Q, sig, ec))
            self.assertTrue(dsa._verify(msg, Q, sig, ec))
示例#6
0
def test_p2pk():
    pubkey = "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
    signature = "304402200A5C6163F07B8D3B013C4D1D6DBA25E780B39658D79BA37AF7057A3B7F15FFA102201FD9B4EAA9943F734928B99A83592C2E7BF342EA2680F6A2BB705167966B742001"
    script_pubkey = script.serialize([pubkey, "OP_CHECKSIG"])
    script_sig = script.serialize([signature])

    founding_tx_script = script.serialize([0, 0])
    founding_tx = Tx(
        1,
        0,
        vin=[
            TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script,
                 0xFFFFFFFF, [])
        ],
        vout=[TxOut(0, script_pubkey)],
    )
    receiving_tx = Tx(
        1,
        0,
        vin=[TxIn(OutPoint(founding_tx.txid, 0), script_sig, 0xFFFFFFFF, [])],
        vout=[TxOut(0, b"")],
    )
    sighash = get_sighash(receiving_tx, founding_tx.vout[0], 0, 0x01)
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#7
0
def test_p2pk_anyonecanpay():
    pubkey = "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf"
    signature = "304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281"
    script_pubkey = script.serialize([pubkey, "OP_CHECKSIG"])
    script_sig = script.serialize([signature])

    founding_tx_script = script.serialize([0, 0])
    founding_tx = Tx(
        1,
        0,
        vin=[
            TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script,
                 0xFFFFFFFF, [])
        ],
        vout=[TxOut(0, script_pubkey)],
    )
    receiving_tx = Tx(
        1,
        0,
        vin=[TxIn(OutPoint(founding_tx.txid, 0), script_sig, 0xFFFFFFFF, [])],
        vout=[TxOut(0, b"")],
    )
    sighash = get_sighash(receiving_tx, founding_tx.vout[0], 0, 0x81)
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#8
0
def test_p2pkh():
    pubkey = "038282263212C609D9EA2A6E3E172DE238D8C39CABD5AC1CA10646E23FD5F51508"
    signature = "304402206E05A6FE23C59196FFE176C9DDC31E73A9885638F9D1328D47C0C703863B8876022076FEB53811AA5B04E0E79F938EB19906CC5E67548BC555A8E8B8B0FC603D840C01"
    script_pubkey = script.serialize([
        "OP_DUP",
        "OP_HASH160",
        "1018853670F9F3B0582C5B9EE8CE93764AC32B93",
        "OP_EQUALVERIFY",
        "OP_CHECKSIG",
    ])
    script_sig = script.serialize([signature, pubkey])

    founding_tx_script = script.serialize([0, 0])
    founding_tx = Tx(
        1,
        0,
        vin=[
            TxIn(OutPoint(b"\x00" * 32, 0xFFFFFFFF), founding_tx_script,
                 0xFFFFFFFF, [])
        ],
        vout=[TxOut(0, script_pubkey)],
    )
    receiving_tx = Tx(
        1,
        0,
        vin=[TxIn(OutPoint(founding_tx.txid, 0), script_sig, 0xFFFFFFFF, [])],
        vout=[TxOut(0, b"")],
    )
    sighash = get_sighash(receiving_tx, founding_tx.vout[0], 0, 0x01)
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#9
0
    def test_signtocontract(self):
        prv = 0x1
        pub = mult(prv)
        m = b"to be signed"
        c = b"to be committed"

        dsa_sig, dsa_receipt = ecdsa_commit_sign(c, m, prv, None)
        self.assertIsNone(dsa._verify(m, pub, dsa_sig, ec, sha256))
        self.assertTrue(verify_commit(c, dsa_receipt))

        # 32 bytes message for ECSSA
        m = sha256(m).digest()
        ssa_sig, ssa_receipt = ecssa_commit_sign(c, m, prv, None)
        self.assertIsNone(ssa._verify(m, pub, ssa_sig, ec, sha256))
        self.assertTrue(verify_commit(c, ssa_receipt))
示例#10
0
def test_legacy_p2pkh():
    pubkey = "04280c8f66bf2ccaeb3f60a19ad4a06365f8bd6178aab0e709df2173df8f553366549aec336aae8742a84702b6c7c3052d89f5d76d535ec3716e72187956351613"
    signature = "3045022100ea43c4800d1a860ec89b5273898a146cfb01d34ff4c364d24a110c480d0e3f7502201c82735577f932f1ca8e1c54bf653e0f8e74e408fe83666bc85cac4472ec950801"
    script_sig = [signature, pubkey]
    previous_txout = TxOut(
        value=1051173696,
        script_pubkey=script.serialize([
            "OP_DUP",
            "OP_HASH160",
            "82ac30f58baf99ec9d14e6181eee076f4e27f69c",
            "OP_EQUALVERIFY",
            "OP_CHECKSIG",
        ]),
    )
    tx = Tx(
        1,
        0,
        vin=[
            TxIn(
                OutPoint(
                    bytes.fromhex(
                        "d8343a35ba951684f2969eafe833d9e6fe436557b9707ae76802875952e860fc"
                    ),
                    1,
                ),
                script_sig,
                0xFFFFFFFF,
                [],
            )
        ],
        vout=[
            TxOut(
                2017682,
                bytes.fromhex(
                    "76a91413bd20236d0da56492c325dce289b4da35b4b5bd88ac"),
            ),
            TxOut(
                1049154982,
                bytes.fromhex(
                    "76a914da169b45781ca210f8c11617ba66bd843da76b1688ac"),
            ),
        ],
    )
    sighash = get_sighash(tx, previous_txout, 0, 0x01)
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#11
0
def test_first_transaction():
    transaction = Tx.deserialize(
        "0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000"
    )
    previous_txout = TxOut(
        value=5000000000,
        script_pubkey=bytes.fromhex(
            "410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"
        ),
    )
    sighash = get_sighash(transaction, previous_txout, 0, 0x01)
    assert (sighash.hex() ==
            "7a05c6145f10101e9d6325494245adf1297d80f8f38d4d576d57cdba220bcb19")
    pubkey = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"
    signature = "304402204E45E16932B8AF514961A1D3A1A25FDF3F4F7732E9D624C6C61548AB5FB8CD410220181522EC8ECA07DE4860A4ACDD12909D831CC56CBBAC4622082221A8768D1D0901"
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#12
0
def test_sighashsingle_bug():
    pubkey = "02D5C25ADB51B61339D2B05315791E21BBE80EA470A49DB0135720983C905AACE0"
    signature = "3045022100C9CDD08798A28AF9D1BAF44A6C77BCC7E279F47DC487C8C899911BC48FEAFFCC0220503C5C50AE3998A733263C5C0F7061B483E2B56C4C41B456E7D2F5A78A74C07703"
    script_pubkey = script.serialize([
        "OP_DUP",
        "OP_HASH160",
        "5b6462475454710f3c22f5fdf0b40704c92f25c3",
        "OP_EQUALVERIFY",
        "OP_CHECKSIGVERIFY",
        1,
    ])

    previous_txout = TxOut(0, script_pubkey)
    tx = Tx.deserialize(
        "01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000"
    )
    sighash = get_sighash(tx, previous_txout, 1, 0x03)
    assert dsa._verify(sighash, bytes.fromhex(pubkey),
                       bytes.fromhex(signature)[:-1])
示例#13
0
    def test_ledger(self):
        """Hybrid ECDSA Bitcoin message signature generated by Ledger"""

        mnemonic = "barely sun snack this snack relief pipe attack disease boss enlist lawsuit"

        # non-standard leading 31 in DER serialization
        derivation_path = "m/1"
        msg = b"\xfb\xa3\x1f\x8cd\x85\xe29#K\xb3{\xfd\xa7<?\x95oL\xee\x19\xb2'oh\xa7]\xd9A\xfeU\xd8"
        dersig = '3144022012ec0c174936c2a46dc657252340b2e6e6dd8c31dd059b6f9f33a90c21af2fba022030e6305b3ccf88009d419bf7651afcfcc0a30898b93ae9de9aa6ac03cf8ec56b'

        # pubkey derivation
        rprv = bip32.rootxprv_from_bip39mnemonic(mnemonic)
        xprv = bip32.derive(rprv, derivation_path)
        xpub = bip32.xpub_from_xprv(xprv)

        # the actual message being signed
        magic_msg = bms._magic_hash(msg)

        # save key_id and patch dersig
        dersig = bytes.fromhex(dersig)
        key_id = dersig[0]
        dersig = b'\x30' + dersig[1:]

        r, s = dsa.deserialize(dersig)

        # ECDSA signature verification of the patched dersig
        dsa._verify(magic_msg, xpub, dersig, ec, hf)
        self.assertTrue(dsa.verify(magic_msg, xpub, dersig))

        # compressed address
        addr = base58address.p2pkh(xpub)

        # equivalent Bitcoin Message Signature (non-serialized)
        rec_flag = 27 + 4 + (key_id & 0x01)
        btcmsgsig = (rec_flag, r, s)

        # Bitcoin Message Signature verification
        bms._verify(msg, addr, btcmsgsig)
        self.assertTrue(bms.verify(msg, addr, btcmsgsig))
        self.assertFalse(bms.verify(magic_msg, addr, btcmsgsig))

        bms.sign(msg, xprv)

        # standard leading 30 in DER serialization
        derivation_path = 'm/0/0'
        msg = "hello world"
        dersig = "3045022100967dac3262b4686e89638c8219c5761017f05cd87a855edf034f4a3ec6b59d3d0220108a4ef9682b71a45979d8c75c393382d9ccb8eb561d73b8c5fc0b87a47e7d27"

        # pubkey derivation
        rprv = bip32.rootxprv_from_bip39mnemonic(mnemonic)
        xprv = bip32.derive(rprv, derivation_path)
        xpub = bip32.xpub_from_xprv(xprv)

        # the actual message being signed
        magic_msg = bms._magic_hash(msg)

        # save key_id and patch dersig
        dersig = bytes.fromhex(dersig)
        key_id = dersig[0]
        dersig = b'\x30' + dersig[1:]

        r, s = dsa.deserialize(dersig)

        # ECDSA signature verification of the patched dersig
        dsa._verify(magic_msg, xpub, dersig, ec, hf)
        self.assertTrue(dsa.verify(magic_msg, xpub, dersig))

        # compressed address
        addr = base58address.p2pkh(xpub)

        # equivalent Bitcoin Message Signature (non-serialized)
        rec_flag = 27 + 4 + (key_id & 0x01)
        btcmsgsig = (rec_flag, r, s)

        # Bitcoin Message Signature verification
        bms._verify(msg, addr, btcmsgsig)
        self.assertTrue(bms.verify(msg, addr, btcmsgsig))
        self.assertFalse(bms.verify(magic_msg, addr, btcmsgsig))