简体   繁体   中英

Generate Unique hash from Long id

I need to generate a unique hash from a ID value of type Long . My concern is that it should not globally generate the same hash from two different Long/long values.

MD5 hashing looks a nice solution but the hash String is very long. I only need characters

0-9
a-z and A-Z

And just 6-characters like: j4qwO7

What could be the simpliest solution?

Your requirements cannot be met. You've got an alphabet of 62 possible characters, and 6 characters available - which means there are 62 6 possible IDs of that form.

However, there are 256 8 possible long values. By the pigeon-hole principle , it's impossible to give each of those long values a different ID of the given form.

You don't have to use the hex representation. Build your own hash representation by using the actual hash bytes from the function. You could truncate the hash output to simplify the hash representation, but that would make collisions more probable.

Edit:

The other answers stating that what you ask isn't possible, based on the number of possible long values, is teoretically true, if you actually need the whole range.

If your IDs are auto incremented from zero and up, just 62^6 = 56800235584 values might be more than enough for you, depending on your needs.

Your question doesn't make sense.

  1. 'Unique hash' is a contradiction in terms.

  2. A 'unique hash' value of a Java long must be 64 bits in length, like the long itself, and of course the simplest hash function for that is f(x) = x, ie the long value itself.

  3. 6 characters that can be 0-9, AZ, and az can only yield 62^6 = 56800235584 distinct values, which isn't enough.

Step 1. Switch to using ints instead of longs, or allow for a longer "hash". See every other answer for discussion of why 6 characters is unsufficient for dealing with longs.

Step 2. Encrypt your number using an algorithm which does not using padding. Personally, I suggest skip32 encoding. I make no promises that this is strong enough for security, but if your goal is "make random-looking IDs," it works well.

Step 3. Encode your number as a base_62 number (as opposed to base_10, not as opposed to base64 encoding).

  1. You can use long value irself as same as hash (for indexing/search purposes).

  2. if you need to obfuscate/hide your long value, you can use any symmetric encryption algorithm with 64-bit block, for example - DES or AES in ECB-mode.

Update :

No need to use Hashids. Base 36 is pretty enough.

long id = 12345;
String hash = Integer.toString(Math.abs((int)id), 36);

Original answer, with Hashids:

You might want to use Hashids

long id = 12345;
Hashids hashids = new Hashids("this is my salt");
String hash = hashids.encrypt(id); // "ryBo"

"ryBo" is going to be unique, as it can be converted back to your long. Hashids just converts, doesn't hash further.

long[] numbers = hashids.decrypt("ryBo");
// numbers[0] == 12345

If you really have a 64-bit value, the hash string is going to be quite long (around 16 characters, depending on the alphabet), but if you don't plan to have more than 2^16 thingies, you can get away with truncating the 64-bit hash to 32-bit (an int).

long id = 12345;
String hash = hashids.encrypt(Math.abs((int)id));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM