2013-07-29 2 views
3

Мне нужно сгенерировать уникальный хэш из значения ID типа Long. Меня беспокоит то, что он не должен глобально генерировать один и тот же хэш из двух разных значений Long/long.Создать уникальный хэш из Long id

MD5 хеширование выглядит неплохо, но хэш-строка очень длинная. Мне нужно только символы

0-9 
a-z and A-Z 

И только 6-символы, такие как: j4qwO7

Что может быть самым простым решением?

+3

Если это уникально, то это не хэш в нормальном смысле слова. –

+1

Вам действительно нужна абсолютно нулевая вероятность получить один и тот же хеш для разных значений или достаточно низкая вероятность? –

+0

Длительное значение - это значение хэша. длинные значения будут иметь каждую цифру в диапазоне (0-9). Это подмножество ваших требований; так что успех! – DwB

ответ

1

Вам не нужно использовать шестнадцатеричное представление. Создайте собственное представление хэша, используя фактические байты хэша из функции. Вы можете усечь хэш-выход, чтобы упростить представление хэша, но это сделало бы столкновения более вероятными.

Edit:

Другие ответы заявляющие, что вы просите не представляется возможным, исходя из числа возможных long значений, является teoretically правда, если вы на самом деле нужно весь диапазон.

Если ваши идентификаторы автоматически увеличивается от нуля и выше, просто62^6 = 56800235584 значения могут быть более чем достаточно для вас, в зависимости от ваших потребностей.

+0

Нравится это: https://github.com/peet/hashids.java – xybrek

13

Ваши требования не могут быть выполнены. У вас есть алфавит из 62 возможных символов и доступно 6 символов, что означает наличие 62 возможных идентификаторов этой формы.

Однако имеется 256 возможно long значения. В pigeon-hole principle невозможно присвоить каждому из этих long значения другого идентификатора данной формы.

+1

https://github.com/peet/hashids.java – xybrek

+3

@xybrek: Я не вижу, как это аннулирует мои аргументы вообще. Этот код * не может удовлетворить ваши требования, как я доказал в своем ответе. –

+0

@JonSkeet Конечно, но если вы немного ослабляете требования и говорите, что 8-символьная строка приемлема, чем Hashids - это путь. – andras

0

Ваш вопрос не имеет смысла.

  1. «Уникальный хэш» - это противоречие в терминах.

  2. A «уникальный хэш» значение Java long должно быть 64 бита в длину, как и сама long, и, конечно, самый простой хэш-функции для этого является f(x) = x, т.е. значением самого long.

  3. 6 символов, которые могут быть 0-9, A-Z и a-z, могут давать только 62^6 = 56800235584 различных значений, чего недостаточно.

0

Шаг 1. Переключитесь на использование ints вместо longs или допустите более длинный «хэш». См. Каждый другой ответ для обсуждения того, почему 6 символов недостаточно для работы с длинными.

Шаг 2. Шифруйте свой номер, используя алгоритм, который не использует прописку. Лично я предлагаю кодировку skip32. Я не обещаю, что это достаточно сильное для безопасности, но если ваша цель - «делать случайные идентификаторы», она работает хорошо.

Шаг 3. Кодируйте номер в качестве номера base_62 (в отличие от base_10, а не в отличие от кодировки base64).

+0

Для шага 2 см. Также http://stackoverflow.com/q/959916/18192 – Brian

0
  1. Вы можете использовать длинное значение irself так же, как и hash (для индексирования/поиска).

  2. Если вам нужно зафуснуть/скрыть свое длинное значение, вы можете использовать любой симметричный алгоритм шифрования с 64-битным блоком, например DES или AES в режиме ECB.

0

Update:

Нет необходимости использовать Hashids. Базы 36 достаточно хороши.

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

Оригинальный ответ, с Hashids:

Вы можете использовать Hashids

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

"ryBo" собирается быть уникальным, так как он может быть преобразован обратно в ваш длинный. Hashids просто преобразует, не hash далее.

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

Если у вас действительно есть 64-битное значение, хэш-строка будет довольно долго (около 16 символов, в зависимости от алфавита), но если вы не планируете иметь больше чем 2^16 штук, вы можете уйти с усечением 64-битного хэша до 32-битного (int).

long id = 12345; 
String hash = hashids.encrypt(Math.abs((int)id)); 
Смежные вопросы