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 }