Click here to Skip to main content
Click here to Skip to main content

OTP (One Time Password) Demystified - Part 1

By , 13 May 2013
 

Introduction

At the beginning of 2004, I was working with a small team of Gemplus on the EAP-SIM authentication protocol. As we were a bit ahead of the market, our team was reassigned to work with a team of Verisign on a new authentication method: OTP or One Time Password.

At this time, the existing one time password was a token from RSA that was using a clock to synchronize the passwords.

The lab of Versign came with a very simple but I should say very smart concept. The OTP that you may be using with your bank or Google was born.

This is this algorithm and authentication method I describe in the following two articles. In this article, I present a complete code of the OTP generator. It is very similar to the Javacard Applet I wrote in 2004 when I started to work on this concept with the Versign labs.

The One Time Password Generator

This OTP is based on the very popular algorithm HMAC SHA. The HMAC SHA is an algorithm generally used to perform authentication by challenge response. It is not an encryption algorithm but a hashing algorithm that transforms a set of bytes to another set of bytes. This algorithm is not reversible which means that you cannot use the result to go back to the source.

A HMAC SHA uses a key to transform an input array of bytes. The key is the secret that must never be accessible to a hacker and the input is the challenge. This means that OTP is a challenge response authentication.

The secret key must be 20 bytes at least; the challenge is usually a counter of 8 bytes which leaves quite some time before the value is exhausted.

The algorithm takes the 20 bytes key and the 8 bytes counter to create a 8 digits number. This means that there will obviously be duplicates during the life time of the OTP generator but this doesn't matter as no duplicate can occur consecutively and an OTP is only valid for a couple of minutes.

Why is the OTP a very strong authentication method?

There are few reasons why this is a very strong method.

  • The key is 20 digits
  • A password is a couple counter/password, only valid once and a very short time
  • The algorithm that generates each password is not reversible
  • With an OTP token, the key is hardware protected
  • If the OTP is received on your phone, the key always stays at the server

Those few characteristics make the OTP a strong authentication protocol. The weakness in an authentication is usually the human factor. It is difficult to remember many complex passwords, so users often use the same one all across the internet and not really a strong one. With an OTP, you don't have to remember a password, the most you would have to remember would be PIN code (4 to 8 digits) if the OTP token is PIN protected. In the case of an OTP sent by a mobile phone, it is protected by your phone security. A PIN is short but you can't generally try it more than 3 times before the token is locked.

The weakness of an OTP if there is one, is the media used to generate or receive the OTP. If the user loses it, then the authentication could be compromised. A possible solution would be to protect this device with a biometric credential, making it virtually totally safe.

The code of the OTP generator follows:

public class OTP
{
    public const int SECRET_LENGTH = 20;
    private const string
	MSG_SECRETLENGTH = "Secret must be at least 20 bytes",
	MSG_COUNTER_MINVALUE = "Counter min value is 1";

    public OTP()
    {
    }

    private static int[] dd = new int[10] { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }; 

    private byte[] secretKey = new byte[SECRET_LENGTH] 
    {
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43
    };

    private ulong counter = 0x0000000000000001;

    private static int checksum(int Code_Digits) 
    {
	int d1 = (Code_Digits/1000000) % 10;
	int d2 = (Code_Digits/100000) % 10;
	int d3 = (Code_Digits/10000) % 10;
	int d4 = (Code_Digits/1000) % 10;
	int d5 = (Code_Digits/100) % 10;
	int d6 = (Code_Digits/10) % 10;
	int d7 = Code_Digits % 10;
	return (10 - ((dd[d1]+d2+dd[d3]+d4+dd[d5]+d6+dd[d7]) % 10) ) % 10;
    }

    /// <summary>
    /// Formats the OTP. This is the OTP algorithm.
    /// </summary>
    /// <param name="hmac">HMAC value</param>
    /// <returns>8 digits OTP</returns>
    private static string FormatOTP(byte[] hmac)
    {
	int offset =  hmac[19] & 0xf ;
	int bin_code = (hmac[offset]   & 0x7f) << 24
		| (hmac[offset+1] & 0xff) << 16
		| (hmac[offset+2] & 0xff) <<  8
		| (hmac[offset+3] & 0xff) ;
	int Code_Digits = bin_code % 10000000;
	int csum = checksum(Code_Digits);
	int OTP = Code_Digits * 10 + csum;

	return string.Format("{0:d08}", OTP);
    }

    public byte[] CounterArray
    {
	get
	{
	    return BitConverter.GetBytes(counter);
	}

	set
	{
	    counter = BitConverter.ToUInt64(value, 0);
	}
    }

    /// <summary>
    /// Sets the OTP secret
    /// </summary>
    public byte[] Secret
    {
	set
	{
	    if (value.Length < SECRET_LENGTH)
	    {
		throw new Exception(MSG_SECRETLENGTH);
	    }

	    secretKey = value;
	}
    }

    /// <summary>
    /// Gets the current OTP value
    /// </summary>
    /// <returns>8 digits OTP</returns>
    public string GetCurrentOTP()
    {
	HmacSha1 hmacSha1 = new HmacSha1();

	hmacSha1.Init(secretKey);
	hmacSha1.Update(CounterArray);
		
	byte[] hmac_result = hmacSha1.Final();

	return FormatOTP(hmac_result);
    }

    /// <summary>
    /// Gets the next OTP value
    /// </summary>
    /// <returns>8 digits OTP</returns>
    public string GetNextOTP()	
    {
	// increment the counter
	++counter;

	return GetCurrentOTP();
    }

    /// <summary>
    /// Gets/sets the counter value
    /// </summary>
    public ulong Counter
    {
	get
	{
	    return counter;
	}

	set
	{
	    counter = value;
	}
    }
}

The methods FormatOTP() and checksum() are the heart of the OTP algorithm. Those methods transform the result of the hmacsha into an 8 digits OTP.

The attached code also contains an implementation of the HMAC SHA algorithm. It is of course possible to use the standard hmacsha of the .NET Framework but the code I provide in fact used a demo in a prototype of smart card that was running a .NET CLR. At the time I wrote this code, the cryptography namespace was not yet implemented by the card.

This way, you can also see how a hmacsha algorithm is implemented.

The OTP Server and Authentication Protocol

An OTP authentication can be done in 2 ways. Using an OTP token or receiving an OTP number on your mobile. In both cases, there is in the back-end an OTP server.

In a second article, I will describe how this OTP server works and is able to resynchronize if you enter some wrong OTP code or use your OTP token without verifying the code with the server.

Getting the Source

You can get the source code of the project from the ZIP files attached to the article or you can follow it on github where it will be updated regularly as this is a public repository.

Points of Interest

OTP is a popular and quite simple authentication method; I hope those articles will help you understand how it works behind the scenes.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

orouit
Architect Consistel - Singapore
Singapore Singapore
Member
Software Architect, COM, .NET and Smartcard based security specialist.
 
I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I preferred digital to analog.
 
I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.
 
For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when things don't go right!
 
After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small computers! I'm currently back in the business to design the licensing system for the enterprise solution I'm currenly working on, using a .NET smart card (yes they can run .NET CLR!)
 
View my profile on LinkedIn
 
You can contact me for professional consulting by using the forum.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130513.1 | Last Updated 13 May 2013
Article Copyright 2013 by orouit
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid