user
|  |
| --- |
| This page uses content from **Wikipedia**. The original article was at Time-based one-time password algorithm. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |

A Time-based One-time Password Algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It is the cornerstone of Initiative For Open Authentication (OATH) and is used in a number of two factor authentication systems.

Essentially, both the server and the client compute the time-limited token, then the server checks if the token supplied by the client matches the locally generated token.

Task

Implement this algorithm using **HMAC-SHA1** and an optional step is to generate the random Base-32 string used as the secret key, but this is not a requirement.

A reference implementation, based on JavaScript, can be found at the following location:

:   :   :   http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript

According to RFC 6238, the reference implementation is as follows:

* Generate a key, **K**, which is an arbitrary bytestring, and share it securely with the client.
* Agree upon an epoch, T0, and an interval, TI, which will be used to calculate the value of the counter C (defaults are the Unix epoch as T0 and 30 seconds as TI)
* Agree upon a cryptographic hash method (default is SHA-1)
* Agree upon a token length, **N** (default is 6)

Although RFC 6238 allows different parameters to be used, the Google implementation of the authenticator app does not support T0, TI values, hash methods and token lengths different from the default.   It also expects the **K** secret key to be entered (or supplied in a QR code) in base-32 encoding according to RFC 3548.

* Google Authenticator App (Apple iOS)
* Google Authenticator App (Google Android)
* Microsoft Authenticator App (Windows Phone)
assistant
(formerly Perl 6)
This is a minimal attempt that covers only the "Time-based" part of the requirement.

```
# Reference:
# https://github.com/retupmoca/P6-Digest-HMAC

use v6.d;
use Digest::HMAC;
use Digest::SHA;

sub totp (Str \secret, DateTime \counter, Int \T0=0, Int \T1=30 --> Str) {
   my \key = ( counter - DateTime.new(T0) ).Int div T1;   
   return hmac-hex(key.Str, secret, &sha1).substr(0,6) # first 6 chars of sha1
}

my $message = "show me the monKey";

say "Deterministic output at ", DateTime.new(2177452800), " with fixed checks,";
loop (my $t = 2177452800 ; $t < 2177452900 ; $t+= 17 ) { # Y2038 safe
   say totp $message, DateTime.new($t);
}

say "Current time output at ", DateTime.new(now), " with random checks,";
loop (my $n = 0 ; $n < 6 ; $n++, sleep (13..23).roll ) {
   say totp $message, DateTime.new(now);
}

```

Output:

```
Deterministic output at 2039-01-01T00:00:00Z with fixed checks,
34ca2a
acfa3f
950fc3
950fc3
a2d4ea
a2d4ea
Current time output at 2019-03-31T15:00:01.765312Z with random checks,
4e36de
d4e9f8
d4e9f8
077e2c
63bbb5
63bbb5
```