Вы можете просто перечислить все возможные пароли, содержащие буквы и цифры, считая от 0 до бесконечности и конвертируя число toString
с основанием 36.
long k = 0;
while (true) {
String pwd = Long.toString(k++, 36);
if (SHA1(pwd).equals(hashedPassword)) {
System.out.println(pwd);
}
}
Здесь toString
работает для базы до 36, используя [0-9a-z]
, т.е. она работает в вашем случае, но если вы хотите включить специальные символы, вам придется создать свою собственную функцию числа-пароля ( думаю деление и по модулю), но остальное остается прежним.
Таким образом, требование к памяти составляет O (1), но, конечно, сложность по-прежнему составляет O (36 n ) для паролей длиной до n символов.
Одна из проблем этого подхода заключается в том, что, как и во всех представлениях чисел, ведущие нули будут опущены, поэтому Long.toString
никогда не выдаст пароль, начинающийся с 0
(кроме самого 0
). Чтобы противостоять этому, вы можете использовать два вложенных цикла: внешний цикл, повторяющий число цифр в пароле, и внутренний цикл, повторяющий числа до 36 d и дополняющий строку начальными нулями, или цикл от 36 d до 2 * 36 d и обрежьте первую (ненулевую) цифру. Это может показаться намного более трудоемким, чем раньше, но на самом деле это просто вдвое больше паролей.
for (int d = 1; d < 3; d++) {
long p = pow(36, d);
for (long n = p; n < 2 * p; n++) {
String pwd = Long.toString(n, 36).substring(1);
System.out.println(n + " " + pwd);
}
}
Выход:
0
1
...
z
00
01
...
zz