Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-135244: use CSPRNG for random UUID node ID#135226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
picnixz merged 13 commits intopython:mainfromLamentXU123:main
Jun 8, 2025

Conversation

LamentXU123
Copy link
Contributor

@LamentXU123LamentXU123 commentedJun 6, 2025
edited by bedevere-appbot
Loading

random.getrandbits() is used widely in libuuid espectially in generating clock_seqs in UUID v1 and v6

if 624*32//14+1 UUIDs are leaked to hackers, they could predict the next UUID generated.

reference:https://github.com/LamentXU123/cve/blob/main/UUID.md

to make it more cryptography secure,secrets.randbits() should be used instead ofrandom.getrandbits()

mattwang44 reacted with thumbs up emoji
@python-cla-bot
Copy link

python-cla-botbot commentedJun 6, 2025
edited
Loading

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app
Copy link

Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply theskip news label instead.

@LamentXU123LamentXU123 changed the titleget random in UUID more cryptography securtyget random in UUID more cryptography secureJun 6, 2025
Copy link
Member

@ZeroIntensityZeroIntensity left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

uuid1() already has security warnings, and the rest that were changed here aredocumented as pseudo-random. I don't think we need to change anything here, apart from maybe adding some extra documentation notes.

LamentXU123 reacted with eyes emoji
@LamentXU123
Copy link
ContributorAuthor

You're right. But I think changing them to a more secure way has no disadvantage. Why not make it more unpredictable with no side effects?

@ZeroIntensity
Copy link
Member

Well, there are clearly side-effects. The UUID tests are totally broken by this change.

@LamentXU123
Copy link
ContributorAuthor

Well it seems like its broken because the test script usesrandom.getrandbits()

for example:

    def test_uuid1_time(self):        with mock.patch.object(self.uuid, '_generate_time_safe', None), \             mock.patch.object(self.uuid, '_last_timestamp', None), \             mock.patch.object(self.uuid, 'getnode', return_value=93328246233727), \             mock.patch('time.time_ns', return_value=1545052026752910643), \             mock.patch('random.getrandbits', return_value=5317): # guaranteed to be random            u = self.uuid.uuid1()            self.assertEqual(u, self.uuid.UUID('a7a55b92-01fc-11e9-94c5-54e1acf6da7f'))

this will triger a assertion error becauserandom.getrandbits() was changed tosecrets.randbits() so teh script could not control the random number by patching ;)

I'll take a closer look soon

@LamentXU123
Copy link
ContributorAuthor

Well it seems like its broken because the test script usesrandom.getrandbits()

for example:

    def test_uuid1_time(self):        with mock.patch.object(self.uuid, '_generate_time_safe', None), \             mock.patch.object(self.uuid, '_last_timestamp', None), \             mock.patch.object(self.uuid, 'getnode', return_value=93328246233727), \             mock.patch('time.time_ns', return_value=1545052026752910643), \             mock.patch('random.getrandbits', return_value=5317): # guaranteed to be random            u = self.uuid.uuid1()            self.assertEqual(u, self.uuid.UUID('a7a55b92-01fc-11e9-94c5-54e1acf6da7f'))

this will triger a assertion error becauserandom.getrandbits() was changed tosecrets.randbits() so the script could not control the random number by patching ;)

I'll take a closer look soon

@LamentXU123
Copy link
ContributorAuthor

Maybe I could add a parameter to uuid1() and uuid6() which is False by default, and if its true, using secret.randbits() instead of random.getrandbits() ?

@picnixz
Copy link
Member

First of all, please open an issue. This needs a wider discussion. I'll still post here.


I explicitly avoided using a CSPRNG for UUIDv8 because the RFCstates that:

Implementations SHOULD NOT assume that UUIDs are hard to guess

And at the same time itstates:

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"). The exception is when a suitable CSPRNG is unavailable in the execution environment

Now, it's possible to predict the next UUIDv8 if we have enough UUIDv8s values (we can rewind MT-19937 on whichrandom.getrandbits() is based if we have624 32-bit outputs of the PRNG, but that's assuming we do have them). Since UUIDv8 directly embeds the random values, we could say that it's recoverable. But using a CSPRNG instead comes at a cost.

Now, since UUIDv8 is highly customizable, if someone wants to use a CSPRNG for the blocks, they should simply supply it outside the call. The wrapper is simple enough to write. In addition, if someone is worried about using atrue random UUIDv8, they should use UUIDv4 instead. UUIDv8's purpose is not be secure or unguessable, that's the purpose of UUIDv4. Therefore, I don't want to change UUIDv8 (otherwise, the default output would behave as for UUIDv4 which is not interesting).


For the Node ID, it's something I overlooked and forgot. RFC 4122 actually didn't talk about CSPRNG, but its successor, RFC 9562,does:

Alternatively, implementations MAY elect to obtain a 48-bit cryptographic-quality random number as per Section 6.9 to use as the Node ID.

So for Node ID, I'm willing to switch to a CSPRNG, although we're already dealing with privacy issues due to the MAC address. Note that the random Node ID is only here in case we fail to fetch the MAC address.


Finally, for the clock sequence, it appears that other programming languages use a CSPRNG, even though the number of random bits is small (14) and thus, while not predictable with a single shot, it's possible to guess with a probability ~1/16000.


To summarize:

  • open an issue
  • don't change UUIDv8; a secure version of UUIDv8 is UUIDv4 (and I think I've said it in the docs, but we can still make it clearer)
  • change_random_node though it's only if we fail to guess the MAC and sincegh-132710: only use stable_uuid.generate_time_safe() to deduce MAC address #132901, this function should be called less
  • benchmarks the performance impact when switching tosecrets.getrandbits() for the clock sequence. Check if usingos.urandom() + cutoff +int.from_bytes() is actually faster as well. Run those benchmarks under--enable-optimizations --with-lto and usepyperf to make the benchmarks.
LamentXU123 reacted with eyes emoji

@LamentXU123
Copy link
ContributorAuthor

issue is at:#135244
I'll test the brenchmarks soon

@picnixzpicnixz changed the titleget random in UUID more cryptography securegh-135244: use CSPRNG for random UUID node ID & clock sequenceJun 8, 2025
@bedevere-app
Copy link

Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply theskip news label instead.

@bedevere-app
Copy link

Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply theskip news label instead.

@LamentXU123LamentXU123 changed the titlegh-135244: use CSPRNG for random UUID node ID & clock sequencegh-135244: use CSPRNG for random UUID node IDJun 8, 2025
@bedevere-app
Copy link

Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply theskip news label instead.

@bedevere-app
Copy link

Most changes to Pythonrequire a NEWS entry. Add one using theblurb_it web app or theblurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply theskip news label instead.

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
@LamentXU123
Copy link
ContributorAuthor

And add a NEWS entry indicating that the random Node ID is now generated by a CSPRNG.

done. Ready to merge now

@picnixzpicnixz added needs backport to 3.13bugs and security fixes needs backport to 3.14bugs and security fixes labelsJun 8, 2025
…2SOTJ.rstCo-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
@picnixzpicnixzenabled auto-merge (squash)June 8, 2025 11:20
@picnixzpicnixz merged commit1cb7163 intopython:mainJun 8, 2025
39 checks passed
@miss-islington-app
Copy link

Thanks@LamentXU123 for the PR, and@picnixz for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull requestJun 8, 2025
…C 9562, §6.10.3 (pythonGH-135226)This aligns with the recommendations of RFC 9562, Section 6.10, paragraph 3 [1].[1]:https://www.rfc-editor.org/rfc/rfc9562.html#section-6.10-3.---------(cherry picked from commit1cb7163)Co-authored-by: LamentXU <108666168+LamentXU123@users.noreply.github.com>Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
@miss-islington-app
Copy link

Sorry,@LamentXU123 and@picnixz, I could not cleanly backport this to3.13 due to a conflict.
Please backport usingcherry_picker on command line.

cherry_picker 1cb716387255a7bdab5b580bcf8ac1b6fa32cc41 3.13

@bedevere-app
Copy link

GH-135255 is a backport of this pull request to the3.14 branch.

@bedevere-appbedevere-appbot removed the needs backport to 3.14bugs and security fixes labelJun 8, 2025
@picnixz
Copy link
Member

For 3.13, I'll hold this off until#134704 is done.

@LamentXU123
Copy link
ContributorAuthor

Awesome. Thanks for ur work@picnixz 🎉

picnixz added a commit that referenced this pull requestJun 8, 2025
…FC 9562, §6.10.3 (GH-135226) (#135255)gh-135244: generate UUID random Node ID with a CSPRNG as per RFC 9562, §6.10.3 (GH-135226)This aligns with the recommendations of RFC 9562, Section 6.10, paragraph 3 [1].[1]:https://www.rfc-editor.org/rfc/rfc9562.html#section-6.10-3.---------(cherry picked from commit1cb7163)Co-authored-by: LamentXU <108666168+LamentXU123@users.noreply.github.com>Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
lkollar pushed a commit to lkollar/cpython that referenced this pull requestJun 19, 2025
…C 9562, §6.10.3 (python#135226)This aligns with the recommendations of RFC 9562, Section 6.10, paragraph 3 [1].[1]:https://www.rfc-editor.org/rfc/rfc9562.html#section-6.10-3.---------Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@picnixzpicnixzpicnixz approved these changes

@ZeroIntensityZeroIntensityZeroIntensity requested changes

Assignees

@picnixzpicnixz

Labels
needs backport to 3.13bugs and security fixes
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@LamentXU123@ZeroIntensity@picnixz

[8]ページ先頭

©2009-2025 Movatter.jp