Live data from Hacker News

Goodbye integers, hello UUIDv7

buildkite.com

331–340 of 376 posts

Re: Goodbye integers, hello UUIDv7

#331

Earlier quoted context omitted.

>Having any information, specifically time information, leaking from your systems may or may not have unanticipated security or business implications. (e.g. knowing when session tokens or accounts are created). I don't think this is really true? These are not serially incrementing, they just indicate the time it happened. If you have an ID that you know exists, having the ability to know _when_ it was created is very…

One business implication is that third parties can detect whether your sales increase or decrease from sampling those IDs (a variation on https://en.wikipedia.org/wiki/German_tank_problem )

But how?

You would be correct if the ID were an integer being serially increased. I can sign up to your website today and get an ID X and then sign up again in a week and get ID Y, I can then calculate the number of new users you've had by performing Y-X.

If this ID is a timestamp then there's no such information I can get out of it from a small sample. I sign up today and get todays timestamp, then I sign up next week and get next weeks timestamp..?

Re: Goodbye integers, hello UUIDv7

#332
post #180

Earlier quoted context omitted.

Given that a UUID identifier fits in a single cipher block, and the whole point is that these are unique by construction (no IV needed so long as that holds true), it seems like a single round of ECB-mode AES-128 would enable quickly converting between internal/external identifiers. 128 bits -> 128 bits

I like the idea, but I think it's not possible to rotate the key with that approach, without introducing a breaking change. Eternal secrets are usually a very bad idea, because at some point they are going to be leaked.

Sure you can, just prefix the encrypted identifier with a version number.

    https://app.example.org/file/1:abcdef12345

    -> decrypt abcdef12345 with key "1" to yield UUIDv7 key of file (no matter what the latest key is)

Re: Goodbye integers, hello UUIDv7

#333

Earlier quoted context omitted.

Given that a UUID identifier fits in a single cipher block, and the whole point is that these are unique by construction (no IV needed so long as that holds true), it seems like a single round of ECB-mode AES-128 would enable quickly converting between internal/external identifiers. 128 bits -> 128 bits

No IV, ECB mode... why bother with encryption at all? Just expose the internal id.

Because the internal ID exposes timing/sequence information, as per jonhohle's comment.

Re: Goodbye integers, hello UUIDv7

#335
post #272

Earlier quoted context omitted.

As someone who only cares about v4, I periodically wonder why don't I just use fully random 128-bit identifiers instead (without the version information).

UUID v4 isn't large enough to prevent collisions, that is why segment.io created https://github.com/segmentio/ksuid which is 160bit vs the 128bit of a UUIDv4.

That doesn't help me. My code may generate a whole bunch of IDs in a microsecond, so using a 32bit time isn't going to keep them time sorted. I may as well just use a UUIDv4 at that point.

Re: Goodbye integers, hello UUIDv7

#336

Earlier quoted context omitted.

Storage is cheap, updating indexes is not.

This is why I’ll probably just always use a UUIDv7 primary key and a secondary UUIDv4 indexed external identifier… which is extremely close to how I tend to do things today (I’ve been using ULID and UUIDv4)

But you still need an external->internal lookup, so doesn't that mean you still need an index on the fully random id?

Re: Goodbye integers, hello UUIDv7

#337

Earlier quoted context omitted.

Yep have used an approach just like that, worked quite well if you have a strong pattern to easily translate from one to the other. Gives you an id with the right properties for internal use, efficient indexing etc, and in its encrypted form gives you the properties you want from an external identifier being unpredictable etc, all from one source id. It is true that now your encryption key is now very long lived and…

>> It is true that now your encryption key is now very long lived and effectively part of your public interface No need to encrypt, just store the external key in a table. Not that you're likely to change algorithms.

Late edit: I meant to say No need to encrypt on the fly. Do it once and save it.

Re: Goodbye integers, hello UUIDv7

#338

Earlier quoted context omitted.

What's the risk of collisions with your external ID in this scenario?

I would imagine that they enforce this using e.g. a unique constraint in their database.

Yes, a unique index per table, not globally. Although the probability of a global colission is still extremely small.

Re: Goodbye integers, hello UUIDv7

#339

Earlier quoted context omitted.

This seems overly complex, and you need some kind of key too. Why not just hash it with pretty much any hash function?

Because a hash is (by definition) a one-way function. You need to be able to go the other way for incoming ids.

Ah, good point. Hadn't thought about the opposite direction.

Re: Goodbye integers, hello UUIDv7

#340
post #308
post #302

Earlier quoted context omitted.

Don't create them each time a record is created, create a batch in advance in sufficient number, and do the same every time the previous batch has ran out. UUIDv7 is 128 bits, you can store a large number of them without major penalty.

But then you need to have the client communicate with the server to identify it's newly created object or complicate your logic to have incomplete objects in a pending state, which is one of the things people were using UUIDs to avoid.

You don't store the UUIDs in the database as incomplete records. You can put them in a unused_uuids table and store some of the values in memory to minimize the round-trip. You can even store them in a simple file, and remove each used UUID from that file. When the file is empty, you create a million more of them.
Post reply on HN