Follow the algorithm
As implemented in Google Authenticator app, you’ll need:
- A shared secret key K, which is
base32encoded - a specific time period since UNIX epoch T
I’ll use K = GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ and T = 1450235092 (which is Wed, 16 Dec 2015 11:04:52 CST) for example. In the Google Authenticator App, both K and T are passed to TOTP as hexadecimal values (or byte arrays).
Since K is a base32 encoded string, we’ll decode it to byte format. Password changes every 30 seconds, T should be divided by 30, tuncated to integer and converted to hex and padded to 16 hexadecimal digits.
K = 12345678901234567890 K_hex = 31 21 33 34 35 36 37 38 39 30 31 21 33 34 35 36 37 38 39 30 T = truncate(1450235092/30) = 48341169 T_hex = 00 00 00 00 02 E1 A0 B1
The core of TOTP is a hmac-sha1 function, say mac_value = hmac-sha1(auth_code, content). We use K_hex as the auth_code and T_hex as the content.
Byte: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mac_value = 3d 43 cb 58 89 39 a1 a4 bf 76 b9 dc 27 79 81 70 f7 22 a5 0c
Now we need an offset offset = last 4 bits of mac_value
Byte: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
mac_value = 3d 43 cb 58 89 39 a1 a4 bf 76 b9 dc 27 79 81 70 f7 22 a5 0c
offset = 12 ^
And cut off 4 bytes from offset number of bytes to get an intermediate value IV1
Byte: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mac_value = 3d 43 cb 58 89 39 a1 a4 bf 76 b9 dc 27 79 81 70 f7 22 a5 0c IV1 = ** ** ** ** ** ** ** ** ** ** ** ** 27 79 81 70 ** ** ** **
In case that big endian and little endian would interfere with generation, mask IV1 with 0x7FFFFFFF
IV1 = 27 79 81 70 mask = 7F FF FF FF IV2 = 27 79 81 70
then pick last 6 digits of IV2
IV2 = 662274416 Token = ***274416
So at Wed, 16 Dec 2015 11:04:52 CST, with the key GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ, you get the token 274416.
Full implementation
see my GitHub repository cthbleachbit/totp-cth-cli, a bash implementation of a TOTP password manager, I used openssl for hmac hashing and database encryption.
Reference
base32RFC 4648- TOTP RFC 6238
hmac-sha1see RFC 2104 and hmac on Wikipedia