def copy_psk(token, src_device_id, src_attr, dest_device_id, dest_attr):
        """
        Copies a pre shared key from a device attribute to another

        :param token: The authorization token (JWT).
        :param src_device_id: The source device (from).
        :param src_attr: The source attribute (from).
        :param dest_device_id: The destination device (to).
        :param dest_attr: The destination attribute (to).
        :return None.
        :raises HTTPRequestError: If no authorization token was provided (no
        tenant was informed)
        todo list the others exceptions
        """

        tenant = init_tenant_context2(token, db)

        src_device_orm = assert_device_exists(src_device_id, db.session)
        if not src_device_orm:
            raise HTTPRequestError(404, "No such device: {}".format(src_device_id))

        src_device = serialize_full_device(src_device_orm, tenant, True)

        found_attr = False
        src_attr_ref = None
        for template_id in src_device["templates"]:
            for attr in src_device["attrs"][template_id]:
                if attr["label"] == src_attr:
                    if attr["value_type"] == "psk":
                        found_attr = True
                        src_attr_ref = attr
                        break
                    else:
                        raise HTTPRequestError(400,
                                "Attribute {} is not a 'psk' type_value".format(src_attr))

        if not found_attr:
            raise HTTPRequestError(404, "Not found attributes {}".format(src_attr))

        dest_device_orm = assert_device_exists(dest_device_id, db.session)
        if not dest_device_orm:
            raise HTTPRequestError(404, "No such device: {}".format(dest_device_id))

        dest_device = serialize_full_device(dest_device_orm, tenant, True)

        found_attr = False
        dest_attr_ref = None
        for template_id in dest_device["templates"]:
            for attr in dest_device["attrs"][template_id]:
                if attr["label"] == dest_attr:
                    if attr["value_type"] == "psk":
                        found_attr = True
                        dest_attr_ref = attr
                        break
                    else:
                        raise HTTPRequestError(400,
                                "Attribute {} is not a 'psk' type_value".format(dest_attr))

        if not found_attr:
            raise HTTPRequestError(404, "Not found attributes {}".format(dest_attr))

        # copy the pre shared key
        src_psk_entry = DeviceAttrsPsk.query.filter_by(device_id=src_device["id"],
                                                    attr_id=src_attr_ref["id"]).first()
        if not src_psk_entry:
            raise HTTPRequestError(400, "There is not a psk generated to {}".format(src_attr))

        dest_psk_entry = DeviceAttrsPsk.query.filter_by(device_id=dest_device["id"],
            attr_id=dest_attr_ref["id"]).first()
        if not dest_psk_entry:
            db.session.add(DeviceAttrsPsk(device_id=dest_device["id"],
                                            attr_id=dest_attr_ref["id"],
                                            psk=src_psk_entry.psk))
        else:
            dest_psk_entry.psk = src_psk_entry.psk

        dest_device_orm.updated = datetime.now()
        db.session.commit()

        dest_attr_ref['static_value'] = src_attr_ref['static_value']

        # send an update message on kafka
        kafka_handler = KafkaHandler()
        kafka_handler.update(dest_device, meta={"service": tenant})

        return None
    def gen_psk(token, device_id, key_length, target_attributes=None):
        """
        Generates pre shared keys to a specifics device

        :param token: The authorization token (JWT).
        :param device_id: The target device.
        :param key_length: The key length to be generated.
        :param target_attributes: A list with the target attributes, None means
        all suitable attributes.
        :return The keys generated.
        :rtype JSON
        :raises HTTPRequestError: If no authorization token was provided (no
        tenant was informed)
        :raises HTTPRequestError: If this device could not be found in
        database.
        """

        tenant = init_tenant_context2(token, db)

        device_orm = assert_device_exists(device_id, db.session)
        if not device_orm:
            raise HTTPRequestError(404, "No such device: {}".format(device_id))

        device = serialize_full_device(device_orm, tenant, True)

        # checks if the key length has been specified
        # todo remove this magic number
        if key_length > 1024 or key_length <= 0:
            raise HTTPRequestError(400, "key_length must be greater than 0 and lesser than {}".format(1024))

        is_all_psk_attr_valid = False
        target_attrs_data = []

        # find the target attributes
        # first case: if there are specified attributes
        if target_attributes:
            for template_id in device["templates"]:
                for attr in device["attrs"][template_id]:
                    if attr["value_type"] == "psk" and attr["label"] in target_attributes:
                        target_attrs_data.append(attr)
                        is_all_psk_attr_valid = True

            if not is_all_psk_attr_valid:
                raise HTTPRequestError(400, "Not found some attributes, "
                    "please check them")

            if len(target_attributes) != len(target_attrs_data):
                if not is_all_psk_attr_valid:
                    raise HTTPRequestError(400,
                                    "Some attribute is not a 'psk' type_value")
                else:
                    raise HTTPRequestError(400, "Not found some attributes, "
                        "please check them")
        else: # second case: if there are not specified attributes
            for template_id in device["templates"]:
                for attr in device["attrs"][template_id]:
                    if attr["value_type"] == "psk":
                        target_attrs_data.append(attr)
                        is_all_psk_attr_valid = True

            if not is_all_psk_attr_valid:
                # there is no psk key, do not worry it is not a problem
                raise HTTPRequestError(204, "")

        # generate the pre shared key on selected attributes
        result = []
        for attr in target_attrs_data:
            psk = secrets.token_hex(key_length)
            psk_hex = psk
            attr["static_value"] = psk_hex
            encrypted_psk = encrypt(psk)
            psk_entry = DeviceAttrsPsk.query.filter_by(device_id=device["id"],
                                                       attr_id=attr["id"]).first()
            if not psk_entry:
                db.session.add(DeviceAttrsPsk(device_id=device["id"],
                                              attr_id=attr["id"],
                                              psk=encrypted_psk))
            else:
                psk_entry.psk = encrypted_psk

            result.append( {'attribute': attr["label"], 'psk': psk_hex} )

        device_orm.updated = datetime.now()
        db.session.commit()

        # send an update message on kafka
        kafka_handler = KafkaHandler()
        kafka_handler.update(device, meta={"service": tenant})

        return result