Repository navigation
Use CSPRNG for random UUID node ID #135244
Copy link
Copy link
Closed
Labels
3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Feature or enhancement
Proposal:
Issue for: #135226
(I forgot to open issue first, sry)
I'll do the benchmark of the performance impact when switching to secrets.getrandbits() for the clock sequence soon. I'll post here.
I totally agree with the previous discussion. Summary:
- Maybe make it more clearer in the docs of UUIDv8(?) Its possible to predict UUIDv8 if hackers have collected enough UUIDs. BUT, UUIDv8 is highly customizable. It's pretty ez if someone wants to use CSPRNG in UUIDv8s by writing a wrapper outside the call(or using UUIDv4 instead lol).
- Change
_random_getnode()from PRNG to CSPRNG which randomly generates 48-bits note when python failed to get MAC address
def _random_getnode():
+ import secrets
+ return secrets.randbits(48) | (1 << 40)
- import random
- return random.getranbits(48) | (1 << 40)- Change the logic when generating
clock_seqfrom PRNG to CSPRNG in bothuuidv1()anduuidv6(). Well I think this is of great importance. Those two algorithm are time-based. The only random thing comes fromclock_seq. Hackers can predict the next UUID if they got 624*32 random bits generated from the previous UUIDs (1427 UUIDs will be enough).
def uuid1(node=None, clock_seq=None):
...
if clock_seq is None:
+ import secrets
+ clock_seq = secrets.randbits(14) # instead of stable storage
- import random
- clock_seq = random.getrandbits(14) # instead of stable storage
...
def uuid6(node=None, clock_seq=None):
...
+ import secrets
+ clock_seq = secrets.randbits(14) # instead of stable storage
- import random
- clock_seq = random.getrandbits(14) # instead of stable storage
...note that nothing will be changed if the performance impact is unacceptable.
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
Linked PRs
- gh-135244: use CSPRNG for random UUID node ID #135226
- [3.14] gh-135244: generate UUID random Node ID with a CSPRNG as per RFC 9562, §6.10.3 (GH-135226) #135255
- gh-135244: improve wording of
uuid8docs about CSPRNG #135433 - [3.14] gh-135244: improve wording of
uuid8docs about CSPRNG (GH-135433) #135467 - [3.13] gh-135244: generate UUID random Node ID with a CSPRNG as per RFC 9562, §6.10.3 (GH-135226) #137408
Note
3.13 needs a backport but we need to wait until the MAC address detection PR is merged (see #135244 (comment)), as otherwise, there is a small penalty at import time and upon first use of uuid1() and uuid6().
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
Activity
LamentXU123 commentedon Jun 8, 2025
Another CSPRNG(
os.urandom()+ cutoff +int.from_bytes()) is considered if its faster thansecrets.randbits()I've run the brench mark wieh pyperf. It seems like
os.urandom()might be faster.so to sum up, may we use
os.urandom()instead ofrandom.getrandbits()in clock_seq and notes generations, and make clearer security clarifications in doc of UUIDv8? @picnixzpicnixz commentedon Jun 8, 2025
To be precise, I should have said that this is assuming that the UUIDs are generated sequentially and that the underlying MT-19937 state is not touched in between, so it's a bit more complex.
picnixz commentedon Jun 8, 2025
I think I saw the benchmarks results somewhere. Can you post them in full as well? (I think you edited your message).
[-]Get random in UUID more cryptography secure[/-][+]Use CSPRNG for random UUID node ID & clock sequence #135226 [/+][-]Use CSPRNG for random UUID node ID & clock sequence #135226 [/-][+]Use CSPRNG for random UUID node ID & clock sequenc[/+][-]Use CSPRNG for random UUID node ID & clock sequenc[/-][+]Use CSPRNG for random UUID node ID & clock sequence[/+]picnixz commentedon Jun 8, 2025
I'll treat this as a bugfix but not a security bug fix as it's not critical enough IMO.
LamentXU123 commentedon Jun 8, 2025
os.urandom(): Mean +- std dev: 205 ns +- 6 ns
random.getrandbits(): Mean +- std dev: 105 ns +- 5 ns
secrets.randbits(): Mean +- std dev: 17.6 us +- 2.3 us
pyperf on python 3.9
benchmark_UUID.json
36 remaining items
picnixz commentedon Jun 15, 2025
Again, the attack surface is way too small and quite hard to exploit.
This penalizes other users, which I don't want to. And it wouldn't really solve the issue. Assuming that the adversary is able to attack a UUIDv8 where a, b, and c are generated by the same PRNG (this is the case here), then even if 'b' is generated by a CSPRNG, they can ignore it. And then, they can predict the next 'a' and 'c' chunks, and can just bruteforce the 'b' chunk directly (12 bits is only 5k possibilities, and if they can spam 200 API sequential calls to get their password-reset token, we should assume they can also spam 5k sequential API calls).
Once again, I will reject this feature.
pythongh-135244: generate UUID random Node ID with a CSPRNG as per RF…
pythongh-135244: improve wording of `uuid8` docs about CSPRNG (python…
pythongh-135244: generate UUID random Node ID with a CSPRNG as per RF…
pythongh-135244: improve wording of `uuid8` docs about CSPRNG (python…
hugovk commentedon Jul 22, 2025
3.14 RC1 note: this has been fixed for 3.14, the
deferred-blockerlabel is for 3.13.pythongh-135244: generate UUID random Node ID with a CSPRNG as per RF…
pythongh-135244: improve wording of `uuid8` docs about CSPRNG (python…
[3.13] pythongh-135244: generate UUID random Node ID with a CSPRNG as…
[3.13] gh-135244: generate UUID random Node ID with a CSPRNG as per R…
pythongh-135244: generate UUID random Node ID with a CSPRNG as per RF…
pythongh-135244: improve wording of `uuid8` docs about CSPRNG (python…