Уменьшите MD5 - используя другую базу - PullRequest
0 голосов
/ 26 мая 2018

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

Моя задача состоит в том, чтобы уменьшить строку MD5 с 32 до менее чем 10 символов таким образом, чтобы хэш можно было воссоздать изсокращенная строка.

Сокращение важно, поскольку пользователям было бы проще воспроизвести уменьшенный хеш.

Например, например: 719bedacf2e560b27f39d80accc67ffd => ZjKa1Gh (математически не верно)

Я сталкивался с этим: Как уменьшить длину хеш-значения?

Он предлагает: Использование другой базы

Я не знаю, каксделать это в PHP, можем ли мы декодировать строку в ее ASCII и перекодировать ее?

Есть ли в PHP встроенные функции, которые я могу использовать в этом случае?

Обновление с использованием https://packagist.org/packages/aza/math

$original = '719bedacf2e560b27f39d80accc67ffd';
$long1 = NumeralSystem::convert($original, 16, 10);
$short = NumeralSystem::convertTo($long1, 62);
$long2 = NumeralSystem::convertFrom($short, 62);
$recovered = NumeralSystem::convert($long2, 10, 16);

var_dump($long1);
var_dump($short);
var_dump($long2);
var_dump($recovered);

// output
string(39) "151012390170261082849236619706853916669"
string(22) "3SNOKWefotgnnCmWnYkTOf"
string(39) "151012390170261082849236619706853916669"
string(32) "719bedacf2e560b27f39d80accc67ffd"

Похоже, что самое низкое, что я могу достичь из 32 символов MD5 - это 22 символа таким образом.Я все еще ищу способы, с помощью которых я могу еще уменьшить его до 10 символов.

Обновление: использование первой половины MD5

$original = '719bedacf2e560b';
$coupon = NumeralSystem::convert($original, 16, 62);
$recovered = NumeralSystem::convert($coupon, 62, 16);

var_dump($coupon);
var_dump($recovered);

// output
string(10) "bnMR3RjZil"
string(15) "719bedacf2e560b"

Если пользователь предоставляетbnMR3RjZil Я могу использовать это для воссоздания 719bedacf2e560b, а затем выполнить поиск MySQL LIKE, чтобы получить полный MD5.Если он возвращает строку, я могу продолжить рекламную деятельность.

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

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

Идея состоит в том, что вы интерпретируете свою входную строку как последовательность из 128 битов.Теперь, если вы укажете, что ваш новый алфавит (символы новой базовой системы) A-Za-z0-9+-, у вас есть 64 символа, что означает, что вам нужно 6 бит для кодирования каждого из них.Поэтому вы можете сначала преобразовать свою входную строку в двоичное представление, разделить это представление на куски по 6 битов и выразить каждый кусок в указанном наборе символов A-Za-z0-9+-:

<?php

$s = "719bedacf2e560b27f39d80accc67ffd";

function conv($s){
  $ret = base_convert($s, 16, 2);
  return str_repeat("0", 8 - strlen($ret)) . $ret;
}

$binary_repr = implode(array_map(conv, str_split($s, 2)), '');

$items = str_split($binary_repr, 6);

function item2char($str){
  $code = base_convert($str, 2, 10);
  $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-';
  return $alphabet[$code];
}

$result = implode(array_map(item2char, $items), '');
echo $result;

?>

Как отмечено в комментариях, этов основном идея:

<?php
$s = "719bedacf2e560b27f39d80accc67ffd";

echo base64_encode(hex2bin($s));
//cZvtrPLlYLJ/OdgKzMZ//Q==

echo bin2hex(base64_decode("cZvtrPLlYLJ/OdgKzMZ//Q=="));
//719bedacf2e560b27f39d80accc67ffd

?>
0 голосов
/ 26 мая 2018

Моя задача - сократить строку MD5 с 32 до менее чем 10 символов таким образом, чтобы хеш можно было воссоздать из уменьшенной строки.

Это невозможно,Хеш MD5 составляет 128 бит;символ ASCII составляет 7 бит.Невозможно сохранить хеш MD5 в количестве менее 128 ÷ 7 = 18,2 (округление до 19) символов ASCII, и даже это будет включать непечатные управляющие символы.

0 голосов
/ 26 мая 2018

Криптографический хэш на самом деле представляет собой последовательность битов, но его можно интерпретировать как число.Таким образом, теоретически вы можете использовать старый добрый base_convert () для выражения в большой базе.К сожалению, эта функция работает только до базы 36 и ограничена действительными числами (т.е. короткими целыми числами, которые вписываются в PHP_INT_MAX) - в противном случае происходит потеря данных.

Здесь на помощь приходят сторонние библиотеки.Единственная проблема заключается в том, что их, как правило, трудно найти, потому что они обычно предназначены для очень специфических случаев использования (Биткойн, обфускация идентификаторов и т.вероятно, излишне, но должно сделать работу.У меня не было возможности проверить это, но это должно выглядеть так:

$original = '719bedacf2e560b27f39d80accc67ffd';
$short = NumeralSystem::convert($original, 16, 62);
$recovered = NumeralSystem::convert($short, 62, 16);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...