Beispiel #1
0
def verify(base64sig, msg, address, ctx=None, net=BC):
    if len(base64sig) != 88:
        raise Exception("Invalid base64 signature length")

    msg = msg.encode('utf8')
    fullmsg = (varint(len(net.msgprefix)) + net.msgprefix +
               varint(len(msg)) + msg)
    hmsg = shasha(fullmsg).digest()

    sigbytes = base64.b64decode(base64sig)
    if len(sigbytes) != 65:
        raise Exception("Invalid signature length")

    compressed = (ord(sigbytes[0:1]) - 27) & 4 != 0
    rec_id = (ord(sigbytes[0:1]) - 27) & 3

    p = PublicKey(ctx=ctx, flags=ALL_FLAGS)
    sig = p.ecdsa_recoverable_deserialize(sigbytes[1:], rec_id)

    # Recover the ECDSA public key.
    recpub = p.ecdsa_recover(hmsg, sig, raw=True)
    pubser = PublicKey(recpub, ctx=ctx).serialize(compressed=compressed)

    addr = pubkey_to_addr(pubser, net)
    return addr == address
Beispiel #2
0
def verify(base64sig, msg, address, ctx=None, net=BC):
    if len(base64sig) != 88:
        raise Exception("Invalid base64 signature length")

    msg = msg.encode('utf8')
    fullmsg = (varint(len(net.msgprefix)) + net.msgprefix + varint(len(msg)) +
               msg)
    hmsg = shasha(fullmsg).digest()

    sigbytes = base64.b64decode(base64sig)
    if len(sigbytes) != 65:
        raise Exception("Invalid signature length")

    compressed = (ord(sigbytes[0:1]) - 27) & 4 != 0
    rec_id = (ord(sigbytes[0:1]) - 27) & 3

    p = PublicKey(ctx=ctx, flags=ALL_FLAGS)
    sig = p.ecdsa_recoverable_deserialize(sigbytes[1:], rec_id)

    # Recover the ECDSA public key.
    recpub = p.ecdsa_recover(hmsg, sig, raw=True)
    pubser = PublicKey(recpub, ctx=ctx).serialize(compressed=compressed)

    addr = pubkey_to_addr(pubser, net)
    return addr == address
class Secp256k1_compact(object):
    def __init__(self):
        self.priv_key = PrivateKey()
        self.pub_key = PublicKey(pubkey=None, raw=False, flags=secp256k1.ALL_FLAGS)

    def ecdsa_compact_sign(self, msg32, privkey):
        if type(privkey) == unicode:
            privkey = privkey.encode('utf-8')
        self.priv_key.set_raw_privkey(privkey)
        sig = self.priv_key.ecdsa_sign_recoverable(msg32, raw=True)
        return self.priv_key.ecdsa_recoverable_serialize(sig)

    def ecdsa_compact_recover(self, msg32, sign):
        if not len(sign) == 2:
            sign = (sign[:64], ord(sign[64]))
        assert len(sign) == 2
        deserialized_sig = self.pub_key.ecdsa_recoverable_deserialize(sign[0], sign[1])
        self.pub_key.public_key = self.pub_key.ecdsa_recover(msg32, deserialized_sig, raw=True)
        return self.pub_key.serialize(compressed=False)

    def ecdsa_compact_verify(self, msg32, sign, pub):
        # Check if pubkey has been bin_electrum encoded.
        # If so, append \04 to the front of the key, to make sure the length is 65
        if len(pub) == 64:
            pub = '\04'+pub
        pub_k = PublicKey().deserialize(pub)
        pub_key = PublicKey(pub_k, raw=False, flags=secp256k1.ALL_FLAGS)
        der_sig = pub_key.ecdsa_recoverable_deserialize(sign[0], sign[1])
        raw_sig = pub_key.ecdsa_recoverable_convert(der_sig)
        return pub_key.ecdsa_verify(msg32, raw_sig, raw=True)
Beispiel #4
0
    def sender(self):

        if not self._sender:
            # Determine sender
            if self.v:
                if self.r >= N or self.s >= N or self.v < 27 or self.v > 28 \
                or self.r == 0 or self.s == 0:
                    raise InvalidTransaction("Invalid signature values!")
                log.debug('recovering sender')
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = utils.sha3(rlpdata)

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.r)), 32) + zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.s)), 32),
                            self.v - 27
                        ),
                        raw=True
                    )
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise InvalidTransaction("Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * 32:
                    raise InvalidTransaction("Invalid signature (zero privkey cannot sign)")
                pub = encode_pubkey(pub, 'bin')
                self._sender = utils.sha3(pub[1:])[-20:]
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Beispiel #5
0
def recover(message: Union[bytes, str],
            signature: str,
            hex: bool = True) -> str:
    """Signs input data with provided private key

    Args:
        message (str): Message to recover address from
        signature (str): Signature with recovery bit
        hex (bool): Hex string is provided as input message

    Returns:
        signature (str): Recoverable signature with appended recovery bit
    """
    if type(message) == str and hex:
        data = bytes.fromhex(message)
    elif type(message) == str:
        data = message.encode("utf-8")
    else:
        data = message
    pub_key = PublicKey(flags=ALL_FLAGS)
    signature = bytes.fromhex(signature)
    signature = pub_key.ecdsa_recoverable_deserialize(
        signature[:-1], int.from_bytes(signature[-1:], "big"))
    pub_key = PublicKey(pub_key.ecdsa_recover(data, signature,
                                              digest=sha3_256))
    return address_from_public(pub_key.serialize(False).hex()[2:])
Beispiel #6
0
    def sender(self):

        if not self._sender:
            # Determine sender
            if self.v:
                if self.r >= N or self.s >= N or self.v < 27 or self.v > 28 \
                or self.r == 0 or self.s == 0:
                    raise InvalidTransaction("Invalid signature values!")
                log.debug('recovering sender')
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = utils.sha3(rlpdata)

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.r)), 32) + zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.s)), 32),
                            self.v - 27
                        ),
                        raw=True
                    )
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise InvalidTransaction("Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * 32:
                    raise InvalidTransaction("Invalid signature (zero privkey cannot sign)")
                pub = encode_pubkey(pub, 'bin')
                self._sender = utils.sha3(pub[1:])[-20:]
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Beispiel #7
0
def ecrecover(msg, signature, address=None):
    """
    Returns None on failure, returns the recovered address on success.
    If address is provided: Returns True if the recovered address matches it,
    otherwise False.
    """
    rawhash = sha3(msg)

    if len(signature) >= 65:
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        if address:
            return False
        else:
            return None

    pk = PublicKey(flags=ALL_FLAGS)
    pk.public_key = pk.ecdsa_recover(
        rawhash,
        pk.ecdsa_recoverable_deserialize(
            zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) +
            zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32), v - 27),
        raw=True)
    pub = pk.serialize(compressed=False)

    recaddr = data_encoder(sha3(pub[1:])[-20:])
    if address:
        if not address.startswith("0x"):
            recaddr = recaddr[2:]

        return recaddr == address

    return recaddr
Beispiel #8
0
 def recover_sender(self):
     if self.v:
         if self.r >= N or self.s >= P or self.v < 27 or self.v > 28 \
            or self.r == 0 or self.s == 0:
             raise InvalidSignature()
         rlpdata = rlp.encode(self, self.__class__.exclude(['v', 'r', 's']))
         rawhash = sha3(rlpdata)
         pk = PublicKey(flags=ALL_FLAGS)
         try:
             pk.public_key = pk.ecdsa_recover(
                 rawhash,
                 pk.ecdsa_recoverable_deserialize(
                     zpad(
                         "".join(
                             chr(c)
                             for c in int_to_32bytearray(self.r)), 32) +
                     zpad(
                         "".join(
                             chr(c)
                             for c in int_to_32bytearray(self.s)), 32),
                     self.v - 27),
                 raw=True)
             pub = pk.serialize(compressed=False)
         except Exception:
             raise InvalidSignature()
         if pub[1:] == "\x00" * 32:
             raise InvalidSignature()
         pub = encode_pubkey(pub, 'bin')
         return sha3(pub[1:])[-20:]
Beispiel #9
0
def ecdsa_recover(message, signature):
    assert len(signature) == 65
    pk = PublicKey(flags=ALL_FLAGS, ctx=ctx)
    pk.public_key = pk.ecdsa_recover(message,
                                     pk.ecdsa_recoverable_deserialize(
                                         signature[:64], ord(signature[64])),
                                     raw=True)
    return pk.serialize(compressed=False)[1:]
Beispiel #10
0
def ecdsa_verify(pubkey, signature, message):
    assert len(signature) == 65
    assert len(pubkey) == 64
    pk = PublicKey('\04' + pubkey, raw=True, ctx=ctx)
    return pk.ecdsa_verify(message,
                           pk.ecdsa_recoverable_convert(
                               pk.ecdsa_recoverable_deserialize(
                                   signature[:64], ord(signature[64]))),
                           raw=True)
 def ecdsa_compact_verify(self, msg32, sign, pub):
     # Check if pubkey has been bin_electrum encoded.
     # If so, append \04 to the front of the key, to make sure the length is 65
     if len(pub) == 64:
         pub = '\04'+pub
     pub_k = PublicKey().deserialize(pub)
     pub_key = PublicKey(pub_k, raw=False, flags=secp256k1.ALL_FLAGS)
     der_sig = pub_key.ecdsa_recoverable_deserialize(sign[0], sign[1])
     raw_sig = pub_key.ecdsa_recoverable_convert(der_sig)
     return pub_key.ecdsa_verify(msg32, raw_sig, raw=True)
Beispiel #12
0
    def sender(self):
        if not self._sender:
            if not is_bitcoin_available() or not is_secp256k1_available():
                raise ImportError(
                    "In order to derive the sender for transactions the "
                    "`bitcoin` and `secp256k1` packages must be installed."
                )
            from bitcoin import N
            from secp256k1 import PublicKey, ALL_FLAGS

            # Determine sender
            if self.v:
                has_invalid_signature_values = (
                    self.r >= N or
                    self.s >= N or
                    self.v < 27 or
                    self.v > 28 or
                    self.r == 0 or
                    self.s == 0
                )
                if has_invalid_signature_values:
                    raise ValueError("Invalid signature values!")
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = decode_hex(sha3(rlpdata))

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            pad_left(
                                int_to_big_endian(self.r),
                                32,
                                b'\x00',
                            ) + pad_left(
                                int_to_big_endian(self.s),
                                32,
                                b'\x00',
                            ),
                            self.v - 27
                        ),
                        raw=True
                    )
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise ValueError("Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * (len(pub) - 1):
                    raise ValueError("Invalid signature (zero privkey cannot sign)")

                self._sender = to_address(sha3(pub[1:])[-40:])
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Beispiel #13
0
def recover_user_id(msg, signature):
    if isinstance(msg, str):
        msg = msg.encode('utf8')

    key = PublicKey(flags=ALL_FLAGS)
    sig = b58decode(signature)
    sig = key.ecdsa_recoverable_deserialize(sig[1:], sig[0] - 31)
    key.public_key = key.ecdsa_recover(msg, sig)
    serialized_pubkey = key.serialize(True)
    hashed = b'\x00' + ripemd160(sha256(serialized_pubkey))
    checksum = sha256(sha256(hashed))[:4]
    return b58encode(hashed + checksum).decode('ascii')
Beispiel #14
0
def recover_publickey(messagedata, signature):
    if len(signature) != 65:
        raise ValueError('invalid signature')

    key = PublicKey(flags=ALL_FLAGS)  # FLAG_SIGN is required to recover publickeys
    signature_data = key.ecdsa_recoverable_deserialize(
        signature[:64],
        ord(signature[64]),
    )

    message_hash = sha3(messagedata)
    publickey_data = key.ecdsa_recover(message_hash, signature_data, raw=True)
    publickey = PublicKey(publickey_data).serialize(compressed=False)

    return publickey
Beispiel #15
0
    def sender(self):
        if not self._sender:
            if not is_bitcoin_available() or not is_secp256k1_available():
                raise ImportError(
                    "In order to derive the sender for transactions the "
                    "`bitcoin` and `secp256k1` packages must be installed.")
            from bitcoin import N
            from secp256k1 import PublicKey, ALL_FLAGS

            # Determine sender
            if self.v:
                has_invalid_signature_values = (self.r >= N or self.s >= N
                                                or self.v < 27 or self.v > 28
                                                or self.r == 0 or self.s == 0)
                if has_invalid_signature_values:
                    raise ValueError("Invalid signature values!")
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = decode_hex(sha3(rlpdata))

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            pad_left(
                                int_to_big_endian(self.r),
                                32,
                                b'\x00',
                            ) + pad_left(
                                int_to_big_endian(self.s),
                                32,
                                b'\x00',
                            ), self.v - 27),
                        raw=True)
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise ValueError(
                        "Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * (len(pub) - 1):
                    raise ValueError(
                        "Invalid signature (zero privkey cannot sign)")

                self._sender = to_address(sha3(pub[1:])[-40:])
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Beispiel #16
0
def recover_publickey(messagedata, signature):
    if len(signature) != 65:
        raise ValueError('invalid signature')

    key = PublicKey(
        flags=ALL_FLAGS)  # FLAG_SIGN is required to recover publickeys
    signature_data = key.ecdsa_recoverable_deserialize(
        signature[:64],
        ord(signature[64]),
    )

    message_hash = sha3(messagedata)
    publickey_data = key.ecdsa_recover(message_hash, signature_data, raw=True)
    publickey = PublicKey(publickey_data).serialize(compressed=False)

    return publickey
Beispiel #17
0
def extract_ecdsa_signer(msg_hash, signature):
    msg_hash_bytes = decode_hex(msg_hash) if msg_hash.startswith(b'0x') else msg_hash
    signature_bytes = decode_hex(signature) if signature.startswith(b'0x') else signature

    pk = PublicKey(flags=ALL_FLAGS)
    rec_id = signature_bytes[64]
    if is_string(rec_id):
        rec_id = ord(rec_id)
    pk.public_key = pk.ecdsa_recover(
        msg_hash_bytes,
        pk.ecdsa_recoverable_deserialize(
            signature_bytes[:64], rec_id,
        ),
        raw=True,
    )
    pk_serialized = pk.serialize(compressed=False)
    address = add_0x_prefix(sha3(encode_pubkey(pk_serialized, 'bin')[1:])[-40:])
    return address
def extract_ecdsa_signer(msg_hash, signature):
    msg_hash_bytes = decode_hex(msg_hash) if msg_hash.startswith(b'0x') else msg_hash
    signature_bytes = decode_hex(signature) if signature.startswith(b'0x') else signature

    pk = PublicKey(flags=ALL_FLAGS)
    rec_id = signature_bytes[64]
    if is_string(rec_id):
        rec_id = ord(rec_id)
    pk.public_key = pk.ecdsa_recover(
        msg_hash_bytes,
        pk.ecdsa_recoverable_deserialize(
            signature_bytes[:64], rec_id,
        ),
        raw=True,
    )
    pk_serialized = pk.serialize(compressed=False)
    address = add_0x_prefix(sha3(encode_pubkey(pk_serialized, 'bin')[1:])[-40:])
    return address
    def _recover_key(self, msg_hash: bytes, signature: bytes,
                     compressed: bool):
        _public_key = PublicKey(flags=ALL_FLAGS)

        if isinstance(msg_hash, bytes) and len(msg_hash) == 32 and isinstance(
                signature, bytes) and len(signature) == 65:
            internal_recover_sig = _public_key.ecdsa_recoverable_deserialize(
                ser_sig=signature[:64], rec_id=signature[64])
            internal_pubkey = _public_key.ecdsa_recover(msg_hash,
                                                        internal_recover_sig,
                                                        raw=True,
                                                        digest=None)

            public_key = PublicKey(internal_pubkey,
                                   raw=False,
                                   ctx=_public_key.ctx)
            return public_key.serialize(compressed)

        return None
Beispiel #20
0
def proc_ecrecover(ext, msg):
    # print('ecrecover proc', msg.gas)
    OP_GAS = opcodes.GECRECOVER
    gas_cost = OP_GAS
    if msg.gas < gas_cost:
        return 0, 0, []

    message_hash_bytes = [0] * 32
    msg.data.extract_copy(message_hash_bytes, 0, 0, 32)
    message_hash = b''.join(map(ascii_chr, message_hash_bytes))

    # TODO: This conversion isn't really necessary.
    # TODO: Invesitage if the check below is really needed.
    v = msg.data.extract32(32)
    r = msg.data.extract32(64)
    s = msg.data.extract32(96)

    if r >= bitcoin.N or s >= bitcoin.N or v < 27 or v > 28:
        return 1, msg.gas - opcodes.GECRECOVER, []

    signature_bytes = [0] * 64
    msg.data.extract_copy(signature_bytes, 0, 64, 32)
    msg.data.extract_copy(signature_bytes, 32, 96, 32)
    signature = b''.join(map(ascii_chr, signature_bytes))

    pk = PublicKey(flags=ALL_FLAGS)
    try:
        pk.public_key = pk.ecdsa_recover(
            message_hash,
            pk.ecdsa_recoverable_deserialize(
                signature,
                v - 27
            ),
            raw=True
        )
    except Exception:
        # Recovery failed
        return 1, msg.gas - gas_cost, []

    pub = pk.serialize(compressed=False)
    o = [0] * 12 + [safe_ord(x) for x in utils.sha3(pub[1:])[-20:]]
    return 1, msg.gas - gas_cost, o
Beispiel #21
0
def verify_recoverable_message(signature, message, recid):
    """ Verifies a signature of a hash and returns the address that signed it.
    If no address is returned, signature is bad.
    """
    empty = PublicKey(flags=ALL_FLAGS)
    sig = empty.ecdsa_recoverable_deserialize(signature, args.recid)
    msg = MESSAGE_TEMPLATE.format(message)
    pubkey = empty.ecdsa_recover(msg, sig)
    addr_hash = public_key_to_hash(pubkey.serialize())
    address = address_from_hash(address)

    try:
        sig_raw = pub.ecdsa_deserialize(signature)
        good = pub.ecdsa_verify(message, sig_raw)
    except:
        good = False

    if good:
        return address
    else:
        return None
Beispiel #22
0
def proc_ecrecover(ext, msg):
    # print('ecrecover proc', msg.gas)
    OP_GAS = opcodes.GECRECOVER
    gas_cost = OP_GAS
    if msg.gas < gas_cost:
        return 0, 0, []

    message_hash_bytes = [0] * 32
    msg.data.extract_copy(message_hash_bytes, 0, 0, 32)
    message_hash = b''.join(map(ascii_chr, message_hash_bytes))

    # TODO: This conversion isn't really necessary.
    # TODO: Invesitage if the check below is really needed.
    v = msg.data.extract32(32)
    r = msg.data.extract32(64)
    s = msg.data.extract32(96)

    if r >= bitcoin.N or s >= bitcoin.N or v < 27 or v > 28:
        return 1, msg.gas - opcodes.GECRECOVER, []

    signature_bytes = [0] * 64
    msg.data.extract_copy(signature_bytes, 0, 64, 32)
    msg.data.extract_copy(signature_bytes, 32, 96, 32)
    signature = b''.join(map(ascii_chr, signature_bytes))

    pk = PublicKey(flags=ALL_FLAGS)
    try:
        pk.public_key = pk.ecdsa_recover(message_hash,
                                         pk.ecdsa_recoverable_deserialize(
                                             signature, v - 27),
                                         raw=True)
    except Exception:
        # Recovery failed
        return 1, msg.gas - gas_cost, []

    pub = pk.serialize(compressed=False)
    o = [0] * 12 + [safe_ord(x) for x in utils.sha3(pub[1:])[-20:]]
    return 1, msg.gas - gas_cost, o