3

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?

Joey
  • 455
  • 4
  • 9

5 Answers5

14

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
  • 15,584
  • 8
  • 52
  • 59
  • 4
    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 Nov 01 '09 at 07:47
  • @wedge thanks for the good idea, once again lack of sleep keeps things like this from clicking in my head. – Joey Nov 01 '09 at 18:34
  • @Wedge: Yeah, the hashing is just a start, really. Great idea. – Jed Smith Nov 01 '09 at 21:15
  • Thanks -> reimplemented a similar thing in c# using GUID, SHA256 and a bit mask to create the numbers I need. – kͩeͣmͮpͥ ͩ Dec 09 '09 at 09:22
0

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
  • 5,916
  • 25
  • 45
0

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.

prasanna
  • 1,887
  • 3
  • 20
  • 26
0
SELECT HEX(encode(id,'pass_str')) FROM table;
SELECT * FROM table WHERE id=decode(UNHEX('1F68C22821F2AC'), 'pass_str');
andreas
  • 299
  • 3
  • 9
0

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
  • 311
  • 2
  • 4