Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch defaultEntropy to math/rand/v2 #120

Open
bojanz opened this issue May 3, 2024 · 5 comments
Open

Switch defaultEntropy to math/rand/v2 #120

bojanz opened this issue May 3, 2024 · 5 comments

Comments

@bojanz
Copy link

bojanz commented May 3, 2024

defaultEntropy() uses math/rand in order to be fast by default:

	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
BenchmarkNew/WithCryptoEntropy-8      2000000        771 ns/op      20.73 MB/s   16 B/op   1 allocs/op
BenchmarkNew/WithEntropy-8            20000000      65.8 ns/op     243.01 MB/s   16 B/op   1 allocs/op

Go 1.22 introduces math/rand/v2 which uses the ChaCha8Rand generator, greatly improving security with a minimal performance cost. From today's blog post:

For example, consider generating a random UUID. Since UUIDs are not secret, using math/rand might seem fine. But if math/rand has been seeded with the current time, then running it at the same instant on different computers will produce the same value, making them not “universally unique”. This is especially likely on systems where the current time is only available with millisecond precision. Even with auto-seeding using OS-provided entropy, as introduced in Go 1.20, the Go 1 generator’s seed is only a 63-bit integer, so a program that generates a UUID at startup can only generate 2⁶³ possible UUIDs and is likely to see collisions after 2³¹ or so UUIDs. Using Go 1.22, the new ChaCha8Rand generator is seeded from 256 bits of entropy and can generate 2²⁵⁶ possible first UUIDs. It does not need to worry about collisions.

Overall, ChaCha8Rand is slower than the Go 1 generator, but it is never more than twice as slow, and on typical servers the difference is never more than 3ns. Very few programs will be bottlenecked by this difference, and many programs will enjoy the improved security.

So, requiring Go 1.22 and switching defaultEntropy to math/rand/v2 sounds like a win.

@bojanz
Copy link
Author

bojanz commented May 3, 2024

Looks like this is not a simple drop-in replacement because the new Rand does not have a Read() method (yet):
golang/go#65562
golang/go#67059

@peterbourgon
Copy link
Member

Is the benefit purely or mostly derived from the additional entropy of the initial seed?

Twice as slow, even at the level of single-digit nanoseconds, is actually potentially meaningful for this package. I'll play around with the new package, let's see.

@MatteoCalabro-TomTom
Copy link

MatteoCalabro-TomTom commented Jun 6, 2024

Looks like this is not a simple drop-in replacement because the new Rand does not have a Read() method (yet): golang/go#65562 golang/go#67059

It's intended. math/rand.Read has been deprecated: https://pkg.go.dev/math/rand@master#Read

It should use crypto/rand when a non-deterministic source is enough, or an algorithm from math/rand/v2

@bojanz
Copy link
Author

bojanz commented Jun 6, 2024

FWIW golang/go#67059 got accepted and merged, so rand.ChaCha8 will be a drop-in replacement from Go 1.23.

@MatteoCalabro-TomTom
Copy link

I have been looking into google/uuid v7 implementation. By default, crypto/rand.Read is used in NewRandom unless NewRandomFromReader is explicitly preferred.

Probably, that should be the default behavior which is also inline with the aforementioned deprecation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants