## UEID (Unique Enough IDs, part 2)

As part of an open-source project I’m working on (right now, we are still at the technical feasibility stage where we explore and eliminate technical risks, full disclosure will come later) we have to issue session numbers. They’re not session numbers in the usual sense, but they still need to be unique, and not amenable to simple attacks.

There are a couple of ways of generating unique session numbers. RFC 4122-compliant unique IDs is one possible way.

Python does provide a UUID module (import uuid), and while its implementation is compliant to RFC 4122, it still need a little help. For example, if you’re thinking of using uuid.uuid1() to generate UUIDs, you notice that

```import uuid, os

for _ in xrange(20):
print uuid.uuid1()
time.sleep(1)
```

produces the not very uniquely looking:

```6850c980-655a-11e1-ad4c-f46d049a0bd8
```

Only a relatively small part of the key changes between calls. As I’ve said before, using slow- or little-varying keys is just begging to get hacked. Not sure how realistic it is to have a time-based attack on sessions numbers, but the fact is that they’re not random enough. They may be locally UUIDs, but they’re not random enough to rule out the possibility of finding a session number.

Fortunately, we can feed the UUID class a random stream of garbage strong random bits and it will kindly convert it into a RFC-4122-looking UUID. The following code:

```session_id = uuid.UUID(bytes=os.urandom(16))
```

gets the random bits from the /dev/urandom device, which is not quite cryptographic grade, but much stronger than the infamous C library rand. The random stream is RFC-4122 formatted and yields:

```2ba28331-6623-9da0-5dca-c9d45e446381
fb35c53b-dbcb-7b60-f825-33f85ee037b1
1ef51981-7279-29de-b6b4-b12baf664997
2f7a9978-000b-6c37-2179-049deea3f087
1e350dcd-89d6-2378-06da-e4db3c509fe8
b2408a16-2923-dd2a-9eaa-9fb01efde1ce
24f3afec-dc51-4fd7-89e5-5db11f650d52
897b2644-12e9-3da4-52cc-992fff4f8eef
52c00394-01e2-88bc-0c29-33f77ea2791a
3c684d11-d558-e5d5-ecb2-9aaf145bf8b4
0135b666-dc88-16bf-278d-605d70cd0203
4d0f6f7e-e67b-3e1c-8ea9-495ff60d1621
a49de6e8-aa25-9dde-8c32-e8d8e5b8bc3e
e5d681a9-da44-d7ae-72c9-7deaa3b96f27
079cc2f1-b6b1-1a1d-2bdf-2096f677c983
e56f648b-7038-b287-5285-2c689e3a07b3
cf9be65a-41b1-d99b-e0ef-5a79eda8c3e7
```

for immediately consecutive calls.

*
* *

So basically, we’re probably better off using simply strong random numbers converted into (long) identifiers. The (current) Python documentation state that for uuid1, If clock_seq is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. 14 strongly random bits may be somewhat of a protection (it can yield $2^{14}=16384$ different combination) and the simple experiment above indicate that some extra time-based random elements are used (there are more than 14 bits varying between calls, maybe 20, maybe up to 28), but it still doesn’t look nearly random enough to rule out exploits.

*
* *

Strong sessions numbers are one thing, but one may as well use extra protection such as correlating IP addresses and browser id with the session numbers. In our ultimate application, there is no need for cryptographic signature and the usual secure web-based transaction framework, only that we are (very) confident that the data associated with a session number comes from the session owner, and that we can discard (or at least segregate) suspicious/malevolent data we receive.

### 2 Responses to UEID (Unique Enough IDs, part 2)

1. jfdube says:

Nice piece. You might want to take a look at this blog post: http://jfdube.wordpress.com/2011/09/21/guid-generation/ on the same subject!

2. Noach says:

Steven, I’m certainly no expert on UUIDs, but it seems to me you’ve totally missed the point of them. From the RFC:
“6. Security Considerations
Do not assume that UUIDs are hard to guess; they should not be used
as security capabilities (identifiers whose mere possession grants
access), for example.”