Beispiel #1
0
def makeList(fds, conn, pk):
    print("Start discovery process.")
    timestamp = time.time() * 1000  #ms単位の現在時刻
    print("timestamp %d." % timestamp)
    #検索
    priv_key = PrivateKey()
    priv_key.deserialize(pk)
    rlpxd = RLPxDiscovery(priv_key, my_port=22222)
    rlpxd.listen()
    for i in fds:
        if i[3] != ServerIdsTable.STATUS_ENABLE:
            continue
        ipport = urlparse(i[1])
        print("Send PingPacket to %s %s:%d." %
              (i[2], ipport.hostname, ipport.port))
        rlpxd.sendPing(ipport.hostname, ipport.port)
    print("Wait 5 seconds.")
    time.sleep(5)
    r = rlpxd.close()
    print("Recrived %d packets." % (len(r)))

    def toMsg(info):
        return "enode://%s:%d %s" % (info["addr"], info["port"],
                                     datetime.fromtimestamp(
                                         info["packet"]["payload"].timestamp).
                                     strftime("%Y/%m/%d:%H%M%S"))

    ret = []
    for i in fds:
        if i[3] != ServerIdsTable.STATUS_ENABLE:
            continue
        #PONG受信した?
        msg = ""
        status = "OFFLINE"
        for j in r:
            #PONGのみを対象にする
            if j["packet"]["packet_type"] != PongPayload.PACKET_TYPE:
                #不明なパケットタイプ
                print("I", end="")
                continue
            #ip/portの一致チェック
            ipport = urlparse(i[1])
            if ipport.hostname != j["addr"] or ipport.port != j["port"]:
                continue
            print("A", end="")
            msg = toMsg(j)
            status = "ONLINE"
            break
        #sid,timestamp,status,description,url
        ret.append([i[0], timestamp, status, msg, i[1]])
    print()
    print("Done.")
    return ret
Beispiel #2
0
class PingServer(object):
    def __init__(self, my_endpoint: EndPoint):
        self.endpoint = my_endpoint

        # get private key
        with open('priv_key', 'r') as priv_key_file:
            priv_key_serialized = priv_key_file.read()
        self.priv_key = PrivateKey()  # type: PrivateKey
        self.priv_key.deserialize(priv_key_serialized)

        # init socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))

    def wrap_packet(self, packet):
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        payload = b''.join(
            [sig_serialized[0],
             str.encode(chr(sig_serialized[1])), payload])

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def udp_listen(self):
        def receive_ping():
            print("listening...")
            data, addr = self.sock.recvfrom(1024)
            print("received message[", addr, "]")

        return threading.Thread(target=receive_ping)

    def ping(self, endpoint: EndPoint):
        ping = PingNode(self.endpoint, endpoint)
        message = self.wrap_packet(ping)
        print("sending ping...")
        self.sock.sendto(message,
                         (endpoint.address.exploded, endpoint.udpPort))
Beispiel #3
0
class Server(object):
    def __init__(self, my_endpoint):
        self.endpoint = my_endpoint

        # 获取私钥
        priv_key_file = open('priv_key', 'r')
        priv_key_serialized = priv_key_file.read()
        priv_key_file.close()
        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        # 初始化套接字
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))
        # set socket non-blocking mode
        self.sock.setblocking(0)

    def wrap_packet(self, packet):
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        payload = sig_serialized[0] + chr(sig_serialized[1]) + payload

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def listen(self):
        print "listening..."
        while True:
            ready = select.select([self.sock], [], [], 1.0)
            if ready[0]:
                data, addr = self.sock.recvfrom(2048)
                print "received message[", addr, "]:"
                self.receive(data)

    def listen_thread(self):
        thread = threading.Thread(target=self.listen)
        thread.daemon = True
        return thread

    def receive(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
        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)

    def receive_pong(self, payload, msg_hash):
        print " received Pong"
        print "", Pong.unpack(rlp.decode(payload))

    def receive_ping(self, payload, msg_hash):
        print " received Ping"
        ping = PingNode.unpack(rlp.decode(payload))
        pong = Pong(ping.endpoint_from, msg_hash, time.time() + 60)
        print "  sending Pong response: " + str(pong)
        self.send(pong, pong.to)

    def receive_find_neighbors(self, payload, msg_hash):
        print " received FindNeighbors"
        print "", FindNeighbors.unpack(rlp.decode(payload))

    def receive_neighbors(self, payload, msg_hash):
        print " received Neighbors"
        print "", Neighbors.unpack(rlp.decode(payload))

    def ping(self, endpoint):
        ping = PingNode(self.endpoint, endpoint, time.time() + 60)
        message = self.wrap_packet(ping)
        print "sending " + str(ping)
        self.sock.sendto(message,
                         (endpoint.address.exploded, endpoint.udpPort))

    def send(self, packet, endpoint):
        message = self.wrap_packet(packet)
        print "sending " + str(packet)
        self.sock.sendto(message,
                         (endpoint.address.exploded, endpoint.udpPort))
Beispiel #4
0
from secp256k1 import PrivateKey

priv_key_file = open('priv_key', 'r')
priv_key_serialized = priv_key_file.read()
priv_key_file.close()

priv_key = PrivateKey()
priv_key.deserialize(priv_key_serialized)
sig = priv_key.ecdsa_sign_recoverable('asdasd', raw=True)
print sig

Beispiel #5
0
class PingServer(object):
    def __init__(self, my_endpoint):
        self.endpoint = my_endpoint

        # get private key
        priv_key_file = open('priv_key', 'r')
        priv_key_serialized = priv_key_file.read()
        priv_key_file.close()
        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        # init socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))

    def wrap_packet(self, packet):
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        payload = sig_serialized[0] + chr(sig_serialized[1]) + payload

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def udp_listen(self):
        return threading.Thread(target=self.receive)

    def receive(self):
        print "listening..."
        data, addr = self.sock.recvfrom(1024)
        print "received message[", addr, "]"

        ## decode packet below

        ## 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 receive_pong(self, payload):
        print " received Pong"
        print "", Pong.unpack(rlp.decode(payload))

    def receive_ping(self, payload):
        print " received Ping"
        print "", PingNode.unpack(rlp.decode(payload))

    def ping(self, endpoint):
        ping = PingNode(self.endpoint, endpoint, time.time() + 60)
        message = self.wrap_packet(ping)
        print "sending " + str(ping)
        self.sock.sendto(message,
                         (endpoint.address.exploded, endpoint.udpPort))
class PingServer(object):
    def __init__(self, my_endpoint):
        self.endpoint = my_endpoint

        ## get private key
        priv_key_file = open('priv_key', 'r')
        priv_key_serialized = priv_key_file.read()
        priv_key_file.close()

        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        # bind socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))

        # bind tcp socket
        self.tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcpsock.bind(('0.0.0.0', self.endpoint.tcpPort))
        self.tcpsock.listen(10)



    # p2p is the based network
    # so, when the p2p network close
    # the system need to send a quit blockchain msg to Discover server
    def __del__(self):
        pass

    # # hash || signature || packet-type || packet-data
    def wrap_packet(self, packet):
        payload = packet.packet_type + rlp.encode(packet.pack())
        temp = keccak256(payload)
        sig = self.priv_key.ecdsa_sign_recoverable(temp, raw = True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        # signature || packet-type || packet-data
        payload = sig_serialized[0] + chr(sig_serialized[1]) + payload
        # hash
        payload_hash = keccak256(payload)
        return payload_hash + payload

    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 recvfrom(self):
        try:
            print "listening..."
            while True :
                data, addr = self.sock.recvfrom(1024)
                print "recvived mssage[", addr, "]"

                res = self.verifyData(data)
                if res:
                    self.dispatch_data(data)
        except:
            traceback.print_exc()
            raise RuntimeError('recvfrom error')

    def recvtcpfrom(self, sock):
        try:
            print "tcp socket listening..."
            while (True):
                data = sock.recv(1024)
                print "【TCP】: get data, data's length is: %d"%len(data)
                res = self.verifyData(data)
                if res:
                    self.dispatch_data(data)
        except:
            traceback.print_exc()
            raise RuntimeError('recvtcpfrom error')

    # 分裂一个进程
    def tcp_listern(self):
        try:
            while True:
                sock, addr = self.tcpsock.accept()
                t = threading.Thread(target=self.recvtcpfrom, args=(sock,))
                t.setDaemon(True)
                t.start()
        except:
            traceback.print_exc()
            raise RuntimeError('tcp_listern error')

    # 分裂一个线程来进行对tcp监听
    def start_tcp_listern(self):
        t = threading.Thread(target=self.tcp_listern)
        t.setDaemon(True)
        t.start()

    def start_udp_listern(self):
        # udp listern
        listern_thread = self.udp_listen()
        listern_thread.start()


    def udp_listen(self):
        thread = threading.Thread(target= self.recvfrom,)
        thread.setDaemon(True)
        return thread

    def rawsendudpmsg(self, endpoint,  message):
        self.sock.sendto(message, (endpoint.address.exploded, endpoint.udpPort))

    # ping send a hello msg
    def ping(self, endpoint):
        ping = PingProtrol(self.endpoint, endpoint, time.time())
        message = self.wrap_packet(ping)
        self.rawsendudpmsg(endpoint, message)

    def pong(self, pongNode):
        message = self.wrap_packet(pongNode)
        self.rawsendudpmsg(pongNode.to, message)


    def dispatch_data(self, data):
        response_types = {
            PingProtrol.packet_type: self.receive_ping,
            PongProtrol.packet_type: self.receive_pong,
            JoinProtrol.packet_type: self.receive_join,
            WelcomeProtrol.packet_type: self.receive_welcome,
            InitNodeProtrol.packet_type: self.receive_initnode,
            ChainMsgProtrol.packet_type: self.receive_msg
        }

        try:
            packet_type = data[97]
            dispatch = response_types[packet_type]
        except:
            print " Unknown message type: " + data[97]
            return

        payload = data[98:]
        dispatch(payload)

    # the function need overrided
    def receive_pong(self, payload):
        print " received Pong"
        print "", PongProtrol.unpack(rlp.decode(payload))

    def receive_ping(self, payload):
        print " received Ping"
        print "", PingProtrol.unpack(rlp.decode(payload))

    def receive_join(self, payload):
        print " received Join"
        print "", JoinProtrol.unpack(rlp.decode(payload))

    def receive_welcome(self, payload):
        print " received welcome"
        print "", JoinProtrol.unpack(rlp.decode(payload))

    def receive_initnode(self, payload):
        print " received initNode"
        print "", JoinProtrol.unpack(rlp.decode(payload))

    def receive_msg(self, payload):
        print " received msg"
        print "", JoinProtrol.unpack(rlp.decode(payload))


    # common function
    @staticmethod
    def SpecialEncode(endpoint):
        temp = {
            'ip': endpoint.address.exploded,
            'port': endpoint.tcpPort
        }
        return json.dumps(temp)

    @staticmethod
    def SpecialDecode(msg):
        return json.loads(msg)
Beispiel #7
0
from secp256k1 import PrivateKey, PublicKey
import binascii
import sha3

N_ADDRESS_BYTES = 20
N_PUB_KEY_BYTES = 64
address = 0x6e5ab887860e199b91b92d81f418c95d9ffd32cb
key = "40dad29726f7e1b56359d2f1cc5a5365cb105b410e1108b3da65c1d97bfe6f8e"
# b = long_to_bytes(key)
privkey = PrivateKey(bytes(bytearray.fromhex(key)), raw=True)
privkey_der = privkey.serialize()
assert privkey.deserialize(privkey_der) == privkey.private_key
print "privkey", privkey.serialize()
pubkey = privkey.pubkey
pub = pubkey.serialize(compressed=False)
print "pubkey", binascii.hexlify(pub[1:])
print "pubkey", sha3.keccak_256(pub[1:]).hexdigest()[-2 * N_ADDRESS_BYTES:]
Beispiel #8
0
class PingServer(object):
    def __init__(self, my_endpoint, remote_endpoint, pingSleep, privKeyFile,
                 kid):
        self.myEndpoint = my_endpoint
        self.theirEndpoint = remote_endpoint
        self.pingSleep = pingSleep
        self.kid = kid

        ## get private key
        pkf = open(privKeyFile, "r")
        priv_key_serialized = pkf.read()
        pkf.close()
        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        ## init socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(
            (self.myEndpoint.address.exploded, self.myEndpoint.udpPort))

    def startPingLoop(self):
        self.pingLoopThread = threading.Thread(target=self._pingLoop).start()

    def startListening(self):
        print("Server " + str(self.kid) + ", start listening")
        self.listenThread = threading.Thread(target=self._listenLoop).start()

    def _pingLoop(self):
        print("pingLoop")
        while True:
            self.ping(self.theirEndpoint)
            self.findnode(
                self.theirEndpoint,
                0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0
            )
            # self.neighbors(self.theirEndpoint, 0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0)
            time.sleep(self.pingSleep)

    def wrap_packet(self, packet):
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        # print(str(type(sig_serialized[0])) + " " + str(type(sig_serialized[1])) + str(type(payload)))
        # print(sig_serialized[1])
        payload = sig_serialized[0] + bytes([sig_serialized[1]]) + payload

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def _listenLoop(self):
        print("Start Listening...")
        while True:
            data, addr = self.sock.recvfrom(2048)
            print("--------------- New Packet (ID: " + str(self.kid) +
                  ") -------------")
            self.handlePacket(data, addr)

    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 ping(self, theirEndpoint):
        ping = PingPacket(self.myEndpoint, theirEndpoint, time.time() + 60)
        message = self.wrap_packet(ping)
        print("Sending ping to: " + str(theirEndpoint))
        self.sock.sendto(
            message, (theirEndpoint.address.exploded, theirEndpoint.udpPort))

    def pong(self, theirEndpoint, echo):
        pong = PongPacket(theirEndpoint, echo, time.time() + 60)
        message = self.wrap_packet(pong)
        print("Sending pong to: " + str(theirEndpoint))
        self.sock.sendto(
            message, (theirEndpoint.address.exploded, theirEndpoint.udpPort))

    def findnode(self, theirEndpoint, target):
        findnode = FindNodePacket(target, time.time() + 60)
        message = self.wrap_packet(findnode)
        print("Sending FindNodePacket to: " + str(theirEndpoint))
        self.sock.sendto(
            message, (theirEndpoint.address.exploded, theirEndpoint.udpPort))

    def neighbors(self, theirEndpoint, target):
        # Compute some close neighbors on the fly
        neighbors = self.computeClosestNeighbors(target)
        packet = NeighborsPacket(neighbors, time.time() + 60)
        message = self.wrap_packet(packet)
        print("Sending NeighborsPacket to: " + str(theirEndpoint))
        self.sock.sendto(
            message, (theirEndpoint.address.exploded, theirEndpoint.udpPort))

    def computeClosestNeighbors(self, target):
        # Just return some hard coded IDs for now
        return [
            Node(
                self.myEndpoint.address, self.myEndpoint.udpPort,
                self.myEndpoint.tcpPort,
                0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0
            ),
            Node(
                self.myEndpoint.address, self.myEndpoint.udpPort,
                self.myEndpoint.tcpPort,
                0x7f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0
            ),
        ]
Beispiel #9
0
class CrawlServer(object):
	def __init__(self, my_endpoint):
		self.endpoint = my_endpoint
		with open('priv_key', 'r') as priv_key_file:
			priv_key_serialized = priv_key_file.read()
		self.priv_key = PrivateKey()
		self.priv_key.deserialize(priv_key_serialized)

	def wrap_packet(self, packet):
		#packet_type + packet_data
		signature_payload = packet.packet_type + rlp.encode(packet.pack())
		# signature = sign(packet_type + packet_data)
		sig = self.priv_key.ecdsa_sign_recoverable(keccak256(signature_payload), raw=True)
		sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
		#signature encoded
		payload = sig_serialized[0] + bytes([sig_serialized[1]])
		#signature + packet_type + packet_data
		payload = payload + signature_payload
		#hash = keccak256(signature + packet_type + packet_data)
		payload_hash = keccak256(payload)
		#hash + signature + packet_type + packet_data
		return payload_hash + payload
	
	def discover(self, q, qset, out, count, running):

		#socket
		sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		sock.bind(('0.0.0.0', self.endpoint.udpPort+count))
		sock.settimeout(5)

		def request_neighbour_lsb(bucket):
			#generate nodeID to discover specified bucket
			hashedID = keccak256(self.their_endpoint.nodeID)
			match = False
			mask = 1
			while match is False:
				generatedID = bytes(random.randint(0,255) for _ in range(64))
				genHashed = keccak256(generatedID)
				if bucket == 0:
					if (genHashed[0] ^ hashedID[0]) & mask == mask:
						match = True
					else:
						match = False
				else:
					#get the bytes in which the relevant bits are and iterate over them
					for x in range(int(bucket/8)+1):
						#make mask according to position in byte array (if last relevant byte get specific bit mask)
						if x == int(bucket/8):
							mask = pow(2, bucket%8)-1
						else:
							mask = 255
						#actual comparing
						if ~(genHashed[x] ^ hashedID[x]) & mask == mask:
							match = True
						else:
							match = False
							break

			#send request
			find_neighbour = NeighbourMsg(generatedID)
			message = self.wrap_packet(find_neighbour)
			logging.debug("sending find_node")
			sock.sendto(message, (self.their_endpoint.address.exploded, self.their_endpoint.udpPort))

		def request_neighbour_msb(bucket):
			#generate nodeID to discover specified bucket
			hashedID = keccak256(self.their_endpoint.nodeID)
			match = False
			mask = 1 << 7
			while match is False:
				generatedID = bytes(random.randint(0,255) for _ in range(64))
				genHashed = keccak256(generatedID)
				if bucket == 0:
					if (genHashed[31] ^ hashedID[31]) & mask == mask:
						match = True
					else:
						match = False
				else:
					#get the bytes in which the relevant bits are and iterate over them
					for x in range(int(bucket/8)+1):
						#make mask according to position in byte array (if last relevant byte get specific bit mask)
						if x == int(bucket/8):
							mask = pow(2, bucket%8)-1
							mask = mask << (8-bucket%8)
						else:
							mask = 255
						#actual comparing
						if ~(genHashed[31-x] ^ hashedID[31-x]) & mask == mask:
							match = True
						else:
							match = False
							break

			#send request
			find_neighbour = NeighbourMsg(generatedID)
			message = self.wrap_packet(find_neighbour)
			logging.debug("sending find_node")
			sock.sendto(message, (self.their_endpoint.address.exploded, self.their_endpoint.udpPort))


		def decode_worker(q, data, workerOut):
			nodes = rlp.decode(data[98:])[0] #[0] nodes [1] expiration
			for node in nodes:
				ip = ip_address(node[0])
				if len(node[1]) == 2:	
					udp_port = struct.unpack(">H", node[1])
				if len(node[2]) == 2:
					tcp_port = struct.unpack(">H", node[2])
				else:
					tcp_port = (0, ">I")
				nodeID = node[3]
				neighbour = Endpoint(str(ip), udp_port[0], tcp_port[0], nodeID)
				logging.debug("Neighbour: " + neighbour.serialize())
				if neighbour not in list(qset.queue):
					q.put(neighbour)
					qset.put(neighbour)
					
				workerOut.put(neighbour)

		while running.is_set():
			#start ping pong
			self.their_endpoint = q.get()
			ping = PingMsg(self.endpoint, self.their_endpoint)
			message = self.wrap_packet(ping)
			logging.info("sending ping to " + self.their_endpoint.address.exploded)
			sock.sendto(message, (self.their_endpoint.address.exploded, self.their_endpoint.udpPort))
			serializeOut = self.their_endpoint.serialize()
			greeted = False
			while not greeted:
				try:
					data, addr = sock.recvfrom(1280)
					if data[97] == 1:
						logging.info("received ping from " + addr[0])	
						pinger = Endpoint(addr[0], addr[1], addr[1], b'')
						pong = PongMsg(pinger, data[:32])
						message = self.wrap_packet(pong)
						logging.info("sending pong to " + str(pinger.address))
						sock.sendto(message, (pinger.address.exploded, pinger.udpPort))	
						greeted = True
					if data[97] == 2:
						logging.info("received pong from " + addr[0])
				except socket.timeout:
					serializeOut += ", no greeting"
					break
			#discover top 14 buckets of a neigbour (finding targets for all buckets would be hard/impossible)
			if greeted:
				for bucket in range(14):
					#discover a bucket
					request_neighbour_msb(bucket)
					counter = 0
					workerOut = queue.Queue()
					workers = []
					while counter < 2:
						try:
							data, addr = sock.recvfrom(1280)
							if data[97] == 4:
								#get up to 16 neighbours and add them to the q (12 neighbours per packet)
								workers.append(Thread(target = decode_worker, args = (q, data, workerOut)))
								workers[counter].start()
								logging.debug("received neighbours from " + addr[0])
								counter += 1
						#timeout because we received all neighbours available (less than 16) or didnt receive ping 
						except socket.timeout:
							break
					for worker in workers:
						worker.join()
					serializeOut += ", \"["
					for item in list(workerOut.queue):
						serializeOut += "[" + item.serialize() + "], "
					if serializeOut[-2] == ',':
						serializeOut = serializeOut[:-2]
					serializeOut += "]\""
			logging.debug(serializeOut)
			out.put(serializeOut)
Beispiel #10
0
class PingServer(object):
    """Open sockets, sign and hash messages, send messages to other servers."""

    def __init__(self, my_endpoint):
        """
        Set up ping server.

        - Take an endpoint object (i.e: itself in the network space)
            - Used as a "from address" when sending packets
        - Load private key for server
        """
        self.endpoint = my_endpoint

        # Load and serialize private key
        private_key_file = open('private_key', 'r')
        private_key_serialized = private_key_file.read()
        private_key_file.close()

        # Ethereum uses secp256k1, an elliptic curve, for assymetric encryption
        self.private_key = PrivateKey()
        self.private_key.deserialize(private_key_serialized)

    def wrap_packet(self, packet):
        """
        Encode the packet.

        hash || signature || packet-type || packet-data
        """
        # Append the packet type to the RLP encoding of the packet data
        payload = packet.packet_type + rlp.encode(packet.pack())
        # Sign the hashed payload, use raw=True, cause we've already hashed,
        # and otherwise, the function would use its own hash function
        signature = self.private_key.ecdsa_sign_recoverable(
            keccak256(payload),
            raw=True,
        )
        # Creates a tuple
        signature_serialized = self.private_key.ecdsa_recoverable_serialize(signature)
        payload = signature_serialized[0] + chr(signature_serialized[1] + payload)

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def udp_listen(self):
        """Listen for incoming transmissions"""
        # Create socket and bind it to the server's endpoint
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('0.0.0.0', self.endpoint.udp_port))

        def receive_ping():
            """Listen at the socket for incoming data"""
            print 'listening...'
            data, addr = sock.recvfrom(1024)
            print 'received message[{}]'.format(addr)

        return threading.Thread(target=receive_ping)

    def ping(self, endpoint):
        sock = socket.socket(socket.AF_INET), socket.SOCK_DGRAM
        ping = PingNode(self.endpoint, endpoint)
        message = self.wrap_packet(ping)
        print "sending ping."
        sock.sendto(
            message,
            (endpoint.address.exploded, endpoint.udp_port)
        )
Beispiel #11
0
class Server(object):
    def __init__(self, boot_nodes):
        # the endpoint of this server
        # this is a fake ip address used in packets.
        self.endpoint = EndPoint(u'127.0.0.1', 30303, 30303)
        # boot nodes
        self.boot_nodes = boot_nodes
        # hold all of pending
        self.pending_hold = []
        # last pong received time of the special node id
        self.last_pong_received = {}
        # last ping received time of the special node id
        self.last_ping_received = {}

        # have the private key
        priv_key_file = open('priv_key', 'r')
        priv_key_serialized = priv_key_file.read()
        priv_key_file.close()
        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        # routing table
        self.table = RoutingTable(
            Node(self.endpoint,
                 pubkey_format(self.priv_key.pubkey)[1:]), self)

        # initialize UDP socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))
        # set socket non-blocking mode
        self.sock.setblocking(0)

    def add_table(self, node):
        self.table.add_node(node)

    def add_pending(self, pending):
        pending.start()
        self.pending_hold.append(pending)
        return pending

    def run(self):
        gevent.spawn(self.clean_pending)
        gevent.spawn(self.listen)
        # wait forever
        evt = Event()
        evt.wait()

    def clean_pending(self):
        while True:
            for pending in list(self.pending_hold):
                if not pending.is_alive:
                    self.pending_hold.remove(pending)
            time.sleep(K_REQUEST_TIMEOUT)

    def listen(self):
        LOGGER.info("{:5} listening...".format(''))
        while True:
            ready = select([self.sock], [], [], 1.0)
            if ready[0]:
                data, addr = self.sock.recvfrom(2048)
                # non-block data reading
                gevent.spawn(self.receive, data, addr)

    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)

    def receive_pong(self, addr, pubkey, pong):
        remote_id = keccak256(pubkey)
        # response to ping
        last_pong_received = self.last_pong_received

        def match_callback():
            # solicited reply
            last_pong_received[remote_id] = time.time()

        self.handle_reply(addr, pubkey, Pong.packet_type, pong, match_callback)

    def receive_ping(self, addr, pubkey, ping, msg_hash):
        remote_id = keccak256(pubkey)
        endpoint_to = EndPoint(addr[0], ping.endpoint_from.udpPort,
                               ping.endpoint_from.tcpPort)
        pong = Pong(endpoint_to, msg_hash, time.time() + K_EXPIRATION)
        node_to = Node(pong.to, pubkey)
        # sending Pong response
        self.send_sock(pong, node_to)
        LOGGER.info("{:5} {}@{}:{} (Pong)".format(
            '---->',
            binascii.hexlify(node_to.node_id)[:8], addr[0],
            ping.endpoint_from.udpPort))

        self.handle_reply(addr, pubkey, PingNode.packet_type, ping)

        node = Node(endpoint_to, pubkey)
        if time.time() - self.last_pong_received.get(remote_id,
                                                     0) > K_BOND_EXPIRATION:
            self.ping(node, lambda: self.add_table(node))
        else:
            self.add_table(node)

        self.last_ping_received[remote_id] = time.time()

    def receive_find_neighbors(self, addr, pubkey, fn):
        remote_id = keccak256(pubkey)
        if time.time() - self.last_pong_received.get(remote_id,
                                                     0) > K_BOND_EXPIRATION:
            # lost origin or origin is off
            return

        target_id = keccak256(fn.target)
        closest = self.table.closest(target_id, BUCKET_SIZE)

        # sent neighbours in chunks
        ns = Neighbors([], time.time() + K_EXPIRATION)
        sent = False
        node_to = Node(EndPoint(addr[0], addr[1], addr[1]), pubkey)
        for c in closest:
            ns.nodes.append(c)

            if len(ns.nodes) == K_MAX_NEIGHBORS:
                self.send_sock(ns, node_to)
                LOGGER.info("{:5} {}@{}:{} {}".format(
                    '---->',
                    binascii.hexlify(node_to.node_id)[:8], addr[0], addr[1],
                    ns))
                ns.nodes = []
                sent = True

        if len(ns.nodes) > 0 or not sent:
            self.send_sock(ns, node_to)
            LOGGER.info("{:5} {}@{}:{} {}".format(
                '---->',
                binascii.hexlify(node_to.node_id)[:8], addr[0], addr[1], ns))

    def receive_neighbors(self, addr, pubkey, neighbours):
        # response to find neighbours
        self.handle_reply(addr, pubkey, Neighbors.packet_type, neighbours)

    def handle_reply(self,
                     addr,
                     pubkey,
                     packet_type,
                     packet,
                     match_callback=None):
        remote_id = keccak256(pubkey)
        is_match = False
        for pending in self.pending_hold:
            if pending.is_alive and packet_type == pending.packet_type:
                if remote_id == pending.from_id:
                    is_match = True
                    pending.emit(packet)
                    match_callback and match_callback()
                elif pending.ep is not None and pending.ep == addr:
                    LOGGER.error('{:5} {}@{}:{} mismatch request {}'.format(
                        '',
                        binascii.hexlify(remote_id)[:8], addr[0], addr[1],
                        binascii.hexlify(pending.from_id)[:8]))
                    # is_match = True
                    # pending.emit(packet)
                    # match_callback and match_callback()
                    # for bucket in self.table.buckets:
                    #     for node in bucket.nodes:
                    #         if node.node_id == pending.from_id:
                    #             node.set_pubkey(pubkey)

        if not is_match:
            LOGGER.warning('{:5} {}@{}:{} ({}) unsolicited response'.format(
                '<-//-',
                binascii.hexlify(remote_id)[:8], addr[0], addr[1],
                PACKET_TYPES.get(packet.packet_type)))

    def ping(self, node, callback=None):
        """
        send a ping request to the given node and return instantly
        invoke callback while reply arrives
        """
        ping = PingNode(self.endpoint, node.endpoint,
                        time.time() + K_EXPIRATION)
        message = self.wrap_packet(ping)
        msg_hash = message[:32]

        def reply_call(chunks):
            if chunks.pop().echo == msg_hash:
                if callback is not None:
                    callback()

                return True

        ep = (node.endpoint.address.exploded, node.endpoint.udpPort)
        pending = self.add_pending(Pending(node, Pong.packet_type, reply_call))
        self.sock.sendto(message, ep)
        LOGGER.info("{:5} {}@{}:{} (Ping)".format(
            '---->',
            binascii.hexlify(node.node_id)[:8], ep[0], ep[1]))

        return pending

    def find_neighbors(self, node, target_key):
        """
        send a find neighbours request to the given node and 
        waits until the node has sent up to k neighbours
        """
        node_id = node.node_id
        if time.time() - self.last_ping_received.get(node_id,
                                                     0) > K_BOND_EXPIRATION:
            send_ping = self.ping(node)
            receive_ping = self.add_pending(
                Pending(node, PingNode.packet_type, lambda _: True))
            # wait until endpoint proof is finished
            gevent.joinall([send_ping, receive_ping])

        fn = FindNeighbors(target_key, time.time() + K_EXPIRATION)

        def reply_call(chunks):
            num_received = 0
            for neighbors in chunks:
                num_received += len(neighbors.nodes)

            if num_received >= BUCKET_SIZE:
                return True

        pending = self.add_pending(
            Pending(node, Neighbors.packet_type, reply_call, timeout=2))
        self.send_sock(fn, node)
        ep = (node.endpoint.address.exploded, node.endpoint.udpPort)
        LOGGER.info("{:5} {}@{}:{} (FN {})".format(
            '---->',
            binascii.hexlify(node.node_id)[:8], ep[0], ep[1],
            binascii.hexlify(keccak256(fn.target))[:8]))
        # block to wait for neighbours
        ret = pending.get()
        if ret:
            neighbor_nodes = []
            for chunk in ret:
                for n in chunk.nodes:
                    neighbor_nodes.append(n)

            return neighbor_nodes

    def send_sock(self, packet, node):
        endpoint = node.endpoint
        message = self.wrap_packet(packet)
        ep = (endpoint.address.exploded, endpoint.udpPort)
        self.sock.sendto(message, ep)

    def wrap_packet(self, packet):
        """
        UDP packets are structured as follows:

        hash || signature || packet-type || packet-data
        packet-type: single byte < 2**7 // valid values are [1,4]
        packet-data: RLP encoded list. Packet properties are serialized in the order in
                    which they're defined. See packet-data below.

        Offset  |
        0       | MDC       | Ensures integrity of packet,
        65      | signature | Ensures authenticity of sender, `SIGN(sender-privkey, MDC)`
        97      | type      | Single byte in range [1, 4] that determines the structure of Data
        98      | data      | RLP encoded, see section Packet Data

        The packets are signed and authenticated. The sender's Node ID is determined by
        recovering the public key from the signature.

            sender-pubkey = ECRECOVER(Signature)

        The integrity of the packet can then be verified by computing the
        expected MDC of the packet as:

            MDC = SHA3(sender-pubkey || type || data)

        As an optimization, implementations may look up the public key by
        the UDP sending address and compute MDC before recovering the sender ID.
        If the MDC values do not match, the packet can be dropped.
                """
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        payload = sig_serialized[0] + chr(sig_serialized[1]) + payload

        payload_hash = keccak256(payload)
        return payload_hash + payload
Beispiel #12
0
class Server(object):
    def __init__(self, my_endpoint):
        self.endpoint = my_endpoint

        # 获取私钥
        priv_key_file = open('priv_key', 'r')
        priv_key_serialized = priv_key_file.read()
        priv_key_file.close()
        self.priv_key = PrivateKey()
        self.priv_key.deserialize(priv_key_serialized)

        # 初始化套接字
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(('0.0.0.0', self.endpoint.udpPort))
        # set socket non-blocking mode
        self.sock.setblocking(0)

    def wrap_packet(self, packet):
        """
        UDP packets are structured as follows:

        hash || signature || packet-type || packet-data
        packet-type: single byte < 2**7 // valid values are [1,4]
        packet-data: RLP encoded list. Packet properties are serialized in the order in
                    which they're defined. See packet-data below.

        Offset  |
        0       | MDC       | Ensures integrity of packet,
        65      | signature | Ensures authenticity of sender, `SIGN(sender-privkey, MDC)`
        97      | type      | Single byte in range [1, 4] that determines the structure of Data
        98      | data      | RLP encoded, see section Packet Data

        The packets are signed and authenticated. The sender's Node ID is determined by
        recovering the public key from the signature.

            sender-pubkey = ECRECOVER(Signature)

        The integrity of the packet can then be verified by computing the
        expected MDC of the packet as:

            MDC = SHA3(sender-pubkey || type || data)

        As an optimization, implementations may look up the public key by
        the UDP sending address and compute MDC before recovering the sender ID.
        If the MDC values do not match, the packet can be dropped.
                """
        payload = packet.packet_type + rlp.encode(packet.pack())
        sig = self.priv_key.ecdsa_sign_recoverable(keccak256(payload),
                                                   raw=True)
        sig_serialized = self.priv_key.ecdsa_recoverable_serialize(sig)
        payload = sig_serialized[0] + chr(sig_serialized[1]) + payload

        payload_hash = keccak256(payload)
        return payload_hash + payload

    def listen(self):
        print "listening..."
        while True:
            ready = select.select([self.sock], [], [], 1.0)
            if ready[0]:
                data, addr = self.sock.recvfrom(2048)
                print "received message[", addr, "]:"
                self.receive(data, addr)

    def listen_thread(self):
        thread = threading.Thread(target=self.listen)
        thread.daemon = True
        return thread

    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 receive_pong(self, payload, msg_hash, addr):
        print " received Pong"
        print "", Pong.unpack(rlp.decode(payload))

    def receive_ping(self, payload, msg_hash, addr):
        print " received Ping"
        ping = PingNode.unpack(rlp.decode(payload))
        endpoint_to = EndPoint(addr[0], ping.endpoint_from.udpPort, ping.endpoint_from.tcpPort)
        pong = Pong(endpoint_to, msg_hash, time.time() + 60)
        print "  sending Pong response: " + str(pong)
        self.send(pong, pong.to)

    def receive_find_neighbors(self, payload, msg_hash, addr):
        print " received FindNeighbors"
        print "", FindNeighbors.unpack(rlp.decode(payload))

    def receive_neighbors(self, payload, msg_hash, addr):
        print " received Neighbors"
        print "", Neighbors.unpack(rlp.decode(payload))

    def ping(self, endpoint):
        ping = PingNode(self.endpoint, endpoint, time.time() + 60)
        message = self.wrap_packet(ping)
        print "sending " + str(ping)
        self.sock.sendto(message, (endpoint.address.exploded, endpoint.udpPort))

    def send(self, packet, endpoint):
        message = self.wrap_packet(packet)
        print "sending " + str(packet)
        self.sock.sendto(message, (endpoint.address.exploded, endpoint.udpPort))