After certain privacy concerns Facebook rolled out a bunch of changes to their APIs, one being "scoping" user identifiers per app. In effect, this means that Alice's canonical facebook user ID is never shared through facebook APIs, but each app sees a unique never-changing value.
To formalize this through two functions:
mask(user_id, app_id) unmask(masked_id, app_id)
These functions should satisfy some properties:
reversible: user_id == unmask(mask(user_id, app_id), app_id)
secret: given y = mask(user_id, app_id) it should be 'hard' to obtain the original user_id.
deterministic: mask(user_id, app_id) == mask(user_id, app_id), where user_id == user_id and app_id == app_id
collision resistant: for all user ids, given the same app_id, it should not be the case that mask(user_id1, app_id) == mask(user_id2, app_id)
After a lot of reading, I have come up with two possible implementations:
Stateful: store a triple (user_id, app_id, hash(user_id, app_id)).
Stateless: for each app_id generate & store a secret, and encrypt(user_id, secret) on the fly. the encryption should be a deterministic cypher, such as AES-SIV.
Both of these approaches have fairly significant downsides. The stateful approach infers an incredible persistence cost -
Is there some other approach I might be missing here? I think this is a deceptively easy problem, looking forward to get some insight.