Ejemplo n.º 1
0
    def handle_packet(self, data, address):
        if len(data) < 1:
            return

        opcode, data = data[0], data[1:]

        # time
        if opcode == TIME_SYNC:
            if len(data) != 32:
                print("TIME_SYNC packet received with incorrect size")
                return

            nonce = data
            timestamp = struct.pack("!Q", int(time.time() * 1000))

            message = timestamp
            message += ed25519.sign(nonce + timestamp, self.public_key,
                                    self.private_key)

            self.socket.sendto(TIME_SYNC + message, address)

        elif opcode == CERT_REQUEST_INIT:
            if len(data) != 96:
                print("CERT_REQUEST_INIT packet received with incorrect size")
                return

            nonce, username, proposed_pubkey = data[:32], data[32:64], data[
                64:96]
            username = struct.unpack("32p", username)[0]

            message = ed25519.sign(nonce + username + proposed_pubkey,
                                   self.public_key, self.private_key)

            self.socket.sendto(CERT_REQUEST_INIT + message, address)
            self.certificate_requests[nonce] = (time.time() + 10, username,
                                                proposed_pubkey)

        elif opcode == CERT_REQUEST_CONFIRM:
            if len(data) != (32 + 20 + 64):
                print(
                    "CERT_REQUEST_CONFIRM packet received with incorrect size")
                return

            nonce, auth, signature = data[:32], data[32:52], data[52:]

            if nonce not in self.certificate_requests:
                print("received CERT_REQUEST_CONFIRM with unknown nonce")
                return

            # we don't need to check the timeout - that's done elsewhere
            timeout, username, proposed_pubkey = self.certificate_requests[
                nonce]

            # only allow one response
            del self.certificate_requests[nonce]

            # invalid authentication
            if username not in self.accounts or hashlib.sha1(
                    nonce + self.accounts[username][1]).digest() != auth:
                message = nonce
                message += ed25519.sign(nonce, self.public_key,
                                        self.private_key)

                self.socket.sendto(CERT_REQUEST_INVALID_AUTH + message,
                                   address)

                return

            if not ed25519.verify(signature, nonce + auth, proposed_pubkey):
                print("received CERT_REQUEST_CONFIRM with invalid signature")
                return

            scalar = ed25519.create_seed()
            pubkey = ed25519.add_scalar(scalar, proposed_pubkey)
            userid = struct.pack(">L", self.accounts[username][0])
            expiry = struct.pack(">H",
                                 round((time.time() / (60 * 60 * 24 * 7)) +
                                       1))  # one week

            message = scalar
            message += userid
            message += expiry
            message += ed25519.sign(pubkey + userid + expiry, self.public_key,
                                    self.private_key)

            self.socket.sendto(CERT_REQUEST_CONFIRM + message, address)
Ejemplo n.º 2
0
Archivo: node.py Proyecto: orlp/secudht
    def handle_packet(self, data, address):
        if len(data) < 1:
                return

        opcode, data = data[0], data[1:]

        # time sync
        if opcode == TIME_SYNC:
            if len(data) != (8 + 64):
                print("TIME_SYNC packet received with incorrect size")
                return

            timestamp, signature = data[:8], data[8:]
            
            # make sure the time is actually from the CA AND contains the correct nonce
            # this implicitly rejects too old responses, because the nonce would have changed already
            if not ed25519.verify(signature, self.last_network_time_request_nonce + timestamp, self.ca_public_key):
                return

            now = time.time()
            latency_correction = (now - self.last_network_time_request_time) / 2

            self.network_time_offset = struct.unpack("!Q", timestamp)[0] / 1000. - latency_correction - now 

        # certificate request reply from the CA 
        elif opcode == CERT_REQUEST_INIT:
            if len(data) != 64:
                print("CERT_REQUEST_INIT packet received with incorrect size")
                return

            check_message = self.last_certificate_request_nonce + self.username + self.last_certificate_request_public_key
            signature = data

            if not ed25519.verify(signature, check_message, self.ca_public_key):
                print("Got wrong CERT_REQUEST_INIT signature")
                return

            message = self.last_certificate_request_nonce
            message += hashlib.sha1(self.last_certificate_request_nonce + self.password_key).digest() 
            message += ed25519.sign(message, self.last_certificate_request_public_key, self.last_certificate_request_private_key)

            self.socket.sendto(CERT_REQUEST_CONFIRM + message, address)

        elif opcode == CERT_REQUEST_CONFIRM:
            if len(data) != (32 + 4 + 2 + 64):
                print("Got wrong CERT_REQUEST_CONFIRM signature")
                return

            scalar, user_id, expiry, certificate = data[:32], data[32:36], data[36:38], data[38:]

            
            public_key, private_key = ed25519.add_scalar(scalar, self.last_certificate_request_public_key, self.last_certificate_request_private_key)

            if ed25519.verify(certificate, public_key + user_id + expiry, self.ca_public_key):
                self.public_key = public_key
                self.private_key = private_key
                self.certificate = certificate
                self.user_id = struct.unpack(">L", user_id)[0]
                expiry = struct.unpack("@H", expiry)[0]

                print("\nIdentification successful")
                print("-------------------------")
                print("User ID: {}".format(self.user_id))
                print("Public key: " + binascii.hexlify(self.public_key))
                print("Certificate: " + binascii.hexlify(self.certificate))


        elif opcode == CERT_REQUEST_INVALID_AUTH:
            nonce, signature = data[:32], data[32:]
            
            # correct signature?
            if not ed25519.verify(signature, nonce, self.ca_public_key):
                return

            # our nonce?
            if nonce != self.last_certificate_request_nonce:
                return

            print("Invalid username or password.")
            sys.exit(0)
Ejemplo n.º 3
0
    def handle_packet(self, data, address):
        if len(data) < 1:
            return

        opcode, data = data[0], data[1:]

        # time
        if opcode == TIME_SYNC:
            if len(data) != 32:
                print("TIME_SYNC packet received with incorrect size")
                return

            nonce = data
            timestamp = struct.pack("!Q", int(time.time() * 1000))

            message = timestamp
            message += ed25519.sign(nonce + timestamp, self.public_key, self.private_key)

            self.socket.sendto(TIME_SYNC + message, address)

        elif opcode == CERT_REQUEST_INIT:
            if len(data) != 96:
                print("CERT_REQUEST_INIT packet received with incorrect size")
                return
            
            nonce, username, proposed_pubkey = data[:32], data[32:64], data[64:96]
            username = struct.unpack("32p", username)[0]
            
            message = ed25519.sign(nonce + username + proposed_pubkey, self.public_key, self.private_key)

            self.socket.sendto(CERT_REQUEST_INIT + message, address)
            self.certificate_requests[nonce] = (time.time() + 10, username, proposed_pubkey)

        elif opcode == CERT_REQUEST_CONFIRM:
            if len(data) != (32 + 20 + 64):
                print("CERT_REQUEST_CONFIRM packet received with incorrect size")
                return

            nonce, auth, signature = data[:32], data[32:52], data[52:]

            if nonce not in self.certificate_requests:
                print("received CERT_REQUEST_CONFIRM with unknown nonce")
                return

            # we don't need to check the timeout - that's done elsewhere
            timeout, username, proposed_pubkey = self.certificate_requests[nonce]

            # only allow one response
            del self.certificate_requests[nonce]

            # invalid authentication
            if username not in self.accounts or hashlib.sha1(nonce + self.accounts[username][1]).digest() != auth:
                message = nonce
                message += ed25519.sign(nonce, self.public_key, self.private_key)

                self.socket.sendto(CERT_REQUEST_INVALID_AUTH + message, address)

                return

            if not ed25519.verify(signature, nonce + auth, proposed_pubkey):
                print("received CERT_REQUEST_CONFIRM with invalid signature")
                return

            scalar = ed25519.create_seed()
            pubkey = ed25519.add_scalar(scalar, proposed_pubkey)
            userid = struct.pack(">L", self.accounts[username][0])
            expiry = struct.pack(">H", round((time.time() / (60 * 60 * 24 * 7)) + 1)) # one week

            message = scalar
            message += userid
            message += expiry
            message += ed25519.sign(pubkey + userid + expiry, self.public_key, self.private_key)

            self.socket.sendto(CERT_REQUEST_CONFIRM + message, address)
Ejemplo n.º 4
0
    def handle_packet(self, data, address):
        if len(data) < 1:
            return

        opcode, data = data[0], data[1:]

        # time sync
        if opcode == TIME_SYNC:
            if len(data) != (8 + 64):
                print("TIME_SYNC packet received with incorrect size")
                return

            timestamp, signature = data[:8], data[8:]

            # make sure the time is actually from the CA AND contains the correct nonce
            # this implicitly rejects too old responses, because the nonce would have changed already
            if not ed25519.verify(
                    signature, self.last_network_time_request_nonce +
                    timestamp, self.ca_public_key):
                return

            now = time.time()
            latency_correction = (now -
                                  self.last_network_time_request_time) / 2

            self.network_time_offset = struct.unpack(
                "!Q", timestamp)[0] / 1000. - latency_correction - now

        # certificate request reply from the CA
        elif opcode == CERT_REQUEST_INIT:
            if len(data) != 64:
                print("CERT_REQUEST_INIT packet received with incorrect size")
                return

            check_message = self.last_certificate_request_nonce + self.username + self.last_certificate_request_public_key
            signature = data

            if not ed25519.verify(signature, check_message,
                                  self.ca_public_key):
                print("Got wrong CERT_REQUEST_INIT signature")
                return

            message = self.last_certificate_request_nonce
            message += hashlib.sha1(self.last_certificate_request_nonce +
                                    self.password_key).digest()
            message += ed25519.sign(message,
                                    self.last_certificate_request_public_key,
                                    self.last_certificate_request_private_key)

            self.socket.sendto(CERT_REQUEST_CONFIRM + message, address)

        elif opcode == CERT_REQUEST_CONFIRM:
            if len(data) != (32 + 4 + 2 + 64):
                print("Got wrong CERT_REQUEST_CONFIRM signature")
                return

            scalar, user_id, expiry, certificate = data[:32], data[
                32:36], data[36:38], data[38:]

            public_key, private_key = ed25519.add_scalar(
                scalar, self.last_certificate_request_public_key,
                self.last_certificate_request_private_key)

            if ed25519.verify(certificate, public_key + user_id + expiry,
                              self.ca_public_key):
                self.public_key = public_key
                self.private_key = private_key
                self.certificate = certificate
                self.user_id = struct.unpack(">L", user_id)[0]
                expiry = struct.unpack("@H", expiry)[0]

                print("\nIdentification successful")
                print("-------------------------")
                print("User ID: {}".format(self.user_id))
                print("Public key: " + binascii.hexlify(self.public_key))
                print("Certificate: " + binascii.hexlify(self.certificate))

        elif opcode == CERT_REQUEST_INVALID_AUTH:
            nonce, signature = data[:32], data[32:]

            # correct signature?
            if not ed25519.verify(signature, nonce, self.ca_public_key):
                return

            # our nonce?
            if nonce != self.last_certificate_request_nonce:
                return

            print("Invalid username or password.")
            sys.exit(0)