I'm sending out a lot of messages, containing links, to my mailing list and I need each link to be unique so that I know who is using it. And I need the link to be as short as possible, as it will be sent via a text message.
The link could be something like this: domain.com?id=1234567
I'm just wondering what would be the best approach to do this as if I send out something like the link above, I'm sure someone would try out domain.com?id=1234568 to see what happens. I don't want people to use someone else's link as I am asking people to provide personal information which would be added to my current database, so I need to know who is using it.
I thought of using two parameters: e.g. domain.com?id=1234567&key=123 or some simple string replacement so that 1234567 would be converted to abcdefg (or something a bit more complicated).
I have a lot of info in my database that would be unique to each individual, but most of it could be guessed on its own. E.g. a unique id, time of creation, phone number, etc.
I thought of a lot of ways to do this but I'm not sure what is good enough but still short.
Do you have any proposals?
P.S. I know this is not really a PHP question, but I tag it as such just in case you think code is needed for your answer (and I don't know what else I should be tagging it as). The landing page will be created with PHP.
The best way is to make a time sensitive hash table that is joined with whatever data you are emailing.
Basically when you send out an email you add a record to this table that ties a hash you send in the email to whatever linked data you are giving them.
Making it time sensitive or single use will make if far more secure, but it's not always possible to do this. If the links are good only for one use, and only for a limited time it makes it harder to attack because there is only a limited attack surface equal to the number of hashes you have stored. The more hashes you keep the easier it is to randomly find one.
No matter what you should have a system in place where 1 user cannot see another users stuff, you can't really rely on obscuring things like IDs (even with hashes). If your just taking in data that give you a bit more leeway but never show any PCI or personally identifying data to an unknown user just because they have the correct link. No matter what you do to obscure it someone will find a way to iterate though it if they want to.
Anyway, for hashing you can use this to see what algo's PHP has and their lenghts
foreach(hash_algos() as $algo){
$h = hash($algo, 'hello world');
echo "$algo (".strlen($h).") $h
";
}
Then for what you hash I would do something like this:
hash($algo, {ID}.microtime().rand(0,999999))
Where ID is something specific to the user or the data, it's good to put something unique (an ID), something progressive(time), and something completely random.
Then you add this to the Link, store it in the DB where you can associate it to whatever you need to etc.
It's also not a bad idea to use 2 smaller hashes or to just add some random junk on the end of the hash, hashes always return the same length so if you add say a random length string to the end of the hash it makes it harder to tell how it was hashed, but again you can't rely on obscuring things alone. For example I've used crc32b
+ fnv164
in the past one is 8
the other is 16
which comes out at 24.
What I mean is if I see something 32 long I know it's md5 (md2 or 4 are hardly ever used), if it's 40 sha1, 56 sha224, 64 sha256 etc. And those I know right off the top.
Cheers.