Skip to content
Advertisement

Is there a way to create a reversible opaque UUID?

Request

We need a php-only system to map a filepath/filename.ext to a UUID in a way that can be reversible.

Example

For example:

maps/shop1.jpg ->  342abfec-31fdfg-23131

The user can access this map only from

loader.php?token=342abfec-31fdfg-23131

The loader.php must be able to ‘reverse’ the UUID so the script can send maps/show1.jpg.

The goal

Main goal in this phase is not to secure content access.

Our goal for now is only to add an “opacity” level to avoid that an user can open for example shop2.jpg simply changing the URL.

The problem

We cannot, for now, save UUID<–>file mapping into a DB or similar.

So I’ve the request to create ‘on the fly’ the UUID corresponding to a filepath/filename.txt, and this UUID must be reversible so a PHP script can ‘decode’ it and serve the corresponding file.

Question

Does a reversible string to UUID algorithm already exist?

Advertisement

Answer

It sounds like you want it to be hard to guess URLs or spot patterns in them. The suggestion of base64 encoding in another answer is a good one, but similar inputs will still lead to similar outputs, so it may not be ideal:

maps/shop1.jpg: bWFwcy9zaG9wMS5qcGc
maps/shop2.jpg: bWFwcy9zaG9wMi5qcGc
maps/shop3.jpg: bWFwcy9zaG9wMy5qcGc
maps/shop4.jpg: bWFwcy9zaG9wNC5qcGc
maps/shop5.jpg: bWFwcy9zaG9wNS5qcGc

To avoid this, you can XOR the string with a random salt (or “nonce”), and include the salt in the URL to decode it, e.g.:

function base64_url_encode($input)
{
    return strtr(base64_encode($input), '+/=', '._-');
}

function base64_url_decode($input)
{
    return base64_decode(strtr($input, '._-', '+/='));
}

function obfuscate($input)
{
    $salt = random_bytes(strlen($input));
    // Make sure our separator doesn't appear in the salt, or explode() will split at the wrong place
    str_replace('|', '-', $salt);
    $xor = $input ^ $salt;
    return base64_url_encode("$salt|$xor");
}

function deobfuscate($input)
{
    [$salt, $xor] = explode('|', base64_url_decode($input), 2);
    return $salt ^ $xor;
}

Which gives strings like this:

maps/shop1.jpg: NubGQVCitxcciGC8wht8W4e2Mn_R33hsuU7Wsnw-
maps/shop2.jpg: ePr0T12ft29NwpNMslN8FZuEPHLs3wA98L0mwjQ-
maps/shop3.jpg: 7stRD6lwniLozbmY_fJ8g6ohfIYD9k2Y_pfyjZU-
maps/shop4.jpg: 1ArPov5EmGqyikHyN2l8uWu_0dE38AXCvm.YRw4-
maps/shop5.jpg: tQN2RHTzN.LCEHu1URJ82GIGN1uAX42yJVXfIXU-

(A variation of this would be to use the MD5 or SHA1 hash of the string as the salt, so that each string will always have the same obfuscated form, but still be hard to guess.)

You could even XOR a second fixed string that’s not transmitted (a “key”), making this into a very simple encryption scheme. But if you want security, you’re better off just using a real encryption function like sodium_crypto_secretbox.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement