One-Time Passwords
And How To Implement Them Using HMAC
By Sahand Saba / sahandsaba.com
Motivation
Problem of Authentication
-
Alice sends Bob message $m$.
-
Alice is the originator.
-
Bob is the receiver.
-
Authentication is confirming the identity of the orignator.
-
I.e. Bob wants to know originator is truly Alice.
Authentication Factors
Knowledge
Something the user knows. Can be static or dynamic.
-
Password (Static)
-
Birthdate (Static)
-
First car's model (Static)
-
Friends' faces (Dynamic)
-
Last payment made (Dynamic)
Authentication Factors
Ownership
Something the user owns.
-
Badge
-
ID card
-
USB key
-
Cellphone
-
Etc.
Authentication Factors
Inherence
Something inherent to the user.
-
DNA
-
Fingerprint
-
Face
-
Etc.
Password-Based Authentication
Advantages
-
Simple to implement
-
No specialized hardware required
Password-Based Authentication
Weaknesses - Part I
Passwords are static knowledge factors.
-
Guessed
-
Stolen
-
Found by brute-force
-
Found by social engineering (e.g. phishing)
Password-Based Authentication
Weaknesses - Part II
Passwords are often implemented incorrecty. Case in point:
Source: Sophos Security, based on Adobe's 153-million user database leak
Password-Based Authentication
Weaknesses - Part III
And related XKCD:
Source: xkcd.com
Two-Factor Authentication
Use two factors instead of one for authentication.
Two common implementations are:
-
Secret questions
-
One-time passwords
Secret Questions
Weaknesses
Secret questions are also static knowledge factors.
-
Guessing
-
Brute-force search
-
Social engineering (e.g. "Find out your superhero name!")
Motivation
Conclusions
-
Passwords alone are insecure.
-
Secret questions are insecure second factors.
One-Time Passwords
Advantages and Disadvantages
-
Introduce an ownership factor.
-
Considered to be more secure than secret questions.
-
Downside: Conventionally require specialized hardware.
One-Time Passwords
Example Hardware I
HSBC One-Time Password Hardware
One-Time Passwords
Example Hardware II
YubiKeys - Offered by YubiCo
One-Time Passwords
Solutions Without Specialized Hardware
-
Specialized hardware can be costly and inconvenient
-
Solution: Cellphones
-
Users almost always have them
-
Provide alternative communication channel: phone calls and SMS
One-Time Passwords
Example Hardware III
Google Authenticator Running on Cellphones
One-Time Passwords
Basic Protocal
-
Bob generates a random one-time password (OTP).
-
Bob sends Alice the OTP.
-
Alice uses the OTP for authentication.
-
Security relies on a "verified" channel of communication, e.g. SMS, phone call, or physically giving the hardware to the user.
-
Used by Facebook.
One-Time Passwords
Alternative Protocal
-
Alice and Bob share a secret key
-
Pseudorandom function (PRF) used to generate OTP
-
Input to PRF is shared key and a synchronization value.
One-Time Passwords
Synchronization Modes
Two common ways to synchronize the OTP's:
Hash-based One-Time Passwords (HOTP)
Counter-Based - RFC 4226
-
HMAC-SHA-1 as the pseudorandom function
-
Counter-based OTP generation
-
OTP is generated as $$Truncate(Hash(k \| C))$$
-
Counter value $C$ incremented after each generation
-
$Truncate$ extracts $D$ decimal digits from HMAC's output
-
RFC standard provides a mechanism for re-synchronization
Time-based One-Time Passwords (TOTP)
Time-Based - RFC 6238
-
Based off of HOTP
-
OTP is generated as $$Truncate(Hash(k \| T))$$
-
With
$$ T = \left \lfloor \frac{T_{current} - T_0}{X} \right \rfloor$$
-
$X$ determines how long OTP is valid for
-
Recommended value for $X$ is 30 seconds
Time-based One-Time Passwords (TOTP)
Time-Based - RFC 6238
Python implementation of OTP generation, taken from pyotp:
def generate_otp(self, input):
"""
@param [Integer] input the number used seed the HMAC
Usually either the counter, or the computed integer
based on the Unix timestamp
"""
hmac_hash = hmac.new(
self.byte_secret(),
self.int_to_bytestring(input),
self.digest,
).digest()
offset = ord(hmac_hash[19]) & 0xf
code = ((ord(hmac_hash[offset]) & 0x7f) << 24 |
(ord(hmac_hash[offset + 1]) & 0xff) << 16 |
(ord(hmac_hash[offset + 2]) & 0xff) << 8 |
(ord(hmac_hash[offset + 3]) & 0xff))
return code % 10 ** self.digits
Demo!
Python and Flask on Heroku + Google Authenticator
Finally, here is a example of implementing TOTP-based
authentication using Python running on Heroku.
Here it is!
Thank you
By Sahand Saba / sahandsaba.com