Beispiel #1
0
    def verify_input(self, input_index):
        '''Returns whether the input has a valid signature'''
        # Exercise 1.1: get the relevant input
        tx_in = self.tx_ins[input_index]
        # Exercise 6.2: get the number of signatures required. This is available in tx_in.script_sig.num_sigs_required()
        if tx_in.script_sig.type() == 'blank':
            if tx_in.script_pubkey().type() == 'p2wpkh':
                sigs_required = 1
                # TODO: refactor
                # witness program verification
                if hash160(tx_in.script_witness[1]) != tx_in.script_pubkey().elements[-1]:
                    return False

                point = S256Point.parse(tx_in.script_witness[1])
                der, hash_type = tx_in.der_signature()
                signature = Signature.parse(der)
                z = self.sig_hash(input_index, hash_type)
                if not point.verify(z, signature):
                    return False

            #elif tx_in.script_pubkey().type() == 'p2wsh':
            #    sigs_required = 1
            #    point = S256Point.parse(tx_in.script_witness[1])
            #    der, hash_type = tx_in.der_signature()
            #    signature = Signature.parse(der)
            #    z = self.sig_hash(input_index, hash_type)
            #    if not point.verify(z, signature):
            #        return False
            else:
                raise RuntimeError("other witness type not yet supported")
        else:
            sigs_required = tx_in.script_sig.num_sigs_required()
            # Exercise 6.2: iterate over the sigs required and check each signature
            for sig_num in range(sigs_required):
                # Exercise 1.1: get the point from the sec format (tx_in.sec_pubkey())
                # Exercise 6.2: get the sec_pubkey at current signature index (check sec_pubkey function)
                point = S256Point.parse(tx_in.sec_pubkey(index=sig_num))
                # Exercise 1.1: get the der sig and hash_type from input
                # Exercise 6.2: get the der_signature at current signature index (check der_signature function)
                der, hash_type = tx_in.der_signature(index=sig_num)
                # Exercise 1.1: get the signature from der format
                signature = Signature.parse(der)
                # Exercise 1.1: get the hash to sign
                z = self.sig_hash(input_index, hash_type)
                # Exercise 1.1: use point.verify on the hash to sign and signature
                if not point.verify(z, signature):
                    return False
        return True
Beispiel #2
0
 def verify_input(self, input_index):
     '''Returns whether the input has a valid signature'''
     # get the relevant input
     tx_in = self.tx_ins[input_index]
     # get the number of signatures required. This is available in tx_in.script_sig.num_sigs_required()
     sigs_required = tx_in.script_sig.num_sigs_required()
     # iterate over the sigs required and check each signature
     for sig_num in range(sigs_required):
         # get the point from the sec format
         sec = tx_in.sec_pubkey(index=sig_num)
         # get the sec_pubkey at current signature index
         point = S256Point.parse(sec)
         # get the der sig and hash_type from input
         # get the der_signature at current signature index
         der, hash_type = tx_in.der_signature(index=sig_num)
         # get the signature from der format
         signature = Signature.parse(der)
         # get the hash to sign
         if tx_in.is_segwit():
             h160 = hash160(tx_in.script_sig.redeem_script())
             if h160 != tx_in.script_pubkey(self.testnet).elements[1]:
                 return False
             pubkey_h160 = tx_in.script_sig.redeem_script()[-20:]
             if pubkey_h160 != point.h160():
                 return False
             z = self.sig_hash_bip143(input_index, hash_type)
         else:
             z = self.sig_hash(input_index, hash_type)
         # use point.verify on the hash to sign and signature
         if not point.verify(z, signature):
             return False
     return True
Beispiel #3
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])
    stack.pop()
    try:
        points = [S256Point.parse(sec) for sec in sec_pubkeys]
        sigs = [Signature.parse(der) for der in der_signatures]
        for sig in sigs:
            if len(points) == 0:
                print("signatures no good or not in right order")
                return False
            while points:
                point = points.pop(0)
                if point.verify(z, sig):
                    break
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #4
0
def op_checksig(stack, z):
    # check that there are at least 2 elements on the stack
    if len(stack) < 2:
        return False
    # the top element of the stack is the SEC pubkey
    pubkey = stack.pop()
    # the next element of the stack is the DER signature
    # take off the last byte of the signature as that's the hash_type
    #맨 뒤에 하나만 빼고 가져오기
    #der 서명에는 r, s를 직렬화
    der_sig = stack.pop()[:-1]

    # parse the serialized pubkey and signature into objects
    try:
        point = S256Point.parse(pubkey)
        sig = Signature.parse(der_sig)
    except (ValueError, SyntaxError) as e:
        return False

    # verify the signature using S256Point.verify()
    # push an encoded 1 or 0 depending on whether the signature verified

    #서명에는 r, s가 포함되어 있음
    #u = x/s
    #v = r/s
    #uG + vP = R
    #R.x = s 이면 서명이 유효함
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #5
0
def op_checksig(stack, z):
    # check that there are at least 2 elements on the stack
    if len(stack) < 1:
        return False

    # the top element of the stack is the SEC pubkey
    sec_pubkey = stack.pop()

    # the next element of the stack is the DER signature
    der_signature_bytes = stack.pop()

    der_signature = der_signature_bytes[:-1]

    # take off the last byte of the signature as that's the hash_type
    hash_type = der_signature_bytes[-1]

    # parse the serialized pubkey and signature into objects
    pk = S256Point.parse(sec_pubkey)
    signature = Signature.parse(der_signature)

    # verify the signature using S256Point.verify()
    # push an encoded 1 or 0 depending on whether the signature verified
    if pk.verify(z, signature):
        stack.append(encode_num(1))
        return True
    else:
        stack.append(encode_num(0))
        return False
Beispiel #6
0
def op_checkmultisig(stack, z):
    # m of n multi-sig
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n+1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m+1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])
    stack.pop() # Off-by-One bug
    try:
        pubPoints = [S256Point.parse(sec) for sec in sec_pubkeys]
        sigs = [Signature.parse(der) for der in der_signatures]
        for sig in sigs:
            if len(pubPoints) == 0:
                return False
            while pubPoints:
                pubPoint = pubPoints.pop(0)
                if pubPoint.verify(z, sig):
                    break
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #7
0
def op_checksig(stack, z):
    # check that there are at least 2 elements on the stack
    if len(stack) < 2:
        return False

    # the top element of the stack is the SEC pubkey
    pubkey_bin = stack.pop()

    # the next element of the stack is the DER signature
    sig_bin = stack.pop()

    # take off the last byte of the signature as that's the hash_type
    hash_type = sig_bin[-1]
    sig_bin = sig_bin[:-1]

    # parse the serialized pubkey and signature into objects
    pubkey = S256Point.parse(pubkey_bin)
    sig = Signature.parse(sig_bin)

    # verify the signature using S256Point.verify()
    valid = pubkey.verify(z, sig)

    # push an encoded 1 or 0 depending on whether the signature verified
    stack.append(encode_num(1) if valid else encode_num(0))

    return True
Beispiel #8
0
 def test_example_4(self):
     sec = bytes.fromhex('0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a')
     der = bytes.fromhex('3045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed')
     z = 0x27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6
     point = S256Point.parse(sec)
     signature = Signature.parse(der)
     self.assertTrue(point.verify(z, signature))
Beispiel #9
0
def op_checksig(stack, z):
    # check that there are at least 2 elements on the stack
    if len(stack) < 2:
        return False
    # the top element of the stack is the SEC pubkey
    sec_pubkey = stack.pop()
    # the next element of the stack is the DER signature
    # take off the last byte of the signature as that's the hash_type
    # We will explain what this means when we explain validation of transactions next!!! Please be patient!
    # More at https://en.bitcoin.it/wiki/OP_CHECKSIG
    der_signature = stack.pop()[:-1]
    # parse the serialized pubkey and signature into objects
    try:
        point = S256Point.parse(sec_pubkey)
        sig = Signature.parse(der_signature)
    except (ValueError, SyntaxError):
        #print('Parse fail', point)
        return False
    # verify the signature using S256Point.verify()
    # push an encoded 1 or 0 depending on whether the signature verified
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #10
0
def op_checksig(stack, z):
    # check that there are at least 2 elements on the stack
    if len(stack) < 2:
        return False

    # the top element of the stack is the SEC pubkey
    sec_pubkey = stack.pop()
    print(f'stack sec:{sec_pubkey.hex()}')

    # the next element of the stack is the DER signature
    der_signature = stack.pop()[:-1]
    print(f'stack der:{der_signature}')

    # take off the last byte of the signature as that's the hash_type
    hash_type = der_signature[-1:]
    print(f'hash_type:{hash_type.hex()}')

    # parse the serialized pubkey and signature into objects
    try:
        point = S256Point.parse(sec_pubkey)
        der_signature = Signature.parse(der_signature)
        print(f'point:{point}')
        print(f'sig:{der_signature}')
    except (ValueError, SyntaxError) as e:
        return False
    if point.verify(z, der_signature):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #11
0
 def test_exercise_2(self):
     der = bytes.fromhex(
         '304402201f62993ee03fca342fcb45929993fa6ee885e00ddad8de154f268d98f083991402201e1ca12ad140c04e0e022c38f7ce31da426b8009d02832f0b44f39a6b178b7a1'
     )
     sec = bytes.fromhex(
         '0204519fac3d910ca7e7138f7013706f619fa8f033e6ec6e09370ea38cee6a7574'
     )
     z = int.from_bytes(hash256(b'ECDSA is awesome!'), 'big')
     sig = Signature.parse(der)
     point = S256Point.parse(sec)
     self.assertTrue(point.verify(z, sig))
Beispiel #12
0
 def test_der(self):
     testcases = (
         (1, 2),
         (randint(0, 2**256), randint(0, 2**255)),
         (randint(0, 2**256), randint(0, 2**255)),
     )
     for r, s in testcases:
         sig = Signature(r, s)
         der = sig.der()
         sig2 = Signature.parse(der)
         self.assertEqual(sig2.r, r)
         self.assertEqual(sig2.s, s)
Beispiel #13
0
def op_checksig(stack, z):
    if len(stack) < 2:
        return False
    sec_pubkey = stack.pop()
    der_signature = stack.pop()[:-1]
    point = S256Point.parse(sec_pubkey)
    sig = Signature.parse(der_signature)
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #14
0
def op_checkmultisig(stack, z): 
    if len(stack) < 1:
        return False
    # n is the number of public keys
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    # get all the public keys into a list.
    pubkeys = []
    for _ in range(n):
        pubkeys.append(stack.pop())
    if len(stack) < 1:
        return False
    # m is the number of signatures
    m = decode_num(stack.pop())
    # m + 2 because of the additional element at the bottom of the stack that is added.
    if len(stack) < m + 1:
        return False
    # get all the signatures.
    signatures = []
    for _ in range(m):
        # take off last byte, which is the hashtype
        signatures.append(stack.pop()[:-1])
    if len(stack) < 1:
        return False
    # we remove the last element from the stack (the one included because the off by one error)
    stack.pop()
    # verify all the signatures against all pubkeys. If a signature isn't valid for any pubkeys, fail.
    try:
        sigs = [Signature.parse(signature) for signature in signatures]
        points = [S256Point.parse(pubkey) for pubkey in pubkeys]
    except (ValueError, SyntaxError) as e:
        LOGGER.info(e)
        return False
    # variable to count the number of valid signatures.
    count = 0
    # in the next loop, we check that each signature is valid for a pubkey.
    while len(points) > 0:
        # point is popped so each signature can only be valid for 1 point.
        point = points.pop()
        for sig in sigs:
            # if the signature is valid for this pubkey, increase the count and break from the while
            # to check next signature.
            if point.verify(z, sig):
                count += 1
    # if the number of valid signatures is m = each signature is valid for some pubkey, then script is valid.
    if count == m:
        stack.append(encode_num(1))
    # else, script should fail.
    else:
        stack.append(encode_num(0))
    return True
Beispiel #15
0
 def verify_input(self, input_index):
     '''Returns whether the input has a valid signature'''
     # get the relevant input
     tx_in = self.tx_ins[input_index]
     # parse the point from the sec format (tx_in.sec_pubkey())
     point = S256Point.parse(tx_in.sec_pubkey())
     # parse the signature from the der format (tx_in.der_signature())
     signature = Signature.parse(tx_in.der_signature())
     # get the hash type from the input (tx_in.hash_type())
     hash_type = tx_in.hash_type()
     # get the sig_hash (z)
     z = self.sig_hash(input_index, hash_type)
     # use point.verify on the z and signature
     return point.verify(z, signature)
Beispiel #16
0
def op_checksig(stack, z):
    if len(stack) < 2:
        return False
    pub_sec = stack.pop()
    sig_der = stack.pop()[:-1] # except hash_type
    try:
        pub_point = S256Point.parse(pub_sec)
        sig = Signature.parse(sig_der)
    except (ValueError, SyntaxError) as e:
        return False
    if pub_point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #17
0
 def test_example_5(self):
     h256 = hash256(
         bytes.fromhex(
             '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c56870000000001000000'
         ))
     z = int.from_bytes(h256, 'big')
     point = S256Point.parse(
         bytes.fromhex(
             '022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70'
         ))
     sig = Signature.parse(
         bytes.fromhex(
             '3045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a89937'
         ))
     self.assertTrue(point.verify(z, sig))
def op_checksig(stack, z):
    if len(stack) < 2:
        return False
    sec_pubkey = stack.pop()
    der_signature = stack.pop()[:-1]
    try:
        point = S256Point.parse(sec_pubkey)
        sig = Signature.parse(der_signature)
    except (ValueError, SyntaxError) as e:
        return False
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #19
0
 def verify_input(self, input_index):
     '''Returns whether the input has a valid signature'''
     inp = self.tx_ins[input_index]
     sigs_required = inp.script_sig.num_sigs_required()
     for sig_num in range(sigs_required):
         # get the point from the sec format
         point = S256Point.parse(inp.sec_pubkey(index=sig_num))
         # get the input signature
         der, sighash = inp.der_signature(index=sig_num)
         signature = Signature.parse(der)
         # get the hash to sign
         z = self.hash_to_sign(input_index, sighash)
         # verify the hash and signature are good
         if not point.verify(z, signature):
             return False
     return True
Beispiel #20
0
 def test_exercise_3(self):
     hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'
     hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71'
     hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022'
     hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae'
     sec = bytes.fromhex(hex_sec)
     der = bytes.fromhex(hex_der)
     redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
     stream = BytesIO(bytes.fromhex(hex_tx))
     tx_obj = Tx.parse(stream)
     tx_obj.tx_ins[0].script_sig = redeem_script
     s = tx_obj.serialize() + int_to_little_endian(SIGHASH_ALL, 4)
     z = int.from_bytes(hash256(s), 'big')
     point = S256Point.parse(sec)
     sig = Signature.parse(der)
     self.assertTrue(point.verify(z, sig))
Beispiel #21
0
 def verify_input(self, input_index):
     '''Returns whether the input has a valid signature'''
     # get the relevant input
     tx_in = self.tx_ins[input_index]
     # get the sec_pubkey at current signature index
     point = S256Point.parse(tx_in.sec_pubkey())
     # get the der sig and hash_type from input
     # get the der_signature at current signature index
     der, hash_type = tx_in.der_signature()
     # get the signature from der format
     signature = Signature.parse(der)
     # get the hash to sign
     z = self.sig_hash_bip143(input_index, hash_type)
     # use point.verify on the hash to sign and signature
     if not point.verify(z, signature):
         return False
     return True
Beispiel #22
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])  # <1>
    stack.pop()
    try:
        # <2>
        # end::source1[]
        # parse all the points
        # parse all the signatures
        # loop through the signatures
        # if we have no more points, signatures are no good
        # we loop until we find the point which works with this signature
        # get the current point from the list of points
        # we check if this signature goes with the current point
        # the signatures are valid, so push a 1 to the stack
        # tag::source1[]
        #    points = [S256Point.parse(sec) for sec in sec_pubkeys]
        points = []
        sigs = []
        for sec in range(len(sec_pubkeys)):
            points.append(S256Point.parse(sec_pubkeys[sec]))
        for sig in range(len(der_signatures)):
            sigs.append(Signature.parse(der_signatures[sig]))
        for sig in sigs:
            if len(points) == 0:
                return False
            while points:
                point = points.pop(0)
                if point.verify(z, sig):
                    break
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #23
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])  # <1>
    stack.pop()  # <2>
    try:
        # end::source1[]
        # parse all the points
        # parse all the signatures
        # loop through the signatures
        # if we have no more points, signatures are no good
        # we loop until we find the point which works with this signature
        # get the current point from the list of points
        # we check if this signature goes with the current point
        # the signatures are valid, so push a 1 to the stack
        # tag::source1[]
        #raise NotImplementedError  # <3>
        pub_key_points = []
        for pub_key in sec_pubkeys:
            point = S256Point.parse(pub_key)
            pub_key_points.append(point)
        signatures = []
        for der_sig in der_signatures:
            sig = Signature.parse(der_sig)
            signatures.append(sig)

        for sig in signatures:
            if not valid_sig(sig, pub_key_points, z):
                stack.append(encode_num(0))
                return False
    except (ValueError, SyntaxError):
        return False
    stack.append(encode_num(1))
    return True
Beispiel #24
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        # signature is assumed to be using SIGHASH_ALL
        der_signatures.append(stack.pop()[:-1])
    # OP_CHECKMULTISIG bug
    stack.pop()
    try:
        # parse the sec_pubkeys into an array of points
        points = [S256Point.parse(sec) for sec in sec_pubkeys]
        # parse the der_signatures into an array of signatures
        sigs = [Signature.parse(der) for der in der_signatures]
        # loop through the signatures
        for sig in sigs:
            # bail early if we don't have any points left
            if len(points) == 0:
                # add a 0 to the stack using encode_num(0)
                stack.append(encode_num(0))
                # return True
                return True
            # while we have points
            while points:
                # get the point at the front (points.pop(0))
                point = points.pop(0)
                # see if this point can verify this sig with this z
                if point.verify(z, sig):
                    # break if so, this sig is valid!
                    break
        # if we made it this far, we have to add a 1 to the stack
        # use encode_num(1)
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #25
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])  # <1>
    stack.pop()  # <2>
    try:
        # parse all the points
        parsed_points = [S256Point.parse(p) for p in sec_pubkeys]

        # parse all the signatures
        parsed_signatures = [Signature.parse(s) for s in der_signatures]

        # loop through the signatures
        valid_sigs = 0
        for sig in parsed_signatures:
            # if we have no more points, signatures are no good
            if len(parsed_points) == 0:
                return False

            # we loop until we find the point which works with this signature
            for i, p in enumerate(parsed_points):
                print(i)
                # get the current point from the list of points
                # we check if this signature goes with the current point
                if p.verify(z, sig):
                    parsed_points.pop(i)
                    valid_sigs += 1
                    
        # the signatures are valid, so push a 1 to the stack
        if valid_sigs == len(parsed_signatures):
            stack.pop(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #26
0
    def test_sig_hash_bip143(self):
        raw_tx = unhexlify(
            '0100000001fd5145175fafdee6d20ac376e376cf26d933848ba5aa177d0d163a462fb3f183010000006b483045022100f49a17e80098bc057e319b890bdc42fe7224e7f6beb69a650102f802239be154022069742f504fdd52906c14d0d18ff0808e01146813775602163ec10d419270c1c541210223f1c80f382f086e2af7ad9d05227d94b6cf292596b9853f04a91194048f9048ffffffff0236820100000000001976a914dc10e999a5f18eb510feec09206d1812fa24a9c288ac5c058049000000001976a91421704f258089af191df1a4abed2b48ec11d6063e88ac00000000'
        )
        stream = BytesIO(raw_tx)
        tx = Tx.parse(stream)
        tx_in = tx.tx_ins[0]
        raw_tx2 = unhexlify(
            '010000000185037eb5531900f2f450e55cd950c509310229c0444e318a8811eecfa3b5c183010000006b483045022100f4a6e308ff7846bd19d394ec1b7263e051f2a60e6819feb006cdb9047bdd21a502206d969dfb5dfee3e53ed1a79b441d1cc2b7b8fe945ac7507c3b5e180565fbaead4121037765d8921f9559a6f03d620a1687a57e5b4ecb9efa5b41fc44555da0a376f81affffffff021ffc6c00000000001976a914fe1f6bea216c790c30d07f52966850268a3f90a788acfc8b8149000000001976a9142563b8536a228ec866e1c1084044a7730e53758888ac00000000'
        )
        stream2 = BytesIO(raw_tx2)
        tx2 = Tx.parse(stream2)
        tx_in._value = tx2.tx_outs[1].amount
        tx_in._script_pubkey = tx2.tx_outs[1].script_pubkey.serialize()
        der, hash_type = tx_in.der_signature()
        sec = tx_in.sec_pubkey()
        sig = Signature.parse(der)
        point = S256Point.parse(sec)
        z = tx.sig_hash_bip143(0, hash_type)
        self.assertTrue(point.verify(z, sig))
        self.assertTrue(tx.verify_input(0))
        self.assertTrue(tx.verify())

        raw_tx = unhexlify(
            '01000000066f267f335a54abf404c66a7a6e9ed3d77566a09ce11632f57029a677f42c6095000000006b483045022100fb0b16699c9b0984345c7860e208c04694aaa5117c8306082cfafc58b53e489a02203cd53408f1f8c8ff29701a9d1f6960b2dc5e1039f0eea949c5a886ac367e1e38412102fdcae0e5a55b20c8d3cbdf451d39f6d47daa50f884ed0ffcf0ae0adfeec4abb9ffffffff4ceb6a2894b19b96fedd543750bf7307805a2f6ca189c8c42d1abbe2930235fa000000006a4730440220794c269d519b567aa694de6dcde1d09dffa30b69dc18a619ce9ea65f239899150220156394f70f405c0710851490b9f21dc8a23931fbdc8a70ea51f73e9b00274a5c412103b708cd0b3329cff03611b0155384d1d4f40cb3aa30f82d8f4a34da044c868058ffffffff15053ac5123a25e0adf0ed998dfb710fff827861ac1a4c6601be8034179350ab000000006a473044022020e7b448318fa44b977d557b639aaf3a9666cf6d8dd446bd7812e752ddfcd1d302207159d22c2e379b77b0514b8e0767d0e9fff7063a659c268d605be436f65703884121031a97eb1664ceffa32988f7ea7c6726d681f1385b9765be1a40d6083fba4e6c69ffffffff2e1fb2ad94461104b147ffe95d0534eb98495c45831547b70eae652ac6cf52d0000000006b483045022100b0ce5496d51673f82430eee24c57f7f2f2631e5b9b32c78bbd79e1cbf3f6297b02201c807ecfa86c1c493e83f1235a19e4426da651e8f76c2f4b41ceebf1222a9291412102e4aa3631fd0b4a877c7c0a040b8211636f743c392ce17e6f266beb1b62490af9ffffffff311368bcf1bac2ae2e906bd7e84e9b45da861a63154ae5c3d69840f65486ba86000000006b483045022100d5f63c5284604eefb942fa9710f8d5b5bccf431e63c496237a0c41eb5c6debf102202bda17f3b7406b9c41f44c7377261413cfa144489a70a40e9e9126b3e7f2fc734121032e413587a71814365b7912eac3a052d8ac0c5f2351d3d84863a02bafefd41f19ffffffff2e9e219c5a68079891a8d2b00bfcf3772fa605997773c2c516bb5ac99aa8ee06000000006a47304402207b6e0d96d0ce538fb54fcb1731a35632b6e40efde834ce45ee22f0c0f5baa886022009327de37e3fb657af29161d265db558869c09e295e84ddb2f686a492db0015a41210389c44f336f7c8cc3096f8f40bc5bdbffea24da9e26649dbe6b862d7d369698d0ffffffff0102b84f05000000001976a9145c52250125494685f133df34f47fb88799b2903588ac00000000'
        )
        stream = BytesIO(raw_tx)
        tx = Tx.parse(stream)
        inputs = (
            ('18Lk6CB2WSpc4BVbxWhZrxLaYaJA2XVtyU', 24285000),
            ('13xY6E2tnBC5eGFCkayAUdVVcuGkFPoebJ', 824730),
            ('1BjFmsA4StiDa9xjAwahFXNpzR6SfXxBFD', 7583000),
            ('1Nn5QirD9iFT5kSF35XN8E3SX3SJM1daPL', 13150000),
            ('1HE8AdXHkP2bbnKmgENET4iyCHncP7rd7G', 32850000),
            ('1J3BgNjoqeR5JhHzC2rgorzBXTmdbmYcau', 10422900),
        )
        for i, data in enumerate(inputs):
            addr, value = data
            tx_in = tx.tx_ins[i]
            i += 1
            h160 = decode_base58(addr)
            tx_in._value = value
            tx_in._script_pubkey = p2pkh_script(h160)
        self.assertTrue(tx.verify())
Beispiel #27
0
def op_checksig(stack, z):
    # check to see if there's at least 2 elements
    if len(stack) < 2:
        return False
    # get the sec_pubkey with stack.pop()
    sec_pubkey = stack.pop()
    # get the der_signature with stack.pop()[:-1] (last byte is removed)
    der_signature = stack.pop()[:-1]
    # parse the sec format pubkey with S256Point
    point = S256Point.parse(sec_pubkey)
    # parse the der format signature with Signature
    sig = Signature.parse(der_signature)
    # verify using the point, z and signature
    # if verified add encode_num(1) to the end, otherwise encode_num(0)
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Beispiel #28
0
def op_checkmultisig(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        der_signatures.append(stack.pop()[:-1])  # <1>
    stack.pop()  # <2>
    try:
        # end::source1[]
        # parse all the points
        points = [S256Point.parse(sec_pubkey) for sec_pubkey in sec_pubkeys]
        # parse all the signatures
        signatures = [Signature.parse(der) for der in der_signatures]
        # loop through the signatures
        for sig in signatures:
            # if we have no more points, signatures are no good
            if not points:
                return False
            # we loop until we find the point which works with this signature
            while points:
                # get the current point from the list of points
                point = points.pop(0)
                # we check if this signature goes with the current point
                if point.verify(z, sig):
                    break
        # the signatures are valid, so push a 1 to the stack
        if points:
            return False
        stack.append(encode_num(1))
        # tag::source1[]
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #29
0
def op_checkmultisig2(stack, z):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        # signature is assumed to be using SIGHASH_ALL
        der_signatures.append(stack.pop()[:-1])
    # OP_CHECKMULTISIG bug
    stack.pop()
    try:
        # parse all the points
        points = [S256Point.parse(sec) for sec in sec_pubkeys]
        # parse all the signatures
        sigs = [Signature.parse(der) for der in der_signatures]
        # loop through the signatures
        for sig in sigs:
            # if we have no more points, signatures are no good
            if len(points) == 0:
                LOGGER.info("signatures no good or not in right order")
                return False
            # we loop until we find the point which works with this signature
            while points:
                # get the current point from the list of points
                point = points.pop(0)
                # we check if this signature goes with the current point
                if point.verify(z, sig):
                    break
        # the signatures are valid, so push a 1 to the stack
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Beispiel #30
0
 def verify_input(self, input_index):
     '''Returns whether the input has a valid signature'''
     # Exercise 1.1: get the relevant input
     tx_in = self.tx_ins[input_index]
     # Exercise 6.2: get the number of signatures required. This is available in tx_in.script_sig.num_sigs_required()
     sigs_required = tx_in.script_sig.num_sigs_required()
     # Exercise 6.2: iterate over the sigs required and check each signature
     for sig_num in range(sigs_required):
         # Exercise 1.1: get the point from the sec format (tx_in.sec_pubkey())
         # Exercise 6.2: get the sec_pubkey at current signature index (check sec_pubkey function)
         point = S256Point.parse(tx_in.sec_pubkey(index=sig_num))
         # Exercise 1.1: get the der sig and hash_type from input
         # Exercise 6.2: get the der_signature at current signature index (check der_signature function)
         der, hash_type = tx_in.der_signature(index=sig_num)
         # Exercise 1.1: get the signature from der format
         signature = Signature.parse(der)
         # Exercise 1.1: get the hash to sign
         z = self.sig_hash(input_index, hash_type)
         # Exercise 1.1: use point.verify on the hash to sign and signature
         if not point.verify(z, signature):
             return False
     return True