コード例 #1
0
ファイル: validation.py プロジェクト: tempusnetwork/tempus
def validate_sig_hash(item):
    # The reason this is a combined check on sig+hash (instead of split methods)
    # Is that check must be atomic, as sig+hash mutate the tick in certain order

    # Deepcopy used to not modify instance we received
    item_copy = copy.deepcopy(item)
    signature = item_copy.pop('signature', None)

    if signature is None:
        logger.debug("Could not find signature in validate sighash..")
        return False

    # Check hash
    if not validate_difficulty(hasher(item_copy)):
        logger.debug("Invalid hash for item: " + str(item_copy) + " " +
                     hasher(item_copy))
        return False

    # Validate signature
    try:
        encoded_message = standard_encode(item_copy)
        if not verify(encoded_message, signature, item_copy['pubkey']):
            return False
    except ecdsa.BadSignatureError:
        # TODO : When new joiner joins, make sure peers relay latest hash
        logger.debug("Bad signature!" + str(item_copy) + " " + str(signature))
        return False

    return True
コード例 #2
0
ファイル: networker.py プロジェクト: tempusnetwork/tempus
    def send_mutual_add_requests(self, peerslist):
        successful_adds = 0
        # Mutual add peers
        for peer in peerslist:
            if peer not in self.peers and len(
                    self.peers) <= config['max_peers']:
                content = {"port": self.port, 'pubkey': credentials.pubkey}
                signature = sign(standard_encode(content), credentials.privkey)
                content['signature'] = signature
                status_code = None
                response = None
                result, success = attempt(requests.post,
                                          False,
                                          url=peer + '/mutual_add',
                                          json=content,
                                          timeout=config['timeout'])
                if success:
                    status_code = result.status_code
                    response = result.text
                else:
                    logger.debug("Couldn't connect to " + peer)

                if status_code in [201, 503]:
                    if status_code == 201:
                        logger.info("Adding peer " + str(peer))
                        peer_addr = response
                        self.register_peer(peer, peer_addr)
                        successful_adds += 1
                    if status_code == 503:
                        logger.info("Peer was at peer-maximum")

        return successful_adds
コード例 #3
0
ファイル: timeminer.py プロジェクト: tempusnetwork/tempus
    def generate_and_process_tick(self):
        height = self.clockchain.current_height() + 1

        tick = {
            'list': list(self.clockchain.ping_pool.values()),
            'pubkey': credentials.pubkey,
            'prev_tick': self.clockchain.prev_tick_ref(),
            'height': height
        }

        this_tick, nonce = mine(tick)

        tick['nonce'] = nonce

        signature = sign(standard_encode(tick), credentials.privkey)
        tick['signature'] = signature

        # This is to keep track of the "name" of the tick as debug info
        # this_tick is not actually necessary according to tick schema
        tick['this_tick'] = this_tick

        prev_tick = self.clockchain.latest_selected_tick()

        possible_previous = self.clockchain.possible_previous_ticks()

        # Validate own tick
        retries = 0
        while retries < config['tick_retries']:
            if not validate_tick(
                    tick, prev_tick, possible_previous, verbose=False):
                retries = retries + 1
                time.sleep(config['tick_retries_sleep'])
            else:
                self.clockchain.add_to_tick_pool(tick)
                # Forward to peers (this must be after all validation)
                self.networker.forward(data_dict=tick,
                                       route='tick',
                                       origin=credentials.addr,
                                       redistribute=0)
                logger.debug("Forwarded own tick: " + str(tick))
                return True

        logger.debug(
            "Failed own tick validation too many times. not forwarded")
        return False
コード例 #4
0
ファイル: timeminer.py プロジェクト: tempusnetwork/tempus
    def generate_and_process_ping(self, reference, vote=False):
        # TODO: Code duplication between here and api.. where to put??
        # TODO: Can't be in helpers, and cant be in clockchain/networker..
        # Always construct ping in the following order:
        # 1) Init 2) Mine+nonce 3) Add signature
        # This is because the order of nonce and sig creation matters

        ping = {
            'pubkey': credentials.pubkey,
            'timestamp': utcnow(),
            'reference': reference
        }

        stage = 'vote' if vote else 'ping'

        _, nonce = mine(ping)
        ping['nonce'] = nonce

        signature = sign(standard_encode(ping), credentials.privkey)
        ping['signature'] = signature

        # Validate own ping
        if not validate_ping(ping, self.clockchain.ping_pool, vote):
            logger.debug("Failed own " + stage + " validation")
            return False

        if vote:
            self.clockchain.add_to_vote_pool(ping)
        else:
            self.clockchain.add_to_ping_pool(ping)

        route = 'vote' if vote else 'ping'

        # Forward to peers (this must be after all validation)
        self.networker.forward(data_dict=ping,
                               route=route,
                               origin=credentials.addr,
                               redistribute=0)

        logger.debug("Forwarded own " + route + ": " + str(ping))

        return True
コード例 #5
0
ファイル: flask_api.py プロジェクト: tempusnetwork/tempus
        def mutual_add():
            values = request.get_json()

            if self.check_duplicate(values):
                return "duplicate request please wait 10s", 400

            # Verify json schema
            if not validate_schema(values, 'mutual_add_schema.json'):
                return "Invalid request", 400

            # Verify that pubkey and signature match
            signature = values.pop("signature")
            if not verify(standard_encode(values), signature,
                          values['pubkey']):
                return "Invalid signature", 400

            # Return a 503: service unavailable here
            # so that they can try adding my friends instead
            if len(self.networker.peers) > config['max_peers']:
                return "dont need more peers", 503

            # TODO: What if rogue peer send fake port? Possible ddos reflection?
            # TODO: Do schema validation for integer sizes / string lengths..
            remote_port = int(values.get('port'))

            remote_url = resolve(request.remote_addr)
            remote_url = "http://" + remote_url + ":" + str(remote_port)

            remote_cleaned_url = self.networker.get_full_location(remote_url)
            own_cleaned_url = self.networker.get_full_location(
                request.url_root)

            # Avoid inf loop by not adding self..
            if remote_cleaned_url != own_cleaned_url:
                result, success = attempt(requests.get,
                                          False,
                                          url=remote_url + '/info/addr',
                                          timeout=config['timeout'])
                if success:
                    addr = result.text
                else:
                    return "couldn't get addr", 400
                # Verify that the host's address matches the key pair used
                # to sign the mutual_add request
                if not pubkey_to_addr(values['pubkey']) == addr:
                    return "Received request signed with key != host", 400

                if not self.networker.register_peer(remote_url, addr):
                    return "Could not register peer", 400
                else:  # Make sure the new joiner gets my pings (if I have any)
                    if credentials.addr in self.clockchain.ping_pool:
                        ping = self.clockchain.ping_pool[credentials.addr]
                        # Forward but do not redistribute
                        _, success = attempt(
                            requests.post,
                            False,
                            url=remote_url + '/forward/ping?addr=' +
                            credentials.addr + "&redistribute=-1",
                            json=ping,
                            timeout=config['timeout'])

                        if not success:
                            return "couldnt forward my ping", 400
            else:
                return "cannot add self", 400

            return credentials.addr, 201
コード例 #6
0
ファイル: rogue.py プロジェクト: tempusnetwork/tempus
from utils.pki import get_kp, sign
from main import config
from utils.helpers import standard_encode
import requests

# Make a mutual_add request pretending to be another host

target = config['seeds'][0]
spoof = config['seeds'][1]
spoof_port = spoof.split(':')[2]

pub, priv = get_kp()

content = {"port": int(spoof_port), 'pubkey': pub}
signature = sign(standard_encode(content), priv)
content['signature'] = signature

response = requests.post(target + '/mutual_add', json=content, timeout=1000)
print(response.text)