How Google Authenticator Works Under The Hood
A Deep Dive Into Google Authenticator & Coding It From Scratch

Traditional authentication methods use username and password to login to accounts/ access funds.
But, Passwords are not secure enough as a single point of failure (password leak) can compromise your account.
Hence, the practice of 2-Factor Authentication (2FA) became popular.
What Is 2-Factor Authentication?
Two-factor authentication (2FA) is a method of confirming a user’s identity by using a combination of two different factors:
1. Something You Know
This could be a password, a PIN, or answers to secret questions.
2. Something You Have
This could be a physical object (card/ fob), or a trusted device like a smartphone where an authentication app is installed or to which a code containing SMS can be sent.
Or
2. Something You Are
These are biometrics like fingerprints, voice patterns, or iris scans.
The Issue With SMS-Based 2-Factor Authentication
SMS-based 2FA sounds convenient but comes with its own risks.
An attacker can intercept the SMS messages containing the 2FA codes (called a Man-in-the-middle attack).
They can also use a device known as a Stingray (IMSI catcher) to mimic a cell tower and intercept mobile traffic.
This can compromise your account’s security.
These problems are mitigated by using Authentication apps like Google Authenticator/ Authy.
How Does Google Authenticator Works?
The basic online on how Google Authenticator works is as follows:
1. Secret Key Generation
The service that hosts your account generates a random and unique key.
This key is shown as a secret key or in the form of a QR code.
2. Setup With Google Authenticator
You scan this QR code with the Google Authenticator app and the secret key is transferred to the app without it ever being exposed.
In this way, the service’s server and your Google Authenticator app share a common secret key.
3. OTP Generation
Every time you log into the service, Google Authenticator uses this secret key and the current time to generate a Time-Based One-Time Password (TOTP).
4. OTPÂ Input
You input this OTP on the service’s login page as a second form of verification along with your password.
5. OTP Verification
The service, which also holds a copy of the secret key, generates its own OTP and checks if it matches the one you inputted.Â
If they match, it confirms that you have access to the secret key and thus verifies your identity.
You are logged in to your account once the authentication is successfully performed.
Deep Dive
Let’s learn in detail how this happens.
1. Secret Key Generation
The service’s server generates a secret key using a Cryptographically Secure Pseudorandom Number Generator (CSPRNG), which produces random numbers suitable for cryptographic uses.
Some CSPRNGs are:Â
Fortuna
Yarrow
ChaCha20
In Python, this can be done using the secrets
module as follows.
The secrets
module uses the os.urandom()
function for generating cryptographically secure random numbers.
import secrets
import base64
def generate_secret_key():
# Generate Secret Key (20 random bytes)
secret_key_bytes = secrets.token_bytes(20)
# Convert the bytes to a base32 string
secret_key_base32 = base64.b32encode(secret_key_bytes).decode('utf-8')
# Remove the padding characters ('=') from the base32 string
secret_key_base32 = secret_key_base32.rstrip('=')
return secret_key_base32
# Generate the secret key
secret_key = generate_secret_key()
print(secret_key)
#Output: EPZXTXE5OBYM4QAA6LA2ZZ4AAQZFEB7N
2. Generation of Authentication URI & QRÂ Code
An authentication URI is generated using the secret key.
This is in the following format:
otpauth://TYPE/LABEL?PARAMETERS
In the above:
TYPE
is eitherhotp
ortotp
, indicating the type of OTP algorithm usedLABEL
is used to identify which account the secret key is associated withPARAMETERS
is a set of parameters in the form of key-value pairs required by the OTP algorithm.
The URI generation can be performed in Python using the pyotp
library.
We will discuss TOTP soon.
import pyotp
# Generate a TOTP object with the secret key
totp = pyotp.TOTP(secret_key)
# Generate the otpauth URL
otpauth_url = totp.provisioning_uri(name='ashish@example.com', issuer_name='SecureApp')
print(otpauth_url)
#Output: otpauth://totp/SecureApp:ashish%40example.com?secret=EPZXTXE5OBYM4QAA6LA2ZZ4AAQZFEB7N&issuer=SecureApp
This URI is then converted into a QR code.
This is done in Python using the qrcode
library.
import qrcode
# Generate the QR code
qr_code = qrcode.make(otpauth_url)
# Save the QR code as a PNG file
qr_code.save('qrcode.png')
This QR code is scanned by the user’s smartphone using the Google Authenticator app.
After this step, both the service’s server and the user’s Google Authentication app share the secret key.Â
Both also agree on a time step value for which an OTP will remain valid (usually 30 or 60 seconds).Â
3. Generating Time-Based One-Time Password (TOTP)
The Time-Based One-Time Password (TOTP) Algorithm is used to generate a one-time password as follows.
A. Convert the Secret key To Bytes
The secret key in the form of a base32 string is converted back to bytes.
Note that padding characters (=
) are added to the end of the secret key to make its length a multiple of 8, which is necessary for base32 decoding.
B. Generate the input for the algorithmÂ
The TOTP algorithm uses the current time to generate the one-time password.Â
The current Unix timestamp (the number of seconds since 1970–01–01 00:00:00 UTC) is divided by the time step value (say 30 seconds), and the result is converted into bytes. This is called the Counter.
C. Calculate the HMAC-SHA1 hashÂ
Calculate an HMAC-SHA1 value using the secret key and the Counter as input.Â
D. Extract a 4-byte value from the hash
A 4-byte (32-bit) value is obtained from the HMAC result at random indexes.
This is done by calculating an offset using the bitwise AND operation between the last byte of the HMAC-SHA1 hash and the hexadecimal number 0xf
which is 15
in decimal and 1111
in binary.
This results in a value between 0 and 15.
The 4 bytes starting at this offset are taken from the HMAC-SHA1 hash.
This adds more randomness to the process of OTP generation.
E. Convert the 4-byte value to a number
The 4-byte value is converted to a big-endian unsigned integer.
F. Reduce the number to the desired number of digits
The resulting number is quite large to be convenient for a one-time password.Â
It is shortened by taking the number modulo 10^d
, where d
is the desired number of digits (for example 6
).
This can be done in Python as follows:
import base64
import hmac
import time
import struct
def generate_totp(secret_key_base32, timestamp, time_step=30, digits=6):
# Add padding characters to the end of the string, if necessary
while len(secret_key_base32) % 8 != 0:
secret_key_base32 += '='
# Convert the secret key to bytes
secret_key_bytes = base64.b32decode(secret_key_base32)
# Calculate the counter from the timestamp
counter = int(timestamp / time_step)
counter_bytes = struct.pack('>q', counter) # '>q' means an 8-byte big-endian integer
# Calculate the HMAC value
hmac_value = hmac.new(secret_key_bytes, counter_bytes, digestmod='sha1').digest()
# Extract a 4-byte value from the HMAC value
offset = hmac_value[19] & 0xf
four_bytes = hmac_value[offset:offset+4]
# Convert the 4-byte value to a number
number = struct.unpack('>L', four_bytes)[0] # '>L' means a 4-byte big-endian unsigned long integer
# Reduce the number to the desired number of digits
otp = number % (10 ** digits)
return otp
secret_key = 'EPZXTXE5OBYM4QAA6LA2ZZ4AAQZFEB7N' #Secret Key
timestamp = int(time.time()) # The current time
print(generate_totp(secret_key, timestamp))
#Output: 294307
4. Verification of OTP
The OTP is input by the user when logging into their account.
The service’s server performs the above calculations using the timestamp and the secret key.
If the result matches with the input OTP, the user is verified and logged in.

And, that’s how Google Authenticator works under the hood!