Welcome, guest | Sign In | My Account | Store | Cart

This is a method I developed recently for generating all but guaranteed unique session IDs for a non-web application I am working on. It takes a string and returns a string.

Python, 35 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/python


"""

Name:        newSID.py
Author:      Bill Anderson <bill@noreboots.com>
License:     LGPL


This is a nice little means of generating a 
"Session ID" for things like web sessions and the like.

It returns an ID of the format:
  Joe_db2039967237b1b1be33222268408c1a

where "Joe" was the string passed to the function.
"""

import time,whrandom,md5



def getNewSID(tag):
	"""Build a new Session ID"""
	t1 = time.time()
	time.sleep( whrandom.random() )
	t2 = time.time()
	base = md5.new( tag + str(t1 +t2) )
	sid = tag + '_' + base.hexdigest()
	return sid


if __name__ == '__main__':
	print getNewSID('Joe')

I needed a way to, as realistically as possible, generate gauranteed unique IDs. I opted for adding some entropy to the solution, by taking an timestamp, sleeping for a random interval between 0 and 1 seconds. I then added (numerically) the two together, and concatenated the result to the argument passed into the function.

I then create an md5 has, and concatenate the hexdigest of it to the input string.

There was no reason for me to determine anything from the key,other than as a unique identifier. MD5 and the hexdigest provides a clean method for generating a somewhat random sequence of alpha-numeric characters. The use of a timestamp, a random sleep interval and a second timestamp makes it rather difficult to 'guess',and very difficult to simultaneously generate duplicates.

2 comments

Rich Dougherty 20 years, 6 months ago  # | flag

Save those seconds! Looks pretty good - I see how you're using the inherent inaccuracy of the system clock to add a bit of randomness to your calculation. My only concern is the time.sleep() call. Unless we really have to, we don't want the user waiting while the computer sleeps. I know we're only talking a few milliseconds, but they all add up! You don't want to spend them unnecessarily. How about this revised version?

def getNewSID2(tag):
        """Build a new Session ID"""
        t1 = time.time()
        t2 = t1 + whrandom.random()
        base = md5.new( tag + str(t1 +t2) )
        sid = tag + '_' + base.hexdigest()
        return sid

Now, I'm not going to say that this is just as random. In fact, I have to confess I have no idea what my change does to the distribution of values that you'll get out. But it seems pretty good to me. I reckon a combination of the system time, a pseudorandom number and a bit of hashing is enough to foil someone trying to guess those ids!

Personally, when I'm generating numbers which need to be hard to guess and unique I go for a very simple solution.

unique_and_hard_to_guess_number = str(unique_number) + '_' + str(hard_to_guess_number)

I'll usually get unique numbers by starting a counter at 1 and increasing it each time. My "hard to guess" numbers are usually just the result of a call to random(), but a technique like you use here might be a better approach.

Foo Bar 20 years, 6 months ago  # | flag

unique_and_hard_to_guess_number isn't hard to guess. The unique_and_hard_to_guess_number in the previous comment is not very hard to guess if you have knowledge of other values in the sequence.

For truely hard to guess random numbers, use the algorithm on page 425-426 in "Applied Cryptography".