views:

258

answers:

5

I am building a small rails app and I need a way to generate tracking numbers to give to customers to check up on their status. I want something similar to what the major shipping companies use, but not as long. Im thinking 12-16 characters long is fine, but I dont want something like 0000000001 where people can just type in incremented numbers and peep around.

What is a good way to generate unique number/letter combination tracking codes?

A: 

Isn't the id generated for every table enough? It is unique by "default". But most of the time it's simply not shown,

Of course one could wrap it in a timestamp or the like.

Friedrich
+12  A: 

For meaningless data, hashes of the time plus a salt are always rock solid, and can't be guessed easily (forgive the Python, I've heard of this Ruby thing but never held it in my hands):

>>> hashlib.md5(str(time.time()) + "!salt!").hexdigest()
'7a8b73fa7e0dadf246612e6001ede165'

Shorten it, if you like:

>>> hashlib.md5(str(time.time()) + "!salt!").hexdigest()[:16]
'46ffb69ebc96412d'

Use an integer instead, if you like, but the length has the chance to vary with this code, unless you zero-pad:

>>> int(hashlib.md5(str(time.time()) + "!salt!").hexdigest()[:13], 16)
1346212029197308

In before "zomg md5 isn't crypto secure":

>>> int(hashlib.sha256(str(time.time()) + "!salt!").hexdigest()[:13], 16)
1948411134966366

Hell, you don't even have to use time, you can use an autoincrementing integer, as long as you salt it:

>>> int(hashlib.sha256(str(1) + "!salt!").hexdigest()[:13], 16)
1269883740611281
>>> int(hashlib.sha256(str(2) + "!salt!").hexdigest()[:13], 16)
3655373802716929

Hashes. Is there anything they can't do?

Jed Smith
thank you, this is what i was wanting to do.
Joey
@Joey: You're very welcome. Cheers.
Jed Smith
If you want to have some degree of date information embedded in the tracking number you could prefix your random hash with the first several digits of unix-time in decimal form. The first 6 digits will uniquely identify time down to about a 3 hour period. This would have the added effect of making your tracking codes semi-sequential (which would provide useful properties in sorting records, for example).
Wedge
@wedge thanks for the good idea, once again lack of sleep keeps things like this from clicking in my head.
Joey
@Wedge: Yeah, the hashing is just a start, really. Great idea.
Jed Smith
Thanks -> reimplemented a similar thing in c# using GUID, SHA256 and a bit mask to create the numbers I need.
David Kemp
A: 

Why not use a hashmap to store the order information and provide the users with a decimal/hex representation of the ID? It's unique enough.

pvsnp
A: 
SELECT HEX(encode(id,'pass_str')) FROM table;
SELECT * FROM table WHERE id=decode(UNHEX('1F68C22821F2AC'), 'pass_str');
andreas
A: 

I wrote a plugin for this sort of scenario called acts_as_hashed (on github). You can specify which fields you'd like to use in the hashing algorithm and the plugin will provide a unique key based on those fields called crypto_hash. This tends to be cleaner than by doing it by hand, and can be used with any number of models within your app.

briandoll