Сгенерировать 16-значное уникальное шестнадцатеричное значение из заданной строки чисел

Как бы я это сделал? Я пробовал использовать SHA-1 и MD5, но вывод слишком длинный для моих требований, и усечение не сделало бы его уникальным.

Вход: строка, содержащая числа, например. (0302160123456789)

Получен вывод: 30f2bddc3e2fba9c05d97d04f8da4449

Желаемый результат: уникальный номер в диапазоне (0000000000000000 - FFFFFFFFFFFFFFFF) и длиной 16 символов

Любая помощь / указатели приветствуются.


person Zeus    schedule 02.03.2016    source источник
comment
stackoverflow.com/questions/1660501/   -  person Darshan Mehta    schedule 03.03.2016
comment
Когда вы пишете, а усечение не делает его уникальным, вы должны понимать, что хеш-функции не уникальны. См. Объяснение на странице en.wikipedia.org/wiki/Hash_function. Усекая, вы просто увеличиваете вероятность столкновения, но оно все равно будет небольшим: 1 из 2 ^ 64. Поэтому я бы использовал усеченные значения SHA1 или MD5.   -  person Sci Prog    schedule 03.03.2016


Ответы (3)


Насколько велик ваш входной домен? Если он больше, чем ваш выходной домен, тогда применяется принцип голубиной норы, и вы не можете получить уникальный вывод по определению.

Если входной домен меньше или равен выходному домену, вы можете легко сделать это с помощью Псевдослучайной перестановки (PRP), которые предоставляют блочные шифры.

Выходные данные в 16 шестнадцатеричных кодов эквивалентны 8 байтам и эквивалентны 64 битам. DES (и Triple DES) - это блочный шифр с таким размером блока.

  1. Компактно проанализируйте входную строку в массив байтов. Если ввод всегда состоит из числовых цифр, вы можете использовать подход Эббе М. Педерсена с

    byte[] plaintext = new BigInteger("0302160123456789").toByteArray();
    
  2. Затем вы можете сгенерировать случайный, но фиксированный ключ из 24 байтов для Triple DES и создать экземпляр шифра с помощью:

    Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DESede"));
    byte[] ciphertext = c.doFinal(plaintext);
    
  3. Используйте какой-нибудь шестнадцатеричный преобразователь, чтобы получить желаемое представление.

С его помощью вы можете "хешировать" числа до 36028797018963968. Если вам нужны более крупные числа (до 9223372036854775808), вам нужно использовать "DESede/ECB/NoPadding" и добавить несколько байтов заполнения.

person Artjom B.    schedule 03.03.2016

вы собираетесь получить больше, чем FFFFFFFFFFFFFFFF разных строк?

если нет, то это простая проблема генерации целых чисел: первая строка получит 0, следующая 1 и т. д .; вы просто ведете список строк и проверяете, появляется ли что-то такое же.

person gpasch    schedule 02.03.2016

Вы можете просто преобразовать свой номер в шестнадцатеричный, используя BigInteger следующим образом:

String id = new BigInteger("0302160123456789").toString(16);
System.out.println(id);

Это дает:

112d022d2ed15
person Ebbe M. Pedersen    schedule 02.03.2016