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
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
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:]
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
def verifyData(self, data): # verify hash msg_hash = data[:32] if msg_hash != keccak256(data[32:]): print " First 32 bytes are not keccak256 hash of the rest." return else: print " Verified message hash." # verify signature signature = data[32:97] signed_data = data[97:] deserialized_sig = self.priv_key.ecdsa_recoverable_deserialize(signature[:64], ord(signature[64])) remote_pubkey = self.priv_key.ecdsa_recover(keccak256(signed_data), deserialized_sig, raw = True) pub = PublicKey() pub.public_key = remote_pubkey verified = pub.ecdsa_verify(keccak256(signed_data), pub.ecdsa_recoverable_convert(deserialized_sig), raw = True) if not verified: print " Signature invalid" return False else: print " Verified signature." return True
def handlePacket(self, data, addr): # print("received message[" + str(addr) + "]") msg_hash = data[:32] # 32 Byte Hash raw_sig = data[32:97] # 64 Byte + 1 Byte Signature ptype = data[97] # 1 Byte packet_type pdata = data[98:] # Rest is rlp-encoded data decdata = rlp.decode(pdata) signedData = data[97:] # Verify hash if msg_hash != keccak256(data[32:]): print("Invalid message hash!") exit(0) # Verify signature deserialized_sig = self.priv_key.ecdsa_recoverable_deserialize( raw_sig[:64], raw_sig[64]) remote_pubkey = self.priv_key.ecdsa_recover(keccak256(signedData), deserialized_sig, raw=True) pub = PublicKey() pub.public_key = remote_pubkey verified = pub.ecdsa_verify( keccak256(signedData), pub.ecdsa_recoverable_convert(deserialized_sig), raw=True) if not verified: print("Signature invalid!") exit(0) else: print("Public Key: " + pub.serialize().hex()) packet_type = bytes([ptype]) if packet_type == PingPacket.packet_type: print("Got ping.") recv_ping = PingPacket.unpack(rlp.decode(pdata)) print(str(recv_ping)) # self.pong(msg_hash, recv_ping.To()) # TODO: Find out the correct endpoint self.pong(self.theirEndpoint, msg_hash) if packet_type == PongPacket.packet_type: print("Got pong.") recv_pong = PongPacket.unpack(decdata) print(str(recv_pong)) # self.ping(self.theirEndpoint) if packet_type == FindNodePacket.packet_type: print("Got FindNodePacket.") recv_findnode = FindNodePacket.unpack(rlp.decode(pdata)) target = recv_findnode.target print("Target: " + str(target.hex())) self.neighbors(self.theirEndpoint, target) if packet_type == NeighborsPacket.packet_type: print("Got NeighborsPacket.") recv_neighbors = NeighborsPacket.unpack(rlp.decode(pdata)) print("# Neighbors: " + str(len(recv_neighbors.neighbors)))
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:]
def receive(self, data, addr): """ macSize = 256 / 8 = 32 sigSize = 520 / 8 = 65 headSize = macSize + sigSize = 97 hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] shouldhash := crypto.Sha3(buf[macSize:]) """ # verify hash msg_hash = data[:32] if msg_hash != keccak256(data[32:]): print " First 32 bytes are not keccak256 hash of the rest." return else: print " Verified message hash." # verify signature signature = data[32:97] signed_data = data[97:] deserialized_sig = self.priv_key.ecdsa_recoverable_deserialize(signature[:64], ord(signature[64])) remote_pubkey = self.priv_key.ecdsa_recover(keccak256(signed_data), deserialized_sig, raw=True) pub = PublicKey() pub.public_key = remote_pubkey verified = pub.ecdsa_verify(keccak256(signed_data), pub.ecdsa_recoverable_convert(deserialized_sig), raw=True) if not verified: print " Signature invalid" return else: print " Verified signature." response_types = { PingNode.packet_type: self.receive_ping, Pong.packet_type: self.receive_pong, FindNeighbors.packet_type: self.receive_find_neighbors, Neighbors.packet_type: self.receive_neighbors } try: packet_type = data[97] dispatch = response_types[packet_type] except KeyError: print " Unknown message type: " + data[97] return payload = data[98:] dispatch(payload, msg_hash, addr)
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
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')
def receive(self): print "listening..." data, addr = self.sock.recvfrom(1024) print "received message[", addr, "]" ## verify hash msg_hash = data[:32] if msg_hash != keccak256(data[32:]): print " First 32 bytes are not keccak256 hash of the rest." return else: print " Verified message hash." ## verify signature signature = data[32:97] signed_data = data[97:] deserialized_sig = self.priv_key.ecdsa_recoverable_deserialize( signature[:64], ord(signature[64])) remote_pubkey = self.priv_key.ecdsa_recover(keccak256(signed_data), deserialized_sig, raw=True) pub = PublicKey() pub.public_key = remote_pubkey verified = pub.ecdsa_verify( keccak256(signed_data), pub.ecdsa_recoverable_convert(deserialized_sig), raw=True) if not verified: print " Signature invalid" return else: print " Verified signature." response_types = { PingNode.packet_type: self.receive_ping, Pong.packet_type: self.receive_pong } try: packet_type = data[97] dispatch = response_types[packet_type] except KeyError: print " Unknown message type: " + data[97] return payload = data[98:] dispatch(payload)
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
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 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
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
def receive(self, data, addr): """ macSize = 256 / 8 = 32 sigSize = 520 / 8 = 65 headSize = macSize + sigSize = 97 hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] shouldhash := crypto.Sha3(buf[macSize:]) """ # verify hash msg_hash = data[:32] assert msg_hash == keccak256( data[32:]), "First 32 bytes are not keccak256 hash of the rest" # verify signature signature = data[32:97] signed_data = data[97:] deserialized_sig = self.priv_key.ecdsa_recoverable_deserialize( signature[:64], ord(signature[64])) remote_pubkey = self.priv_key.ecdsa_recover(keccak256(signed_data), deserialized_sig, raw=True) pub = PublicKey() pub.public_key = remote_pubkey verified = pub.ecdsa_verify( keccak256(signed_data), pub.ecdsa_recoverable_convert(deserialized_sig), raw=True) assert verified, "Signature invalid" pubkey = pubkey_format(pub)[1:] hex_id = binascii.hexlify(keccak256(pubkey)) packet_type = data[97] payload = rlp.decode(data[98:]) if packet_type == PingNode.packet_type: # fake ip in packet payload[1][0] = addr[0] ping = PingNode.unpack(payload) if expired(ping): return self.receive_ping(addr, pubkey, ping, msg_hash) elif packet_type == Pong.packet_type: pong = Pong.unpack(payload) if expired(pong): return self.receive_pong(addr, pubkey, pong) elif packet_type == FindNeighbors.packet_type: fn = FindNeighbors.unpack(payload) if expired(fn): return self.receive_find_neighbors(addr, pubkey, fn) elif packet_type == Neighbors.packet_type: neighbours = Neighbors.unpack(payload) if expired(neighbours): return self.receive_neighbors(addr, pubkey, neighbours) else: assert False, " Unknown message type: {}".format(packet_type)