14_otp.py 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #!/usr/bin/env python3
  2. from hashlib import md5
  3. from itertools import count
  4. def digest(index, salt, iters):
  5. hashed = salt + str(index)
  6. while iters > 0:
  7. hashed = md5(hashed.encode('ascii')).hexdigest()
  8. iters -= 1
  9. return hashed
  10. def key_indices(salt, stretch):
  11. candidates = {}
  12. for index in count(0):
  13. conseq = prev = None
  14. three = None
  15. fives = set()
  16. for cur in digest(index, salt, stretch + 1):
  17. if cur == prev:
  18. conseq += 1
  19. if conseq == 3 and three is None:
  20. three = cur
  21. elif conseq == 5:
  22. fives.add(cur)
  23. else:
  24. conseq = 1
  25. prev = cur
  26. for five in fives:
  27. for candidate in candidates.pop(five, []):
  28. if index - candidate <= 1000:
  29. yield candidate
  30. if three:
  31. candidates.setdefault(three, []).append(index)
  32. def nth_key(n, salt, stretch):
  33. gen_keys = key_indices(salt, stretch)
  34. return max(next(gen_keys) for i in range(64))
  35. salt = 'cuanljph'
  36. print(nth_key(64, salt, 0))
  37. print(nth_key(64, salt, 2016))