8 comments

[ 3.4 ms ] story [ 26.7 ms ] thread
Much faster (~10x) than standard github.com/google/uuid package

I'm interested in feedback from the HN community.

On an extremely quick review:

- This uses global state under the hood. Surprise! Is it thread safe? I’m not a Go expert, but it looks non-thread-safe.

- The copying code reminds me of old-school awful C buffer handling code. Maybe it’s right. Maybe it’s wrong. But it’s not obviously right.

- The actual meat is a cryptographic randomness cache. This is a subtle thing, and all the best practices are missing. Where’s the backtracking protection? What if the program forks? vDSO getrandom() knows how to do this correctly — something high-level should use it, not reimplement it incorrectly.

Would have been nice if that included timestamp information, to make them orderable. Similar to what uuid v7 does.
My understanding was that speed is not something you want in a UUID generator, since it makes it more susceptible to brute force attacks. Is this not the case?

I've been using Cuid2[1] in most of my personal projects (this Go implementation[2], actually), which is fast enough, but not "too fast". It's also secure, collision resistant, and has everything I would need from a UUID.

[1]: https://github.com/paralleldrive/cuid2

[2]: https://github.com/nrednav/cuid2

Advertising any UUID/GUID generator as cryptographically secure, or relying on it to be so, is a mistake, in my opinion.

You use a UUID when you need a universally unique ID whose guessability properties are not a critical security requirement. While the V4 UUID spec (which this package does not implement, but most users might assume it does) states that a UUID implementation SHOULD be cryptographically secure [1], it also states that they MUST NOT be used as security capabilities [2]. This is b/c they are not intended as secure tokens, but many users mistakenly assume them to be suitable as such. Not to mention, V4 UUIDs only have 122 bits of entropy, not 128, since 6 bits are reserved for version and variant information, which many users don't realize.

So you can generate a UUID that is suitable as a secure token, but at that point don't call it a UUID. Just call it a secure token. And if you need a secure token, use something like Go's `Text()` function from `crypto/rand` [3].

The situation reminds me of how the Go team updated the `math/rand` and `math/rand/v2` packages to use a CSPRNG as a defensive measure [4], while still urging users to use `crypto/rand` in secure contexts.

[1]: https://www.rfc-editor.org/rfc/rfc9562.html#unguessability

[2]: https://www.rfc-editor.org/rfc/rfc9562.html#Security

[3]: https://pkg.go.dev/crypto/rand@go1.24.5#Text

[4]: https://go.dev/blog/chacha8rand