4 ms·
Newbie here: for every one of my projects, I go out hunting for a decent way to do record IDs and still am coming up short. I dislike mightily UUIDs for the use
by pbreit 11y ago
Newbie here: for every one of my projects, I go out hunting for a decent way to do record IDs and still am coming up short. I dislike mightily UUIDs for the user-unfriendly lengths. My preference would be for something like airline codes or YouTube IDs: 6-10 alphanumeric IDs. Should I just be generating a hash and actually storing it in the DB after checking for collisions? Or is there a way to encrypt/decrypt to a specific length with a specific set of usable characters?
- schoen 11y agoYou might be interested in https://en.wikipedia.org/wiki/Format-preserving_encryption https://en.wikipedia.org/wiki/Format-preserving_encryption
- kjksf 11y agoYou can use http://hashids.org/ http://hashids.org/. It obfuscated the real ids with reversible (but secret and un-guessable) transformation so on the server I deal with numeric ids (like 5) but the browser sees something like vgRg. I wrote up a bit more about this: https://quicknotes.io/n/vgRg-how-to-prevent-competitors-from- https://quicknotes.io/n/vgRg-how-to-prevent-competitors-from...
- imron 11y agoThe link you provided to the write up is not a valid link.
- kjksf 11y agoSorry about that, it was a private note. Fixed now.
- deleted 11y ago[deleted]
- dchest 11y agoThe are not secret and not unguessable, they use some homegrown cipher, calling the result of encryption a "hash" for some reason (http://carnage.github.io/2015/08/cryptanalysis-of-hashids/ http://carnage.github.io/2015/08/cryptanalysis-of-hashids/)
- yetanothercoder 11y agoIt's for search/seo reasons. http://hashids.org/#why-hashids http://hashids.org/#why-hashids
- michaelt 11y agoI see in your note you say there are many implementations of this idea Is there a general name for this pattern? I'd like to find some of the other libraries for doing the same thing.
- mcao 11y agoYou can simply use the database integer identity column and convert it into a series of alpha numeric characters. With a little effort, you can generate randomized, unique values. I've written a library that does exactly that, https://github.com/mikecao/hashkit https://github.com/mikecao/hashkit.
- mappu 11y agoIn the past i've seen a 32/64bit block cipher used (e.g. Skip32) with a hardcoded key, as an int->int reversable obfuscating transform.
- stan_rogers 11y agoA base 30 time stamp will give you about the right number of characters, case-insensitive, and without the possibly-ambiguous 0, 1, O, I, L (lower-case ambiguous) and Q (possibly upper-case ambiguous) using 23456789ABCDEFGHJKMNPRSTUVWXYZ as valid characters. Adding back the 0 and 1 (that is, anybody listening to a user on a support call, or any code, would automatically interpret I or L as 1 and O or Q as 0) gives you base 32 and a shorter ID code. If milliseconds are going to be too collision-prone (that is, you can't recuperate the time you'll occasionally have to advance), a short entity code (user or server name abbreviation, f'rinstance) prepended with a dash should make it memorable and user-friendly.
- gmac 11y agoI suggest you remove the remaining vowels from that, giving base 27. Then you have no worries about accidentally generating obscenities.
- stan_rogers 11y agoOddly, nobody ever seems to worry about that with hashes, encryption output or GUIDs... but if it's a worry, then, sure, hey, why not. (By the way, that system has been in regular use for more than 20 years in commercial software.)
- zo1 11y agoThank you for that! I could have had a very front-facing "dirty" bug make it into production soon.
- dsr_ 11y agoGDDMNSHTFCK.
- gmac 11y agoBless you!
- ars 11y agoEasiest way is simply XOR the database auto-increment ID with a fixed number, then truncate to (AND to) however many bits seem reasonable for your site. Not super secure, but good enough for this purpose. Unless you have a long ID people can always simply try every ID, no matter what format you use. So fancy encryption on the ID isn't all that useful. If security is important then generate a random 64bit number and store that, rather than let the database auto-generate a number.
- JoshTriplett 11y ago> Easiest way is simply XOR the database auto-increment ID with a fixed number, then truncate to (AND to) however many bits seem reasonable for your site. XOR has a trivial known-plaintext attack, and you don't even need to determine the entire key to get something useful. If you can create a few posts in order and obtain a series of sequential items, you can obtain the low-order bits of the number XORed in, at which point you can easily browse around for adjacent items from any post.
- dchest 11y agoJust generate a random string (make sure to use the proper generator, e.g. https://gist.github.com/dchest/751fd00ee417c947c252 https://gist.github.com/dchest/751fd00ee417c947c252). If the result is shorter than, say 100 bits, you'll have to check for collisions (e.g. unique constraint in database). Alternatively, if you have 64-bit sequences as IDs (e.g. autoincremented ids in SQL database), you can encrypt then using a real 64-bit block cipher, such as Blowfish or XTEA, with a secret key known only to server. This can give you unsigned 64-bit numbers, which are usable in existing systems (except in JavaScript, where maximum integer has 53 bits), for example: 1 -> 3491820675944448233 2 -> 9264994595240464886 If you use base64 encoding, it will give you 11-character strings, e.g. "0AdUgU8OZfo". Make sure to use URL-safe encoding, though (instead of +, / it uses -, _).
- infogulch 11y agoOr even better: base58 encoded[0]. >Compared to Base64, the following similar-looking letters are omitted: 0 (zero), O (capital o), I (capital i) and l (lower case L) as well as the non-alphanumeric characters + (plus) and / (slash). [0]: https://en.wikipedia.org/wiki/Base58 https://en.wikipedia.org/wiki/Base58