Is Python uuid.uuid4 strong enough for password re

2020-04-16 17:55发布

问题:

This is the code I use to generate a password reset link for my app:

def create_unique_code():
    return str(uuid.uuid4())

Is that strong enough? I use a one or two day expiry time.

回答1:

Yes, a UUID4 is fully random and long enough to rule out brute forcing or lucky guesses. So as long as whatever RNG uuid.uuid4() provides sufficiently good randomness you should be fine.

However, consider using e.g. a cryptographically signed token (the itsdangerous lib can take care of it) - not only can you specify an expiry time right when generating it, you also won't necessarily have to store anything about the token on your server.



回答2:

In CPython, yes. In other Python implementations, probably, but you might want to double-check that a cryptographically strong source of randomness is used to generate the UUID.


There are two factors you might care about when judging whether some way of generating secure random tokens - such as UUIDs - is "strong enough":

  1. Are there enough possible values for it not to be brute-forced?
  2. Is the source of randomness used cryptographically secure?

Since there are 2122 version 4 UUIDs (that's a little over 5 trillion trillion trillion), the answer to point 1 is definitely "yes", in this case. The space of all possible UUIDs ain't going to be brute forceable any time soon.

Point 2 is not currently answered by the official Python docs on uuid.uuid4(), which make no mention of security or whether the randomness source used is strong. Indeed, the entire documentation of uuid4() is just:

Generate a random UUID.

which clearly provides no security guarantees.

Nor is it addressed by the UUID specification, which does not mandate a cryptographically strong source of randomness be used in UUID generation and indeed explicitly contemplates the possibility of a "predictable random number source" being used to generate UUIDs in the Security Considerations section.

However, we can look at the implementation at https://github.com/python/cpython/blob/master/Lib/uuid.py:

def uuid4():
    """Generate a random UUID."""
    return UUID(bytes=os.urandom(16), version=4)

Since this uses os.urandom as its randomness source, it's secure. See the docs at https://docs.python.org/3/library/os.html#os.urandom which note that os.urandom returns:

a string of size random bytes suitable for cryptographic use.