Ответ 1
Пароль ограничивается 72 символами внутри алгоритма склепа.
Чтобы узнать, почему, посмотрим на crypt()
source: http://lxr.php.net/xref/PHP_TRUNK/ext/standard/crypt.c#202
} else if (
salt[0] == '$' &&
salt[1] == '2' &&
salt[3] == '$') {
char output[PHP_MAX_SALT_LEN + 1];
memset(output, 0, PHP_MAX_SALT_LEN + 1);
crypt_res = php_crypt_blowfish_rn(password, salt, output, sizeof(output));
if (!crypt_res) {
ZEND_SECURE_ZERO(output, PHP_MAX_SALT_LEN + 1);
return NULL;
} else {
result = zend_string_init(output, strlen(output), 0);
ZEND_SECURE_ZERO(output, PHP_MAX_SALT_LEN + 1);
return result;
}
Поле password
- это простое поле char*
. Поэтому нет информации о длине. Все, что прошло, является нормальным указателем.
Итак, если мы будем следовать этому, мы в конечном итоге приземлимся на BC_set_key
.
Важной частью является цикл:
for (i = 0; i < BF_N + 2; i++) {
tmp[0] = tmp[1] = 0;
for (j = 0; j < 4; j++) {
tmp[0] <<= 8;
tmp[0] |= (unsigned char)*ptr; /* correct */
tmp[1] <<= 8;
tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
if (j)
sign |= tmp[1] & 0x80;
if (!*ptr)
ptr = key;
else
ptr++;
}
diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
expanded[i] = tmp[bug];
initial[i] = BF_init_state.P[i] ^ tmp[bug];
}
BF_N
определяется как 16. Таким образом, внешний цикл будет цикл 18 раз (BF_N + 2
).
Внутренний цикл будет циклически 4 раза. 4 * 18 == 72.
И там у вас есть, будет прочитано всего 72 символа ключа. Больше.
Примечание
Теперь есть интересный побочный эффект для этого алгоритма. Поскольку он использует C-строки (строки, завершенные нулевым байтом \0
), невозможно использовать что-либо за прошлым \0
. Таким образом, пароль, содержащий нулевой байт, теряет любую энтропию. Пример: http://3v4l.org/Y6onV