
Hashids – Generate short hashes from numbers - yildizbe
http://www.hashids.org
======
dsl
> use them as forgotten password hashes

Please don't.

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.

~~~
brey
You could use that argument to say 4-digit bank card PINs are really bad
security - and you'd be right, except that they're always locked out after N
attempts.

Why not the same approach here? if you try to brute force a password reset,
you lock out further attempts for a few minutes.

~~~
krallja
You can then use this lockout for a denial of service attack.

~~~
brey
oh no ... I am unable to change my (perfectly secure) password for ten minutes
because an attacker is attempting to brute force my password reset. I'd regard
that as a feature, not a bug.

you don't need to lock out the entire account.

------
zrail
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.

 _Edit: base62, not base82_

~~~
bazzargh
You're storing 6-char base-32 values, so 1073741824 possibilities, but you've
got 50-50 chance of collision after 38582 values - that's not a lot, the
birthday paradox bites again! Using much larger random values or hashes gives
you a better safety margin.

~~~
zrail
I also have a unique constraint on the value and re-run the generator if
there's a collision.

~~~
d55
That is something that hashid avoids.

------
ExpiredLink
If it is encryption and decryption why is it called 'hash'?

~~~
d55
They explain that on their website.

~~~
ExpiredLink
Oh, I see:

>> _A true cryptographic hash cannot be decrypted. However, to keep things
simple the word hash is used loosely to refer to the random set of characters
that is generated -- like a YouTube hash._

What?

------
jbaudanza
I've used the Blowfish cipher to obfuscate database IDs into youtube-like
URLs. Blowfish has a small 64-bit blocksize which fits nicely into a base64'd
URL param.

------
xhrpost
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.

\- [1] [https://github.com/dylang/shortid](https://github.com/dylang/shortid)

------
mischanix
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.

1\. [http://ideone.com/qLQHI5](http://ideone.com/qLQHI5)

------
latchkey
I've been using this for a while now and I'm pretty happy with it. Java
implementation of Crockford's Base32 algorithm for encoding simple numeric
values:

[https://code.google.com/p/unsuck/source/browse/trunk/src/mai...](https://code.google.com/p/unsuck/source/browse/trunk/src/main/java/unsuck/io/CrockfordBase32.java)

------
kvz
I have an old blogpost around the same idea that many people contributed
versions in different languages to: [http://kvz.io/blog/2009/06/10/create-
short-ids-with-php-like...](http://kvz.io/blog/2009/06/10/create-short-ids-
with-php-like-youtube-or-tinyurl/) Hope it's useful

------
underwater
If you don't need salts you can just use the inbuilt base64 functions:

    
    
       var numbers = [1, 2, 3,  4, 5];
       var encoded = btoa(''+numbers).replace(/=/g, '');
       var decoded = atob(encoded).split(',').map(Number);
       console.log(encoded, decoded);

------
hcarvalhoalves
If you need a short code the user will have to type the legibility is more
important than the length, you can optimize for human input like this:

[https://gist.github.com/hcarvalhoalves/5330d8af36e7163d58c4](https://gist.github.com/hcarvalhoalves/5330d8af36e7163d58c4)

~~~
underwater
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.

------
mcao
I actually created something really similar, except with more options to fine
tune the encoding/decoding process:

[https://github.com/mikecao/hashkit](https://github.com/mikecao/hashkit)

------
oh_sigh
FYI the salt has a max size n - All salts longer than n are equivalent to
using a salt of substr(salt, 0, n)

------
cordite
My only complaint is that not all the implementations yield the same results.

