···8899@memoize
1010def salty_md5(salt, i):
1111- return md5(salt + str(i)).hexdigest()
1111+ return md5('{}{}'.format(salt, i)).hexdigest()
121213131414@memoize
···2727 return a
282829293030-def all_quintuplets(s):
3030+def all_quintuples(s):
3131 for i in range(len(s) - 4):
3232 a, b, c, d, e = s[i:i+5]
3333 if a == b == c == d == e:
3434 yield a
353536363737-def find_pad_key_64(salt, hash_fn):
3737+def find_64th_pad_key(salt, hash_fn):
3838 valid_keys = 0
3939- quintuplets = defaultdict(set)
3939+ triples = {}
4040+ quintuples = defaultdict(set)
4041 i = 0
41424243 while True:
4344 digest = hash_fn(salt, i)
4545+ triple = first_triple(digest)
44464545- for quint in all_quintuplets(digest):
4646- quintuplets[i].add(quint)
4747+ if triple is not None:
4848+ triples[i] = triple
47494848- if i >= 1000:
5050+ for quint in all_quintuples(digest):
5151+ quintuples[i].add(quint)
5252+5353+ if (i - 1000) in triples:
4954 n = i - 1000
5050- triple = first_triple(hash_fn(salt, n))
5555+ triple = triples[n]
5156 for j in range(n + 1, n + 1001):
5252- if triple in quintuplets[j]:
5757+ if triple in quintuples[j]:
5358 valid_keys += 1
5459 sys.stdout.write('.')
5560 sys.stdout.flush()
···64696570if __name__ == "__main__":
6671 SALT = fileinput.input()[0].strip()
6767-6868- print "Index of 64th one-time pad key", find_pad_key_64(SALT, salty_md5)
6969- print "Index of key-stretched pad key", find_pad_key_64(SALT, stretched_md5)
7272+ print "Index of 64th one-time pad key", find_64th_pad_key(SALT, salty_md5)
7373+ print "Index of key-stretched pad key", find_64th_pad_key(SALT, stretched_md5)