<?php
function word_by_index( $index , $dicts ) {
$sizes = array_map ( function ( $val ) { return count ( $val ) ; } , $dicts ) ; // получаем размеры каждого словаря $result = '' ;
foreach ( $sizes as $key => $size ) {
$result .= $dicts [ $key ] [ $index % $size ] ; // сцепляем слово из частей
$index = floor ( $index / $size ) ; }
return $result ;
}
function R( $hash , $dicts , $total ) {
return word_by_index( $index , $dicts ) ;
}
function make_chain( $start , $length , $dicts , $total ) {
$chain [ 'start' ] = $start ;
for ( $i = 0 ; $i < $length ; ++ $i ) {
$hash = md5 ( $start ) ; // <-- сюда вставьте нужную хэш-функцию // echo ">>> $hash : $start\n"; // диагностическое сообщение
$start = R( $hash , $dicts , $total ) ;
}
$chain [ 'end' ] = $hash ;
echo "Chain from ${chain['start']} to ${chain['end']} is ready.\n " ; // диагностическое сообщение
return $chain ;
}
function make_chains( $count , $length , $dicts ) {
$sizes = array_map ( function ( $val ) { return count ( $val ) ; } , $dicts ) ; // получаем размеры каждого словаря $total = array_reduce ( $sizes , function ( $carry , $item ) { return $carry * $item ; } , 1 ) ; // произведение размеров словарей $chains = [ ] ;
for ( $i = 0 ; $i < $count ; ++ $i ) {
$word = word_by_index
( mt_rand ( 0 , $total - 1 ) , $dicts ) ; // начинаем цепочку с псевдослучайного слова $chain = make_chain( $word , $length , $dicts , $total ) ;
$hash = $chain [ 'end' ] ; // используем конец найденной цепочки как индекс для быстрого поиска
if ( ! isset ( $chains [ $hash ] ) ) $chains [ $hash ] = [ ] ; // если такого хэша не было в корзине, инициализируем её if ( ! in_array ( $chain [ 'start' ] , $chains [ $hash ] ) ) { // проверяем на дубли $chains [ $hash ] [ ] = $chain [ 'start' ] ; // добавляем начало цепочки в корзину
}
}
return $chains ;
}
function find_hash_in_basket( $needle , $haystack_start , $haystack_end , $dicts , $total ) {
echo "Роемся в цепочке от $haystack_start до $haystack_end .\n " ; // диагностическое сообщение
$current_word = $haystack_start ;
do {
$current_hash = md5 ( $current_word ) ; // <-- сюда вставьте нужную хэш-функцию if ( $current_hash === $needle ) {
return $current_word ; // нашли слово, хэш от которого равен заданному
}
$current_word = R( $current_hash , $dicts , $total ) ; // роем в глубину
} while ( $current_hash !== $haystack_end ) ;
return false ; // не нашли
}
function search_hash( $hash , $dicts , $chains , $length ) {
$sizes = array_map ( function ( $val ) { return count ( $val ) ; } , $dicts ) ; // получаем размеры каждого словаря $total = array_reduce ( $sizes , function ( $carry , $item ) { return $carry * $item ; } , 1 ) ; // произведение размеров словарей $current_hash = $hash ;
for ( $i = 0 ; $i < $length ; ++ $i ) {
if ( isset ( $chains [ $current_hash ] ) ) { // нашли хэш в одной из корзин echo "Лезем в корзину $current_hash .\n " ; // диагностическое сообщение
foreach ( $chains [ $current_hash ] as $start ) { // роемся в корзине
$result = find_hash_in_basket( $hash , $start , $current_hash , $dicts , $total ) ; // пытаемся найти в каждой из цепочек корзины
if ( $result ) {
return $result ; // конец поиска
}
}
}
$next_word = R( $current_hash , $dicts , $total ) ; // копаем в глубину
$current_hash = md5 ( $next_word ) ; }
return false ; // не нашли
}
///////////////////// ПРИМЕР //////////////////////////////////
array ( 'свино' , 'овце' , 'тигро' , 'косатко' , 'зубро' , 'волко' , 'кото' ) , array ( 'собака' , 'бык' , 'лев' , 'дельфин' , 'бизон' ) ) ;
$chains = make_chains( 15 , 15 , $dicts ) ;
echo "Радужные таблицы готовы.\n " ;
$hash = '360629d3cf05cee0240a23e1251c58a0' ;
echo "Пытаемся обратить $hash .\n " ;
$word = search_hash( $hash , $dicts , $chains , 15 ) ;
echo "$hash is reversed to $word .\n " ;
PD9waHAKCmZ1bmN0aW9uIHdvcmRfYnlfaW5kZXgoJGluZGV4LCAkZGljdHMpIHsKICAgICRzaXplcyA9IGFycmF5X21hcChmdW5jdGlvbigkdmFsKXtyZXR1cm4gY291bnQoJHZhbCk7fSwgJGRpY3RzKTsgLy8g0L/QvtC70YPRh9Cw0LXQvCDRgNCw0LfQvNC10YDRiyDQutCw0LbQtNC+0LPQviDRgdC70L7QstCw0YDRjwogICAgJHJlc3VsdCA9ICcnOwogICAgZm9yZWFjaCgkc2l6ZXMgYXMgJGtleT0+JHNpemUpIHsKICAgICAgICAkcmVzdWx0IC49ICRkaWN0c1ska2V5XVskaW5kZXggJSAkc2l6ZV07IC8vINGB0YbQtdC/0LvRj9C10Lwg0YHQu9C+0LLQviDQuNC3INGH0LDRgdGC0LXQuQogICAgICAgICRpbmRleCA9IGZsb29yKCRpbmRleCAvICRzaXplKTsKICAgIH0KICAgIHJldHVybiAkcmVzdWx0Owp9CgpmdW5jdGlvbiBSKCRoYXNoLCAkZGljdHMsICR0b3RhbCkgewogICAgJGluZGV4ID0gZ21wX2ludHZhbChnbXBfbW9kKGdtcF9pbml0KCRoYXNoLCAxNiksICR0b3RhbCkpOwogICAgcmV0dXJuIHdvcmRfYnlfaW5kZXgoJGluZGV4LCAkZGljdHMpOyAKfQoKZnVuY3Rpb24gbWFrZV9jaGFpbigkc3RhcnQsICRsZW5ndGgsICRkaWN0cywgJHRvdGFsKSB7CiAgICAkY2hhaW5bJ3N0YXJ0J10gPSAkc3RhcnQ7CiAgICBmb3IoJGkgPSAwOyAkaSA8ICRsZW5ndGg7ICsrJGkpIHsKICAgICAgICAkaGFzaCA9IG1kNSgkc3RhcnQpOyAgICAgICAgICAgICAgICAgICAgLy8gPC0tINGB0Y7QtNCwINCy0YHRgtCw0LLRjNGC0LUg0L3Rg9C20L3Rg9GOINGF0Y3RiC3RhNGD0L3QutGG0LjRjgogICAgICAgIC8vIGVjaG8gIj4+PiAkaGFzaCA6ICRzdGFydFxuIjsgICAgICAgICAgICAvLyDQtNC40LDQs9C90L7RgdGC0LjRh9C10YHQutC+0LUg0YHQvtC+0LHRidC10L3QuNC1CiAgICAgICAgJHN0YXJ0ID0gUigkaGFzaCwgJGRpY3RzLCAkdG90YWwpOwogICAgfQogICAgJGNoYWluWydlbmQnXSA9ICRoYXNoOwogICAgZWNobyAiQ2hhaW4gZnJvbSAke2NoYWluWydzdGFydCddfSB0byAke2NoYWluWydlbmQnXX0gaXMgcmVhZHkuXG4iOyAvLyDQtNC40LDQs9C90L7RgdGC0LjRh9C10YHQutC+0LUg0YHQvtC+0LHRidC10L3QuNC1CiAgICByZXR1cm4gJGNoYWluOwp9CgpmdW5jdGlvbiBtYWtlX2NoYWlucygkY291bnQsICRsZW5ndGgsICRkaWN0cykgewogICAgJHNpemVzID0gYXJyYXlfbWFwKGZ1bmN0aW9uKCR2YWwpe3JldHVybiBjb3VudCgkdmFsKTt9LCAkZGljdHMpOyAvLyDQv9C+0LvRg9GH0LDQtdC8INGA0LDQt9C80LXRgNGLINC60LDQttC00L7Qs9C+INGB0LvQvtCy0LDRgNGPCiAgICAkdG90YWwgPSBhcnJheV9yZWR1Y2UoJHNpemVzLCBmdW5jdGlvbigkY2FycnksJGl0ZW0pe3JldHVybiAkY2FycnkqJGl0ZW07fSwgMSk7IC8vINC/0YDQvtC40LfQstC10LTQtdC90LjQtSDRgNCw0LfQvNC10YDQvtCyINGB0LvQvtCy0LDRgNC10LkKICAgICRjaGFpbnMgPSBbXTsKICAgIG10X3NyYW5kKCk7CiAgICBmb3IoJGkgPSAwOyAkaSA8ICRjb3VudDsgKyskaSkgewogICAgICAgICR3b3JkID0gd29yZF9ieV9pbmRleChtdF9yYW5kKDAsICR0b3RhbCAtIDEpLCAkZGljdHMpOyAgLy8g0L3QsNGH0LjQvdCw0LXQvCDRhtC10L/QvtGH0LrRgyDRgSDQv9GB0LXQstC00L7RgdC70YPRh9Cw0LnQvdC+0LPQviDRgdC70L7QstCwCiAgICAgICAgJGNoYWluID0gbWFrZV9jaGFpbigkd29yZCwgJGxlbmd0aCwgJGRpY3RzLCAkdG90YWwpOwogICAgICAgICRoYXNoID0gJGNoYWluWydlbmQnXTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g0LjRgdC/0L7Qu9GM0LfRg9C10Lwg0LrQvtC90LXRhiDQvdCw0LnQtNC10L3QvdC+0Lkg0YbQtdC/0L7Rh9C60Lgg0LrQsNC6INC40L3QtNC10LrRgSDQtNC70Y8g0LHRi9GB0YLRgNC+0LPQviDQv9C+0LjRgdC60LAKICAgICAgICBpZighaXNzZXQoJGNoYWluc1skaGFzaF0pKSAkY2hhaW5zWyRoYXNoXSA9IFtdOyAgICAgIC8vINC10YHQu9C4INGC0LDQutC+0LPQviDRhdGN0YjQsCDQvdC1INCx0YvQu9C+INCyINC60L7RgNC30LjQvdC1LCDQuNC90LjRhtC40LDQu9C40LfQuNGA0YPQtdC8INC10ZEKICAgICAgICBpZighaW5fYXJyYXkoJGNoYWluWydzdGFydCddLCAkY2hhaW5zWyRoYXNoXSkpIHsgICAgIC8vINC/0YDQvtCy0LXRgNGP0LXQvCDQvdCwINC00YPQsdC70LgKICAgICAgICAgICAgJGNoYWluc1skaGFzaF1bXSA9ICRjaGFpblsnc3RhcnQnXTsgICAgICAgICAgICAgIC8vINC00L7QsdCw0LLQu9GP0LXQvCDQvdCw0YfQsNC70L4g0YbQtdC/0L7Rh9C60Lgg0LIg0LrQvtGA0LfQuNC90YMKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gJGNoYWluczsKfQoKZnVuY3Rpb24gZmluZF9oYXNoX2luX2Jhc2tldCgkbmVlZGxlLCAkaGF5c3RhY2tfc3RhcnQsICRoYXlzdGFja19lbmQsICRkaWN0cywgJHRvdGFsKSB7CiAgICBlY2hvICLQoNC+0LXQvNGB0Y8g0LIg0YbQtdC/0L7Rh9C60LUg0L7RgiAkaGF5c3RhY2tfc3RhcnQg0LTQviAkaGF5c3RhY2tfZW5kLlxuIjsgICAgICAgLy8g0LTQuNCw0LPQvdC+0YHRgtC40YfQtdGB0LrQvtC1INGB0L7QvtCx0YnQtdC90LjQtQogICAgJGN1cnJlbnRfd29yZCA9ICRoYXlzdGFja19zdGFydDsKICAgIGRvIHsKICAgICAgICAkY3VycmVudF9oYXNoID0gbWQ1KCRjdXJyZW50X3dvcmQpOyAgICAgICAgIC8vIDwtLSDRgdGO0LTQsCDQstGB0YLQsNCy0YzRgtC1INC90YPQttC90YPRjiDRhdGN0Ygt0YTRg9C90LrRhtC40Y4KICAgICAgICBpZigkY3VycmVudF9oYXNoID09PSAkbmVlZGxlKSB7CiAgICAgICAgICAgICByZXR1cm4gJGN1cnJlbnRfd29yZDsgICAgICAgICAgICAgICAgICAvLyDQvdCw0YjQu9C4INGB0LvQvtCy0L4sINGF0Y3RiCDQvtGCINC60L7RgtC+0YDQvtCz0L4g0YDQsNCy0LXQvSDQt9Cw0LTQsNC90L3QvtC80YMKICAgICAgICB9CiAgICAgICAgJGN1cnJlbnRfd29yZCA9IFIoJGN1cnJlbnRfaGFzaCwgJGRpY3RzLCAkdG90YWwpOyAgLy8g0YDQvtC10Lwg0LIg0LPQu9GD0LHQuNC90YMKICAgIH0gd2hpbGUoJGN1cnJlbnRfaGFzaCAhPT0gJGhheXN0YWNrX2VuZCk7CiAgICByZXR1cm4gZmFsc2U7IC8vINC90LUg0L3QsNGI0LvQuAp9CgpmdW5jdGlvbiBzZWFyY2hfaGFzaCgkaGFzaCwgJGRpY3RzLCAkY2hhaW5zLCAkbGVuZ3RoKSB7CiAgICAkc2l6ZXMgPSBhcnJheV9tYXAoZnVuY3Rpb24oJHZhbCl7cmV0dXJuIGNvdW50KCR2YWwpO30sICRkaWN0cyk7IC8vINC/0L7Qu9GD0YfQsNC10Lwg0YDQsNC30LzQtdGA0Ysg0LrQsNC20LTQvtCz0L4g0YHQu9C+0LLQsNGA0Y8KICAgICR0b3RhbCA9IGFycmF5X3JlZHVjZSgkc2l6ZXMsIGZ1bmN0aW9uKCRjYXJyeSwkaXRlbSl7cmV0dXJuICRjYXJyeSokaXRlbTt9LCAxKTsgLy8g0L/RgNC+0LjQt9Cy0LXQtNC10L3QuNC1INGA0LDQt9C80LXRgNC+0LIg0YHQu9C+0LLQsNGA0LXQuQogICAgJGN1cnJlbnRfaGFzaCA9ICRoYXNoOwogICAgZm9yKCRpID0gMDsgJGkgPCAkbGVuZ3RoOyArKyRpKSB7CiAgICAgICAgICBpZihpc3NldCgkY2hhaW5zWyRjdXJyZW50X2hhc2hdKSkgeyAgICAgICAgICAgICAgICAvLyDQvdCw0YjQu9C4INGF0Y3RiCDQsiDQvtC00L3QvtC5INC40Lcg0LrQvtGA0LfQuNC9CiAgICAgICAgICAgICAgZWNobyAi0JvQtdC30LXQvCDQsiDQutC+0YDQt9C40L3RgyAkY3VycmVudF9oYXNoLlxuIjsgICAgICAgLy8g0LTQuNCw0LPQvdC+0YHRgtC40YfQtdGB0LrQvtC1INGB0L7QvtCx0YnQtdC90LjQtQogICAgICAgICAgICAgIGZvcmVhY2goJGNoYWluc1skY3VycmVudF9oYXNoXSBhcyAkc3RhcnQpIHsgICAgLy8g0YDQvtC10LzRgdGPINCyINC60L7RgNC30LjQvdC1CiAgICAgICAgICAgICAgICAgICRyZXN1bHQgPSBmaW5kX2hhc2hfaW5fYmFza2V0KCRoYXNoLCAkc3RhcnQsICRjdXJyZW50X2hhc2gsICRkaWN0cywgJHRvdGFsKTsgLy8g0L/Ri9GC0LDQtdC80YHRjyDQvdCw0LnRgtC4INCyINC60LDQttC00L7QuSDQuNC3INGG0LXQv9C+0YfQtdC6INC60L7RgNC30LjQvdGLCiAgICAgICAgICAgICAgICAgIGlmKCRyZXN1bHQpIHsKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkcmVzdWx0OyAgICAgICAgICAgICAgICAgICAgICAgIC8vINC60L7QvdC10YYg0L/QvtC40YHQutCwCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICAkbmV4dF93b3JkID0gUigkY3VycmVudF9oYXNoLCAkZGljdHMsICR0b3RhbCk7ICAgICAgICAgICAgIC8vINC60L7Qv9Cw0LXQvCDQsiDQs9C70YPQsdC40L3RgwogICAgICAgICAgJGN1cnJlbnRfaGFzaCA9IG1kNSgkbmV4dF93b3JkKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsgLy8g0L3QtSDQvdCw0YjQu9C4Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLyDQn9Cg0JjQnNCV0KAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKJGRpY3RzPSBhcnJheSgKICAgICAgYXJyYXkoJ9GB0LLQuNC90L4nLCAgJ9C+0LLRhtC1JywgJ9GC0LjQs9GA0L4nLCAn0LrQvtGB0LDRgtC60L4nLCAn0LfRg9Cx0YDQvicsICfQstC+0LvQutC+JywgJ9C60L7RgtC+JyksCiAgICAgIGFycmF5KCfRgdC+0LHQsNC60LAnLCAn0LHRi9C6JywgICfQu9C10LInLCAgICfQtNC10LvRjNGE0LjQvScsICfQsdC40LfQvtC9JykKKTsKCiRjaGFpbnMgPSBtYWtlX2NoYWlucygxNSwgMTUsICRkaWN0cyk7CmVjaG8gItCg0LDQtNGD0LbQvdGL0LUg0YLQsNCx0LvQuNGG0Ysg0LPQvtGC0L7QstGLLlxuIjsKdmFyX2R1bXAoJGNoYWlucyk7CgokaGFzaCA9ICczNjA2MjlkM2NmMDVjZWUwMjQwYTIzZTEyNTFjNThhMCc7CmVjaG8gItCf0YvRgtCw0LXQvNGB0Y8g0L7QsdGA0LDRgtC40YLRjCAkaGFzaC5cbiI7CiR3b3JkID0gc2VhcmNoX2hhc2goJGhhc2gsICRkaWN0cywgJGNoYWlucywgMTUpOwplY2hvICIkaGFzaCBpcyByZXZlcnNlZCB0byAkd29yZC5cbiI7Cg==