Time-based one-time password: TOTP explained

Internet users regularly have to enter passwords – for example, when signing into social media platforms, shopping online, or using internet banking. Passwords prevent third parties from accessing sensitive data. However, many users are not sufficiently diligent about online security: professionals can crack simple passwords in a matter of seconds. Other people create good passwords, but fail to store them safely, thus leaving a door open to criminals. In addition, weaknesses in the services which users subscribe to are no small matter either. If such services do not properly secure passwords, the data of thousands of users can be at risk.

One way of minimizing the risk is to use two-factor authentication or multi-factor authentication. Instead of using just a password, at least one other means of authentication is required. Users of this technology obtain this additional authentication factor via their smartphone or a special hardware device (called a “token”). The common point between most of these additional factors is that they are unique and valid only for a short time – in other words, a time-based one-time password is generated. Let’s take a look at how that works.

Why do we need a TOTP?

Conventional passwords – however strong the user makes them – have a disadvantage: if somebody else knows the character string, security is no longer guaranteed. One solution would be to change passwords regularly, but even the most exemplary users do not do this every hour. The solution is a TOTP: a password which is only valid for a brief time, after which it expires. The Internet Engineering Task Force (IETF) published the one-time password algorithm in 2011 in RFC 6238 to facilitate greater online security.

One-time passwords are mostly used as part of multi-factor authentication, a security system which requires users signing into a web service to first enter their personal, static password, and then a time-limited password generated especially for this sign-in. The user receives the second password via an app or a special hardware token.

Once the one-time password has been used, or if it has not been used after a specified time, it expires. It is therefore very difficult for criminals to obtain the second factor, as even if they know the static password, it's very hard for them to obtain the TOTP too, especially as they have barely any time to crack it.

How does the time-based one-time password algorithm work?

The TOTP is based on a hash function, which is a cryptographic procedure whereby a secret key and a time stamp are combined to form an encrypted character string. Both the user and the server know the secret key. The time stamp is given in Unix time.


Unix time is a value corresponding to the number of seconds that have passed since January 1, 1970.

TOTP is in fact a further development of HOTP, which stands for HMAC-based one-time password. Like HOTP, TOTP is based on the HMAC procedure – the hash operation in the background. Both the user’s device and the server generate a hash value by combining the secret key with a counter. The two values are identical, which is how the authentication works.

The hash function itself is not defined; in practice SHA-1 is often used (including by Google Authenticator, for example). SHA-1 generates a 160-bit hash value. For convenience, this value is truncated using a compression function. The final result is a short number (six digits for example) which the user can easily use to sign in to the web service.


The secret key is embedded in a token in the device, meaning that often even the user doesn’t know it. If this is not the case, the secret key must be stored securely, ideally offline, or even printed and kept in a safe place for example. If the user loses the secret key, they will no longer be able to sign in to the service.

For the second part of the function, HOTP uses a counter, and this is shared by the server and the user. The problem with this is that the generated code remains valid until it is used. TOTP restricts this: the generated code can only be used within a defined time frame. How does this work?

For the time-based one-time password algorithm, there are three important formulas:

TOTP = HOTP(SecretKey,CurrentTime)

This basic formula simply defines that the TOTP is a HOTP procedure with two parameters – SecretKey and CurrentTime:

  • SecretKey: Randomly generated password, known to both the server and the client
  • CurrentTime: Current time in Unix time

However, this time value changes every second, which doesn’t leave the user long enough to enter the generated code. In other words, one second later, the TOTP is no longer valid, because the server has already generated a new hash value. A further formula is therefore required:

CurrentTime = floor((unixtime(now) – unixtime(T0))/T1)

The CurrentTime parameter is defined as follows:

  • unixtime(now): Current time in Unix time
  • unixtime(T0): Unix time at T0, the point from which the time steps are counted – in most cases midnight on January 1, 1970 (=0)
  • T1: The period for which the TOTP will be valid (usually 30 seconds)
  • floor: Rounding function to round the calculated value down to a whole number

In theory, T0 can take any value, not necessarily 0. The important thing is that the client and the server select the same value.

The effect of dividing and rounding is that the result changes at defined intervals.

Next, the generated hash value is truncated to make it more user-friendly.

Result = TOTPmod10d

The modulo operation generates a checksum:

  • mod 10: Modulo with divisor = 10
  • d: Desired number of digits of the TOTP

In other words, the base (10) is raised to the desired number of digits, then the TOTP is divided by this value and the remainder is extracted.

Example of a TOTP calculation

Let us assume that we want to generate a TOTP which is valid for 30 seconds. We can start by calculating the CurrentTime and determining how long the validity will be guaranteed for. For the unixtime(now), let us take 1548322860, i.e. 10:41 a.m. on January 24, 2019. If we divide this value by 30, we get exactly 51610762. Because this is already a whole number, rounding would give the same result. However, if we set the CurrentTime 15 seconds later (i.e. 1548322875), after dividing, the result is 51610762.5. After rounding, the value is 51610762, as before. The CurrentTime therefore remains the same. The following table shows that a new value is only generated every 30 seconds.

unixtime(now) unixtime(now)/30 floor(unixtime(now)/30)
1548322857 51610761.9000 51610761
1548322858 51610761.9333 51610761
1548322859 51610761.9667 51610761
1548322860 51610762.0000 51610762
1548322861 51610762.0333 51610762
1548322862 51610762.0667 51610762
1548322863 51610762.1000 51610762
1548322864 51610762.1333 51610762
1548322865 51610762.1667 51610762
1548322866 51610762.2000 51610762
1548322867 51610762.2333 51610762
1548322868 51610762.2667 51610762
1548322869 51610762.3000 51610762
1548322870 51610762.3333 51610762
1548322871 51610762.3667 51610762
1548322872 51610762.4000 51610762
1548322873 51610762.4333 51610762
1548322874 51610762.4667 51610762
1548322875 51610762.5000 51610762
1548322876 51610762.5333 51610762
1548322877 51610762.5667 51610762
1548322878 51610762.6000 51610762
1548322879 51610762.6333 51610762
1548322880 51610762.6667 51610762
1548322881 51610762.7000 51610762
1548322882 51610762.7333 51610762
1548322883 51610762.7667 51610762
1548322884 51610762.8000 51610762
1548322885 51610762.8333 51610762
1548322886 51610762.8667 51610762
1548322887 51610762.9000 51610762
1548322888 51610762.9333 51610762
1548322889 51610762.9667 51610762
1548322890 51610763.0000 51610763
1548322891 51610763.0333 51610763

Our CurrentTime is therefore established (51610762). We now use a password generator to obtain the SecretKey: >cHSB_UQ#O5m;~b

HMAC (with SHA-1) combines the secret key and the current time to produce a hash value (in hexadecimal format): c0 62 37 94 dd 37 7a 3a f0 91 22 08 1f 21 6f 9b 17 4b 17 45. This 160-bit (20 byte) value is truncated to 31 bits using what is known as dynamic truncation. This involves performing the following steps: First, the last 4 bits are considered. In our example, this is the number 0x5, which can also be written as 5 in decimal notation. This gives the offset value to be used for dynamic truncation, and means that starting from the byte with index 5, we must extract four bytes (read from the left, starting at 0): 0x377a3af0. In this example our value already starts with a bit equal to 0. If this is not the case, it must be changed accordingly. The 31-bit value here is thus: 0x377a3af0, or 930757360.

To reduce this 9-digit string to 6 digits, we use a modulo operation, padding the result with leading zeros if necessary: 930757360 mod (106) = 757360. This is now the TOTP, which is valid for 30 seconds. In combination with another factor, this makes the sign-in procedure fairly secure.