def keygen(): data_owner = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) attr_list = request.form.get("attr_list", None) api_username = request.form.get("api_username", None) device_id = request.form.get("device_id", None) arg_check = check_missing_request_argument( (attr_list, ATTR_LIST_MISSING_ERROR_MSG), (api_username, API_USERNAME_MISSING_ERROR_MSG), (device_id, DEVICE_ID_MISSING_ERROR_MSG)) if arg_check is not True: return arg_check receiver = AttrAuthUser.get_by_user_name(api_username) if receiver is None: return http_json_response(False, 400, **{"error": INCORRECT_API_USERNAME_ERROR_MSG}) attr_list = parse_attr_list(attr_list) if not attr_list: return http_json_response(False, 400, **{"error": INVALID_ATTR_LIST_ERROR_MSG}) serialized_private_key = create_private_key(data_owner.master_keypair.data_master, data_owner.master_keypair.data_public, attr_list) # delegate to receiver of generated key old_key = next((k for k in receiver.private_keys if k.challenger == data_owner and k.device_id == int(device_id)), None) if old_key: db.session.delete(old_key) receiver.private_keys.append(PrivateKey(data=serialized_private_key, challenger=data_owner, device_id=device_id, attributes=create_attributes(attr_list))) db.session.commit() return http_json_response()
def test_doesnt_have_key_from_owner(app_and_ctx, attr_auth_access_token_two): app, ctx = app_and_ctx with app.app_context(): receiver = AttrAuthUser.get_by_id(2) owner = AttrAuthUser() assert not already_has_key_from_owner(receiver, owner)
def test_already_has_key_from_owner(app_and_ctx, attr_auth_access_token_one, attr_auth_access_token_two): app, ctx = app_and_ctx with app.app_context(): owner = AttrAuthUser.get_by_id(1) receiver = AttrAuthUser.get_by_id(2) assert already_has_key_from_owner(receiver, owner)
def test_get_private_key_based_on_owner_missing(): decryptor = Mock() decryptor.private_keys = [ PrivateKey(challenger=AttrAuthUser(id=10)), PrivateKey(challenger=AttrAuthUser(id=34)), PrivateKey(challenger=AttrAuthUser(id=37)) ] owner = AttrAuthUser(id=235) with pytest.raises(Exception): get_private_key_based_on_owner(decryptor, owner)
def test_get_private_key_based_on_owner(): decryptor = Mock() expected = PrivateKey(challenger=AttrAuthUser(id=10)) decryptor.private_keys = [ PrivateKey(challenger=AttrAuthUser(id=11)), expected, PrivateKey(challenger=AttrAuthUser(id=25)) ] owner = expected.challenger key = get_private_key_based_on_owner(decryptor, owner) assert key == expected
def test_replace_existing_key(app_and_ctx, attr_auth_access_token_one, attr_auth_access_token_two): app, ctx = app_and_ctx attr_list = ["TODAY", "TOMORROW"] dummy_serialized_key = b'key' with app.app_context(): owner = AttrAuthUser.get_by_id(1) receiver = AttrAuthUser.get_by_id(2) replace_existing_key(receiver, dummy_serialized_key, owner, attr_list) modified_key = receiver.private_keys[0] assert modified_key.data == dummy_serialized_key assert modified_key.attributes[0].value == "TODAY"
def decrypt(): decryptor = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) owner_api_username = request.args.get("api_username", None) serialized_ciphertext = request.args.get("ciphertext", None) arg_check = check_missing_request_argument( (owner_api_username, OWNER_API_USERNAME_MISSING_ERROR_MSG), (serialized_ciphertext, CIPHERTEXT_MISSING_ERROR_MSG)) if arg_check is not True: return arg_check pairing_group = create_pairing_group() cp_abe = create_cp_abe() data_owner = db.session.query(AttrAuthUser) \ .filter(AttrAuthUser.api_username == owner_api_username) \ .first() if data_owner is None: return http_json_response(False, 400, **{"error": INVALID_OWNER_API_USERNAME_ERROR_MSG}) public_key = deserialize_charm_object(data_owner.master_keypair.data_public, pairing_group) private_key = deserialize_charm_object(get_private_key_based_on_owner(decryptor, data_owner).data, pairing_group) ciphertext = deserialize_charm_object(str.encode(serialized_ciphertext), pairing_group) try: plaintext = cp_abe.decrypt(public_key, private_key, ciphertext) except: return http_json_response(False, 400, **{"error": COULD_NOT_DECRYPT_ERROR_MSG}) # return plaintext return http_json_response(**{'plaintext': plaintext.decode("utf-8")})
def set_username(): user = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) api_username = request.form.get("api_username", None) arg_check = check_missing_request_argument((api_username, API_USERNAME_MISSING_ERROR_MSG)) if arg_check is not True: return arg_check if AttrAuthUser.get_by_user_name(api_username) is not None: return http_json_response(False, 400, **{"error": API_USERNAME_ALREADY_PRESENT_MSG}) user.api_username = api_username db.session.add(user) db.session.commit() return http_json_response()
def delete_account_aa(): user = AttrAuthUser.get_using_jwt_token( request.headers.get('Authorization', "")) db.session.delete(user) db.session.commit() return http_json_response()
def test_set_username(client, app_and_ctx, attr_auth_access_token_one): data = { "access_token": attr_auth_access_token_one, "api_username": "******" } assert_got_data_from_post(client, '/attr_auth/set_username', data) app, ctx = app_and_ctx with app.app_context(): user = AttrAuthUser.get_by_id(1) assert user.api_username == "Changed" data = { "access_token": attr_auth_access_token_one, "api_username": "******" } assert_got_data_from_post(client, '/attr_auth/set_username', data) user = AttrAuthUser.get_by_id(1) assert user.api_username == "MartinHeinz"
def test_keygen_already_has_key_from_owner(client, app_and_ctx, attr_auth_access_token_one, attr_auth_access_token_two): data = { "access_token": attr_auth_access_token_one, "attr_list": "1 1-2 1-GUEST", "api_username": "******", "device_id": "1" } app, ctx = app_and_ctx with app.app_context(): receiver = AttrAuthUser.get_by_id(2) # TestUser access_token old_private_key = next(key for key in receiver.private_keys if key.challenger_id == 1) old_private_key_data = old_private_key.data old_private_key_key_update = old_private_key.key_update private_keys_num = len(receiver.private_keys) assert_got_data_from_post(client, '/attr_auth/user/keygen', data) receiver = AttrAuthUser.get_by_id(2) # TestUser access_token new_private_key = next(key for key in sorted( receiver.private_keys, key=lambda p: p.key_update, reverse=True) if key.challenger_id == 1) assert old_private_key_data != new_private_key.data assert old_private_key_key_update < new_private_key.key_update assert len(receiver.private_keys) > private_keys_num # Try to encrypt and decrypt pairing_group = create_pairing_group() cp_abe = create_cp_abe() plaintext = "Hello World" data_owner = AttrAuthUser.get_by_id(1) policy_str = '(1-GUEST)' public_key = deserialize_charm_object( data_owner.master_keypair.data_public, pairing_group) new_private_key = deserialize_charm_object(new_private_key.data, pairing_group) ciphertext = cp_abe.encrypt(public_key, plaintext, policy_str) decrypted_msg = cp_abe.decrypt(public_key, new_private_key, ciphertext) assert plaintext == decrypted_msg.decode("utf-8")
def retrieve_private_keys(): user = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) private_keys = [{ "data": key.data.decode("utf-8"), "key_update": key.key_update, "attributes": [a.value for a in key.attributes], "challenger_id": key.challenger_id, "device_id": key.device_id, } for key in user.private_keys] return http_json_response(**{'private_keys': private_keys})
def test_keygen_replaces_old_key(client, app_and_ctx, attr_auth_access_token_one, attr_auth_access_token_two): data = { "access_token": attr_auth_access_token_one, "attr_list": "1 1-2 1-GUEST", "api_username": "******", "device_id": "99" } app, ctx = app_and_ctx with app.app_context(): assert_got_data_from_post(client, '/attr_auth/user/keygen', data) receiver = AttrAuthUser.get_by_id(2) old_private_key = next( key for key in receiver.private_keys if key.challenger_id == 1 and key.device_id == 99) old_private_key_data = old_private_key.data old_private_key_key_update = old_private_key.key_update old_private_keys_num = len(receiver.private_keys) assert_got_data_from_post( client, '/attr_auth/user/keygen', data) # This should replace old_private_key_data receiver = AttrAuthUser.get_by_id(2) new_private_key = next( key for key in receiver.private_keys if key.challenger_id == 1 and key.device_id == 99) new_private_key_data = new_private_key.data new_private_key_key_update = new_private_key.key_update assert old_private_key_data != new_private_key_data assert old_private_key_key_update < new_private_key_key_update assert old_private_keys_num == len(receiver.private_keys) db.session.delete(new_private_key) db.session.commit()
def test_key_setup(client, app_and_ctx, attr_auth_access_token_one): data = {"access_token": attr_auth_access_token_one} status_code, json_data = get_data_from_get(client, '/attr_auth/setup', data) assert status_code == 200 serialized_public_key_response = json_data["public_key"] app, ctx = app_and_ctx with app.app_context(): serialized_public_key_from_db = AttrAuthUser.get_by_id( 1).master_keypair.data_public.decode("utf-8") assert serialized_public_key_response == serialized_public_key_from_db
def test_keygen_doesnt_have_key_from_owner(client, app_and_ctx, attr_auth_access_token_one, attr_auth_access_token_two): data = { "access_token": attr_auth_access_token_two, "attr_list": "2 2-1 2-GUEST", "api_username": "******", "device_id": "1" } app, ctx = app_and_ctx with app.app_context(): receiver = AttrAuthUser.get_by_id(1) num_of_old_keys = len(receiver.private_keys) assert_got_data_from_post(client, '/attr_auth/user/keygen', data) receiver = AttrAuthUser.get_by_id(1) new_private_key = next(key for key in receiver.private_keys if key.challenger_id == 2) assert len(receiver.private_keys) == num_of_old_keys + 1 # Try to encrypt and decrypt pairing_group = create_pairing_group() cp_abe = create_cp_abe() plaintext = "Hello World" data_owner = AttrAuthUser.get_by_id(2) policy_str = '(2-GUEST)' public_key = deserialize_charm_object( data_owner.master_keypair.data_public, pairing_group) new_private_key = deserialize_charm_object(new_private_key.data, pairing_group) ciphertext = cp_abe.encrypt(public_key, plaintext, policy_str) decrypted_msg = cp_abe.decrypt(public_key, new_private_key, ciphertext) assert plaintext == decrypted_msg.decode("utf-8")
def validate_token(bind, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except SignatureExpired: return False # valid token, but expired except BadSignature: return False # invalid token if bind is None: user = User.get_by_id(data['id']) else: user = AttrAuthUser.get_by_id(data['id']) if user is not None: return bcrypt.verify(data["token"], user.access_token) return False
def test_delete_account(client, app_and_ctx): server_data = {} aa_data = {} server_provider_token = "server_token" aa_provider_token = "aa_token" device_id = 99999 token_hash = bcrypt.using(rounds=13).hash(server_provider_token) aa_token_hash = bcrypt.using(rounds=13).hash(aa_provider_token) user = User(access_token=token_hash, access_token_update=datetime.now(), owned_devices=[ Device(id=device_id, name=b"test", correctness_hash="") ]) aa_user = AttrAuthUser(access_token=aa_token_hash, access_token_update=datetime.now()) db.session.add(aa_user) db.session.add(user) db.session.commit() app, ctx = app_and_ctx with app.app_context(): server_data["access_token"] = generate_auth_token( user.id, server_provider_token) aa_data["access_token"] = generate_auth_token(user.id, aa_provider_token) assert db.session.query(User).filter( User.access_token == token_hash).first() is not None assert db.session.query(Device).filter( Device.id == device_id).first() is not None assert db.session.query(AttrAuthUser).filter( AttrAuthUser.access_token == aa_token_hash).first() is not None assert_got_data_from_post(client, '/delete_account', server_data) assert_got_data_from_post(client, '/attr_auth/delete_account', aa_data) assert db.session.query(User).filter( User.access_token == token_hash).first() is None assert db.session.query(Device).filter( Device.id == device_id).first() is None assert db.session.query(AttrAuthUser).filter( AttrAuthUser.access_token == aa_token_hash).first() is None
def key_setup(): pairing_group = create_pairing_group() cp_abe = create_cp_abe() public_key, master_key = cp_abe.setup() # "store keypair in DB" user = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) serialized_public_key = serialize_charm_object(public_key, pairing_group) serialized_master_key = serialize_charm_object(master_key, pairing_group) user.master_keypair = MasterKeypair(data_public=serialized_public_key, data_master=serialized_master_key) db.session.add(user) db.session.commit() # return pk, msk return http_json_response(**{'public_key': serialized_public_key.decode("utf-8")})
def encrypt(): data_owner = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) plaintext = request.args.get("message", None) policy_string = request.args.get("policy_string", None) arg_check = check_missing_request_argument( (plaintext, MESSAGE_MISSING_ERROR_MSG), (policy_string, POLICY_STRING_MISSING_ERROR_MSG)) if arg_check is not True: return arg_check pairing_group = create_pairing_group() cp_abe = create_cp_abe() public_key = deserialize_charm_object(data_owner.master_keypair.data_public, pairing_group) ciphertext = cp_abe.encrypt(public_key, plaintext, policy_string) # return ciphertext return http_json_response(**{'ciphertext': serialize_charm_object(ciphertext, pairing_group).decode("utf-8")})
def device_keygen(): data_owner = AttrAuthUser.get_using_jwt_token(request.headers.get("Authorization", None)) attr_list = request.form.get("attr_list", None) arg_check = check_missing_request_argument( (attr_list, ATTR_LIST_MISSING_ERROR_MSG)) if arg_check is not True: return arg_check attr_list = parse_attr_list(attr_list) if not attr_list: return http_json_response(False, 400, **{"error": INVALID_ATTR_LIST_ERROR_MSG}) serialized_private_key = create_private_key(data_owner.master_keypair.data_master, data_owner.master_keypair.data_public, attr_list) # delegate to receiver of generated key return http_json_response(private_key=serialized_private_key.decode("utf-8"))
def save_user(remote, user_info, token): user = get_user(remote, user_info) if user is None: if remote.name == "github": user = User(id=user_info["sub"], name=user_info["preferred_username"], email=parse_email( query_github_api(token["access_token"]))) else: user = AttrAuthUser(id=user_info["sub"], name=user_info["preferred_username"]) db.session.flush() user.access_token = bcrypt.using(rounds=13).hash(token["access_token"]) user.access_token_update = datetime.datetime.utcnow() db.session.add(user) db.session.commit() return generate_auth_token(user.id, token["access_token"])
# pickle.dump(users, open("users.p", "wb")) db.session.add_all(users) db.session.add_all(device_types) db.session.add_all(devices) db.session.commit() aa_users = [] for i, user in enumerate(users): access_token = random_string() token_hash = bcrypt.using(rounds=13).hash(access_token) # noinspection PyArgumentList aa_user = AttrAuthUser(name=user.name, id=user.id, access_token=token_hash, access_token_update=random_date(d1, d2), api_username=user.name) keypair = MasterKeypair(data_public=keypairs[i][0], data_master=keypairs[i][1], attr_auth_user=aa_user) keys["users"][user.id]["aa_access_token"] = generate_auth_token( user.id, access_token).decode() db.session.add(aa_user) db.session.add(keypair) db.session.flush() attr_list = [ f"U-{user.id}", f"U-{user.id}-D-{user.owned_devices[0].id}",