Какие правила итерации применяются к crypt() с использованием CRYPT_EXT_DES?
Мой тестовый пример выглядит следующим образом:
echo crypt('string', '_....salt');//error
echo crypt('string', '_A...salt');//fast
echo crypt('string', '_AAAAsalt');//slow
Объяснение, как указано на http://www.php.net/manual/en/function.crypt.php:
CRYPT_EXT_DES - расширенный хэш на основе DES. "Соль" - это строка из 9 символов, состоящая из подчеркивания, за которым следуют 4 байта числа итераций и 4 байта соли. Они кодируются как печатаемые символы, 6 бит на символ, наименее значимый символ в первую очередь. Значения от 0 до 63 кодируются как "./0-9A-Za-z". Использование недопустимых символов в соли приведет к сбою crypt().
Точка - это печатный символ, так почему он возвращает ошибку? И какой "порядок" применяется к используемым символам, в результате чего "AAAA" больше итераций, чем "A..."?
4 ответа
Этот вопрос немного стар, но я нашел его, пытаясь обдумать, как создать здесь класс хеширования для внутреннего использования, и я придумал эту маленькую функцию, которая будет base64 кодировать целое число с соответствующими символами / значимостью для использоваться как 4-символьный "счетчик итераций". Возможные значения от 1 до 16 777 215
private function base64_int_encode($num){
$alphabet_raw = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$alphabet = str_split($alphabet_raw);
$arr = array();
$base = sizeof($alphabet);
while($num){
$rem = $num % $base;
$num = (int)($num / $base);
$arr[]=$alphabet[$rem];
}
$arr = array_reverse($arr);
$string = implode($arr);
return str_pad($string, 4, '.', STR_PAD_LEFT);
}
Надеюсь, это поможет кому-то!
Система счисления, используемая в Extended DES:
.... - 0 (Extended DES error)
/... - 1
0... - 2
1... - 3
2... - 4
3... - 5
4... - 6
5... - 7
6... - 8
7... - 9
8... - 10
z... - 63
./.. - 64
//.. - 65
0/.. - 66
1/.. - 67
Y/.. - 100
61.. - 200
g2.. - 300
E4.. - 400
o5.. - 500
M7.. - 600
w8.. - 700
UA.. - 800
2C.. - 900
cD.. - 1000
zz.. - 4095
../. - 4096
/./. - 4097
0./. - 4098
1./. - 4099
xzzz - 16 777 213
yzzz - 16 777 214
zzzz - 16 777 215
И в связи с солью:
_/...salt - 1
_0...salt - 2
_1...salt - 3
_2...salt - 4
_3...salt - 5
_4...salt - 6
_5...salt - 7
_6...salt - 8
_7...salt - 9
_8...salt - 10
_z...salt - 63
_./..salt - 64
_//..salt - 65
_0/..salt - 66
_1/..salt - 67
_Y/..salt - 100
_61..salt - 200
_g2..salt - 300
_E4..salt - 400
_o5..salt - 500
_M7..salt - 600
_w8..salt - 700
_UA..salt - 800
_2C..salt - 900
_cD..salt - 1000
_zz..salt - 4095
_../.salt - 4096
_/./.salt - 4097
_0./.salt - 4098
_1./.salt - 4099
_xzzzsalt - 16 777 213
_yzzzsalt - 16 777 214
_zzzzsalt - 16 777 215
Код Klathmon хорош, но есть некоторые ошибки:
Первый - алфавит
It is:
./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
Should be:
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Второе - порядок символов / цифр
It generates for example: ...z
But it should generate: z...
Улучшенный код:
function base64_int_encode($num) {
$alphabet_raw='./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$alphabet=str_split($alphabet_raw);
$arr=array();
$base=sizeof($alphabet);
while($num) {
$rem=$num % $base;
$num=(int)($num / $base);
$arr[]=$alphabet[$rem];
}
$string=implode($arr);
return str_pad($string, 4, '.', STR_PAD_RIGHT);
}
В цитируемом параграфе сказано все: - сначала наименее значимый символ - значения от 0 до 63 кодируются как "./0-9A-Za-z"
Так что в вашем примере "_.... соль" будет означать 0 раундов, которые, очевидно, не могут работать. и "_A... соль" меньше, чем "_AAAAsalt", учитывая, что наименьший значимый символ стоит первым.
"_... Asalt" также будет больше, чем "_A... соль"