The author tries to trick you into believing it is secure by including a salt. However the resulting key space of the "hash" gives you the same security as a 5-6 character alphanumeric password. A motivated attacker could enumerate all possibilities in a few hours.

Interesting. Effectively it's base62 encoding with a fixed salt. I think saying "encrypt" and "decrypt" is sort of misleading, even though you call the non-cryptographic nature of the hashing in the README files.

For my own products I do something a little different. Instead, when I create a record I generate a random number (with Ruby's SecureRandom module) and store the base32 encoding in the database. With the universe set at 1bil, this reliably generates a random 6 character string that I can safely show to the customer.

> this reliably generates a random 6 character string that I can safely show to the customer

Are you sure about that? You might want to consider a smaller alphabet, with vowels and ambiguous letters/numerals (0/O, 1/l/I) omitted. That has two advantages: you won't accidentally generate an identifier containing meaningful words (notably profanity), and the identifiers become easier to unambiguously transcribe and interpret. And you'll still reliably get a 6-character identifier as long as you have at least 32 symbols to use.

That's a fair point. So far there hasn't been any transcribing necessary because I have the customers reply to their receipt emails if they have a problem, but that's definitely something to consider if you have to do phone support.

It's also useful for anything where they might retype the string. (Even if you tell them to copy/paste, some people will still retype.) Not that this necessarily applies to you, but for others considering similar schemes, avoiding I/1/l and such can be really handy.

>For instance, suppose you issue a series of discount coupons. These could be identified by number: 1, 2, 3, 4, ... But of course anyone can fake the number, so you could disguise it with this encryption scheme. Because it's not a one-way hash, the number is recoverable from the coupon, by someone who knows the secret key. When you process the coupon, you decrypt the code, and invalidate that ID so the code can't be used again.

This sounds extremely over-engineered though. You have to have a database of all of the IDs to keep track of which ones are valid, right? If so, you just randomly generate the IDs rather than serializing + encrypting. There is no point in trying to hide information in the ID when it's essentially just a primary key into a database anyway.

Hi, Hashids guy here. Thanks for all of your feedback. A few points: 1) a few updates are coming in the next few weeks (especially in the documentation department) 2) re: "use them as forgotten password hashes" comment <- we used to encode a primary id + a create date + a random throw-away int for the user record, and would end up with a url path similar to this: "/reset-password/Q9rsRKqbZ3Ckv" (yes shorter than md5 or bcrypt, also yes - would lock you out after N attempts; many ways to do it - use your own judgement) 3) version table is coming to show which lang implementations are not yet updated (but we'll try to get all on the same page anyway) 4) "encrypt/decrypt" is misleading and is being renamed to "encode/decode" in upcoming versions (I've had a few people try to pass strings and we've discouraged this since this is not an encryption library, that's my fault). Overall, this is not a project for every scenario, but is useful in its own tiny way. Comments/feedback is always welcome via github or the rest of the Internets. Thanks :)

I recently tried using this for a project but ended up switching. I don't really need the encryption ability. More of an issue though is that there is no way to force that the hashes are "short". If you use their example for hashing the default _id in Mongo, you'll end up with a fairly long hash. The only way I could get them short was to switch to an auto-increment starting at 1 and then they will remain short for as long as the number is small. This presented other issues and in the end I found ShortId [1] which made the whole process much simpler.

I mocked up something similar [1] a while ago, although operating on fixed-length integers instead of db keys and not designed with any regard for the "decryption" process. I'm curious if it's flawed in any significant way for the purpose of converting sequential ids into apparently-random distinct ids.

You still need to remove '5' and 'S'. I'd like a to see people use similar algorithms for mobile input. The two most important characteristics would be to be purely lowercase and to cluster numbers and letters to minimize keyboard switching.