3 ms·
RFC4122 doesn’t require the use of a CSPRNG. From Section 4.4: > Set all the other bits to randomly (or pseudo-randomly) chosen values. Section 4.5, which is
by sgarland 2y ago
RFC4122 doesn’t require the use of a CSPRNG. From Section 4.4:
> Set all the other bits to randomly (or pseudo-randomly) chosen values.
Section 4.5, which is actually scoped to UUIDv1, does hint at it being a good idea:
> Advice on generating cryptographic-quality random numbers can be found in RFC1750.
But absolutely nothing stops you from doing this:
import random
import string
def terrible_prng(k: int) -> int:
_int = int("".join(random.choices(string.digits, k=k)))
return _int << (128 - _int.bit_length())
def make_uuid_v4(_int: int) -> str:
_int &= ~(0xC000 << 48)
_int |= 0x8000 << 48
_int &= ~(0xF000 << 64)
_int |= 4 << 76
_uuid_hex = "%032x" % _int
return "%s-%s-%s-%s-%s" % (
_uuid_hex[:8],
_uuid_hex[8:12],
_uuid_hex[12:16],
_uuid_hex[16:20],
_uuid_hex[20:],
)
They'll all be RFC4122-compliant (depending on how you interpret "randomly chosen values", since with `k=10`, for example, only the first field will be unique), but terrible, e.g. '83f1a1ea-0000-4000-8000-000000000000'.
In fairness, RFC9562, which supersedes RFC4122, says this in Section 6.9:
> Implementations SHOULD utilize a cryptographically secure pseudorandom number generator (CSPRNG) to provide values that are both difficult to predict ("unguessable") and have a low likelihood of collision ("unique").
And the RFC2119 definition of SHOULD requires that you "[understand and carefully weigh the] full implications before choosing a different course."