· 7 years ago · Feb 21, 2018, 12:28 PM
1import time
2import struct
3import hmac
4import hashlib
5import base64
6
7def authenticate(secret_key, code_attempt):
8 tm = int(time.time() / 30)
9
10 # try 30 seconds behind and ahead as well
11 for ix in [-1, 0, 1]:
12 # convert timestamp to raw bytes
13 b = struct.pack(">q", tm + ix)
14
15 if get_code(secret_key, b) == str(code_attempt):
16 return True
17
18 return False
19
20def get_code(secret_key, raw_timestamp=None):
21 if raw_timestamp is None:
22 tm = int(time.time() / 30)
23 raw_timestamp = struct.pack(">q", tm)
24
25 secret_key = base64.b32decode(secret_key)
26
27 # generate HMAC-SHA1 from timestamp based on secret key
28 hm = hmac.HMAC(secret_key, raw_timestamp, hashlib.sha1).digest()
29
30 # extract 4 bytes from digest based on LSB
31 offset = ord(hm[-1]) & 0x0F
32 truncatedHash = hm[offset:offset+4]
33
34 # get the code from it
35 code = struct.unpack(">L", truncatedHash)[0]
36 code &= 0x7FFFFFFF;
37 code %= 1000000;
38
39 return ("%06d" % code)
40
41if __name__ == "__main__":
42 # debug
43 secret_key = raw_input('Secret Key: ').upper()
44 code = get_code(secret_key)
45 print "Code: %s" % code
46 print "Auth: %s" % authenticate(secret_key, code)