1 module simpletotp.totp;
2 
3 import simpletotp.hotp;
4 import std.string;
5 import std.datetime;
6 
7 enum T0 = 0;
8 enum TI = 30;
9 
10 int totp(
11 		const ubyte[] K,
12 		const ulong time,
13 		const int offset = 0,
14 		const int digits = TOK_LEN)
15 {
16 	ulong TC = (time - T0) / TI + offset;
17 	return hotp(K, TC, digits);
18 }
19 
20 int totp(
21 		const string K,
22 		const ulong time,
23 		const int offset = 0,
24 		const int digits = TOK_LEN)
25 {
26 	return totp(K.representation, time, offset, digits);
27 }
28 
29 bool verify_token(const ubyte[] K, const int token, const int sync)
30 {
31 	long now = Clock.currTime(UTC()).toUnixTime!long;
32 	if (totp(K, now) == token)
33 		return true;
34 	
35 	for (int i = 1; i <= sync; ++i)
36 		if (totp(K, now, -i) == token || totp(K, now, i) == token)
37 			return true;
38 	return false;
39 }
40 
41 bool verify_token(const string K, const int token, const int sync)
42 {
43 	return verify_token(K.representation, token, sync);
44 }
45 
46 unittest
47 {
48 	const string key = "12345678901234567890";
49 	assert(totp(key,          59, 0, 8) == 94287082);
50 	assert(totp(key,  1111111109, 0, 8) ==  7081804);
51 	assert(totp(key,  1111111111, 0, 8) == 14050471);
52 	assert(totp(key,  1234567890, 0, 8) == 89005924);
53 	assert(totp(key,  2000000000, 0, 8) == 69279037);
54 	assert(totp(key, 20000000000, 0, 8) == 65353130);
55 }