def _trigger_action_by_nonowner(device_id, device_name, name, token): data = { "device_name_bi": blind_index(get_device_bi_key(device_id), device_name), "name_bi": blind_index(get_device_bi_key(device_id), name), "additional_data": b2a_hex(os.urandom(32)).decode() } return requests.get(URL_TRIGGER_ACTION, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS)
def add_scene_action(scene_name, action_name, device_id, token): if not is_global_bi_key_missing( create_device, "Blind index key for scene name is missing"): data = { "scene_name_bi": blind_index(get_global_bi_key(), scene_name), "action_name_bi": blind_index(get_device_bi_key(device_id), action_name), } r = requests.post(URL_ADD_ACTION_TO_SCENE, headers={"Authorization": token}, data=data, verify=VERIFY_CERTS) click.echo(r.content.decode('unicode-escape'))
def create_device(device_type_id, device_name, password, token): password_hash = pbkdf2_hash(password) bi_key = os.urandom(32) device_name_key = key_to_hex( os.urandom(32)) # NOTE: retrieve key as `key_to_hex(key)` device_status_key = key_to_hex(os.urandom(32)) data = { "type_id": device_type_id, "name": hex_to_fernet(device_name_key).encrypt(device_name.encode()), "correctness_hash": correctness_hash(device_name), "name_bi": blind_index(bi_key, device_name), "password": password_hash } r = requests.post(URL_CREATE_DEVICE, headers={"Authorization": token}, data=data, verify=VERIFY_CERTS) content = json.loads(r.content.decode('unicode-escape')) if content["success"]: insert_into_tinydb( path, 'device_keys', { 'device_id': str(content["id"]), 'bi_key': key_to_hex(bi_key), 'device:name': device_name_key, 'device:status': device_status_key }) click.echo(r.content.decode('unicode-escape'))
def _trigger_action_by_owner(device_id, device_name, name, token, real): data = { "device_name_bi": blind_index(get_device_bi_key(device_id), device_name), "name_bi": blind_index(get_device_bi_key(device_id), name), } if real: data["additional_data"] = "real" else: data["additional_data"] = "fake" data["additional_data"] = encrypt_using_fernet_hex( get_shared_key_by_device_id(path, device_id), data["additional_data"]).decode() return requests.get(URL_TRIGGER_ACTION, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS)
def revoke_user(device_id, device_name, revoke_user_id, token): data = { "device_name_bi": blind_index(get_device_bi_key(device_id), device_name), "revoke_user_id": revoke_user_id } r = requests.post(URL_REVOKE_USER, headers={"Authorization": token}, data=data, verify=VERIFY_CERTS) click.echo(r.content.decode('unicode-escape'))
def get_device_data(user_id, device_id, device_name, owner, token): """ Queries server for data of :param device_id device and then verifies the received data using integrity information from device (received using MQTT Broker) and correctness hash attribute of each DB row. """ user_id = int(user_id) device_name_bi = blind_index(get_device_bi_key(device_id), device_name) data = {"device_name_bi": device_name_bi} r = requests.get(URL_GET_DEVICE_DATA, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS) content = r.content.decode('unicode-escape') json_content = json_string_with_bytes_to_dict(content) if not json_content["success"]: click.echo(json_content["error"]) return if owner: _get_fake_tuple_data(user_id, int(device_id)) decrypted_fake_tuple_data = { "device_data": json.loads( decrypt_using_fernet_hex( get_shared_key_by_device_id(path, device_id), fake_tuple_data["device_data"]).decode()) } fake_tuples, rows = _divide_fake_and_real_data( json_content["device_data"], device_id, decrypted_fake_tuple_data) # NOTE: ^ Not checking for ability of user to decrypt (having SK that satisfies Ciphertext) because owner should have keys setup # so that he can decrypt all data from his devices verify_integrity_data( generate_fake_tuples_in_range( decrypted_fake_tuple_data["device_data"]), fake_tuples) check_correctness_hash(rows, 'added', 'data', 'num_data', 'tid') result = [] for row in rows: try: result.append(unpad_row("data", row)) except Exception as e: click.echo(str(e)) click.echo(result) else: get_foreign_device_data(device_id, json_content)
def trigger_scene(name, token, real): data = {"name_bi": blind_index(get_global_bi_key(), name)} if real: data["additional_data"] = "real" else: data["additional_data"] = "fake" data["additional_data"] = encrypt_using_fernet_hex( key_to_hex(get_global_scene_key()), data["additional_data"]).decode() r = requests.get(URL_TRIGGER_SCENE, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS) click.echo(r.content.decode('unicode-escape'))
def create_row(data, num_data, tid, added): user_data = get_user_data() encrypted = encrypt_row( { "added": added, "num_data": num_data, "data": pad_payload_attr(str(data)), "tid": str(tid) }, get_key_type_pair(user_data)) encrypted["correctness_hash"] = correctness_hash( added, pad_payload_attr(str(data)), num_data, tid) encrypted["tid_bi"] = blind_index(hex_to_key(get_bi_key()), str(tid)) return encrypted
def get_devices(device_name, device_id, token): """Triggered using: ./cli.py -b "172.26.0.8" user get-devices test_device 46 --token 5c36ab84439c55a3c196f4csd9bd7b3d9291f39g""" device_name_bi = blind_index(get_device_bi_key(device_id), device_name) data = {"name_bi": device_name_bi} r = requests.get(URL_GET_DEVICE, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS) content = json.loads(r.content.decode('unicode-escape')) table = get_tinydb_table(path, 'device_keys') for device in content["devices"]: ciphertext = device["name"] doc = table.get(Query().device_id == str(device["id"])) plaintext = decrypt_using_fernet_hex(doc["device:name"], ciphertext) device["name"] = plaintext.decode() check_correctness_hash(content["devices"], "name") click.echo(content["devices"])
def get_fake_tuple(bound): try: table = get_tinydb_table(path, 'users') doc = get_user_data() if bound == "lower_bound" and not can_remove_fake_row( doc["integrity"]["device_data"]): return # "Can't remove row that was not yet inserted (lower bound equals upper bound)" fake_tuple = {**generate(doc["integrity"]["device_data"], bound=bound)} fake_tuple["data"] = pad_payload_attr(str(fake_tuple["data"]), fake=True) keys = get_key_type_pair(doc) fake_tuple_hash = correctness_hash([ fake_tuple["added"], fake_tuple["data"], fake_tuple["num_data"], fake_tuple["tid"] ]) encrypted_fake_tuple = encrypt_row(fake_tuple, keys) row = { **encrypted_fake_tuple, "correctness_hash": fake_tuple_hash, "tid_bi": blind_index(hex_to_key(get_bi_key()), str(fake_tuple["tid"])) } if bound == "upper_bound": doc["integrity"]["device_data"] = increment_bounds( doc["integrity"]["device_data"]) if bound == "lower_bound": doc["integrity"]["device_data"] = increment_bounds( doc["integrity"]["device_data"], bound=bound) payload = dict_to_payload(**row) table.update(doc) click.echo(payload) except Exception as e: # pragma: no exc cover _, _, exc_tb = sys.exc_info() line = exc_tb.tb_lineno click.echo(f"{repr(e)} at line: {line}")
def create_scene(name, description, token): if not is_global_bi_key_missing( init_global_keys, "Blind index key for scene name is missing"): if len(get_tinydb_table(path, 'scene_keys')) == 0: init_scene_keys() table = get_tinydb_table(path, 'scene_keys') doc = table.all()[0] name_ciphertext = encrypt_using_fernet_hex(doc["name"], name) desc_ciphertext = encrypt_using_fernet_hex(doc["description"], description) data = { "name": name_ciphertext, "correctness_hash": correctness_hash(name), "name_bi": blind_index(get_global_bi_key(), name), "description": desc_ciphertext } r = requests.post(URL_CREATE_SCENE, headers={"Authorization": token}, data=data, verify=VERIFY_CERTS) click.echo(r.content.decode('unicode-escape'))
def set_action(device_id, name, token): doc = search_tinydb_doc(path, 'device_keys', Query().device_id == str(device_id)) if not doc: with click.Context(send_column_keys) as ctx: click.echo( f"Keys for device {device_id} not present, please use: {ctx.command.name}" ) click.echo(send_column_keys.get_help(ctx)) return data = { "device_id": device_id, "name": encrypt_using_fernet_hex(doc["action:name"], name), "correctness_hash": correctness_hash(name), "name_bi": blind_index(get_device_bi_key(device_id), name) } r = requests.post(URL_SET_ACTION, headers={"Authorization": token}, data=data, verify=VERIFY_CERTS) click.echo(r.content.decode('unicode-escape'))
def create_data(): dal = setup() session = dal.Session() Base.metadata.drop_all(dal.engine) Base.metadata.create_all(dal.engine) rows = [] rows_num = 10000 global searched_row global searched_name for i in range(1, rows_num): name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)) if i == searched_row: searched_name = name rows.append(BlindIndex( id=i, name=name, name_bi=blind_index(key, name) )) session.add_all(rows) session.commit()
def get_device_data_by_num_range(user_id, device_id, device_name, lower=None, upper=None, token=""): if lower is not None and upper is not None and upper <= lower: click.echo("Upper bound needs to be greater then lower bound.") return device_name_bi = blind_index(get_device_bi_key(device_id), device_name) if lower is not None and upper is not None: data = { "lower": int(lower), "upper": int(upper), "device_name_bi": device_name_bi } elif lower is not None and upper is None: upper = 214748364700 # 100000000000 data = {"lower": int(lower), "device_name_bi": device_name_bi} elif lower is None and upper is not None: lower = -214748364800 # -100000000000 data = {"upper": int(upper), "device_name_bi": device_name_bi} else: lower = -214748364800 # -100000000000 upper = 214748364700 # 100000000000 data = { "lower": lower, "upper": upper, "device_name_bi": device_name_bi } r = requests.get(URL_GET_DEVICE_DATA_BY_RANGE, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS) content = r.content.decode('unicode-escape') json_content = json_string_with_bytes_to_dict(content) _get_fake_tuple_data(int(user_id), int(device_id)) decrypted_fake_tuple_data = { "device_data": json.loads( decrypt_using_fernet_hex( get_shared_key_by_device_id(path, device_id), fake_tuple_data["device_data"]).decode()) } fake_tuples, rows = _divide_fake_and_real_data(json_content["device_data"], str(device_id), decrypted_fake_tuple_data) generated_tuples = generate_fake_tuples_in_range( decrypted_fake_tuple_data["device_data"]) expected_fake_rows = slice_by_range(generated_tuples, int(lower), int(upper), "device_data:num_data") verify_integrity_data(expected_fake_rows, fake_tuples) if json_content["success"]: check_correctness_hash(rows, 'added', 'data', 'num_data', 'tid') result = [] for row in rows: try: result.append(unpad_row("data", row)) except Exception as e: click.echo(str(e)) click.echo('{"device_data":' + str(result).replace("'", '"') + '}')
def query_orm(session, name): return session.query(BlindIndex).filter(BlindIndex.name_bi == blind_index(key, name)).scalar()
session = dal.Session() rows = [] rows_num = 1000 searched_row = 500 searched_name = "" key = b'\xb8z\x1dU)\xb7YY~\xd3>\x00\x85^\x11|\x12K\x95e\xd4\xca\xc9\xf2,\xe0g\xe4\xc44\xd3W' for i in range(1, rows_num): name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)) if i == searched_row: searched_name = name rows.append(BlindIndex( id=i, name=name, name_bi=blind_index(key, name) )) session.add_all(rows) session.commit() start = timer() result = session.query(BlindIndex).filter(BlindIndex.name_bi == blind_index(key, searched_name)).scalar() end = timer() print(f'We searched for row with name: {searched_name}') print(f'We found row: {result}') print(f'Search over {rows_num} rows took {end - start}\n') uri = urlparse(dal.conn_string)