# How random are TOTP codes?

I'm pretty sure that the 2FA codes generated by my bank's TOTP app have a bias towards the number 8 - because eight is an auspicious number.

But is that just my stupid meaty brain noticing patterns where none exist?

The TOTP algorithm uses HMAC, which in turn uses SHA-1. My aforementioned brain is not clever enough to understand how that works. Although bigger, meatier brains have assured me it is fine.

What happens if I sample, say, the next 10 TOTP codes and plot how often digits appear?

HOLY SHIT! CONSPIRACY CONFIRMED! WTAF?!?!?

Don't believe me? Here's the code:

``````import pyotp
import numpy as np
import matplotlib.pyplot as plt

totp = pyotp.TOTP('')

#   How many times to run this?
runs = 10

#   Initialize a NumPy array with shape to store the digits
digits_array = np.zeros( ( runs, 6), dtype=int)

#   Generate the digits
for i in range( runs ):
number_str = totp.at( i * 30 )
for j in range(6):
digits_array[i, j] = int(number_str[j])

#   Analyse the entire array
all_digits = digits_array.flatten()

# Plot histogram for all digits
plt.figure()
plt.hist(all_digits, bins=np.arange(11) - 0.5, edgecolor='black', density=True)
plt.xticks(range(10))
plt.title('Digit Distribution for All Digits (' + f"{runs:,}" + ' runs)')
plt.xlabel('Digit')
plt.ylabel('Frequency')
plt.show()``````

OK, so maybe that's a coincidence. What happens if we check 100 generations?

Quite a lot of noise in there - but lucky number 8 isn't quite as prominent.

After 10,000 generations, the variation is all but gone.

There are about 30 million seconds in a year. TOTP codes change every 30 seconds. Which means, in a year, you'll see about a million of them:

Is it possible that a TOTP code could be formed which shows a clear bias to a specific number? Probably not.

I love being able to check the source code - but sometimes it's just as reassuring to measure the output.