Я всё-таки не понимаю, почему это корректный способ. Вы учли, например, что пароль «aftera» получается из [«after», «a»] и [«aft», «era»]?
Да: пароль из 6 символов можно получить и как 5+1, и как 3+3, и ещё десятка три комбинаций (от 6 и 4+2 и 2+4, до 1+2+1+1+1 и 1+1+1+1+2 и 1+1+1+1+1+1). Просто как количество разных разложений числа
в сумму натуральных чисел.
(Полный список для 6 символов)
Например для пароля из 6 символов из исходного словаря есть
вариант из одного слова,
комбинаций из слов длины 5 и 1 в любом порядке,
комбинаций из слов длины 3 (даже двух одинаковых), и например
комбинаций из слов длины 3 и 2 и 1 символов именно в таком порядке. Чтобы учесть разный порядок достаточно домножить на количество перестановок, которых для таких трёх слов всего
, а например для слов длиной 3 и 1 и 1 и 1 символов перестановок будет лишь 4 разных (3+1+1+1, 1+3+1+1, 1+1+3+1, 1+1+1+3) и количество комбинаций
. Сложив их и все остальные комбинации получим полное количество всех возможных комбинаций пароля, без перебора самих этих комбинаций.
Для исходного словаря полное количество комбинаций ровно 6 символьного пароля будет
— сумма всех строк, каждая из которых как перемножение соответствующих количеств слов указанной в строке длины.
это энтропия пароля.
Для исходного словаря полное количество комбинаций ровно 16 символьного пароля будет
с энтропией
. По сравнению с грубой оценкой выше в
.
Надеюсь ни в чём не ошибся, но лучше проверьте. Да, считал не руками, написал программулю на PARI/GP, считалось доли секунды:
Код:
? v=[52,773,783,2345,3136,631];
? z=0; forpart(x=6, forperm(x,s, z+=prod(i=1,#s,v[s[i]])), #v); print(z,"=2^",log(z)/log(2));
58839018855=2^35.77605413862021505930980806
? z=0; forpart(x=16, forperm(x,s, z+=prod(i=1,#s,v[s[i]])), #v); print(z,"=2^",log(z)/log(2));
70348031827212043070971446506=2^95.82849671765207141028344286
time = 46 ms.
Вот про коллизии не подумал, факт.