<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc toc="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc sortrefs="yes"?>
<?rfc iprnotified="no" ?>
<?rfc strict="no" ?>
<?rfc compact="yes" ?>
<?rfc subcompact="yes" ?>
<rfc category="info" docName="draft-mraihi-totp-timebased-08.txt" ipr="trust200902" submissionType="IETF">
  <front>
    <title abbrev="HOTPTimeBased">TOTP: Time-based One-time Password Algorithm</title>
    <author fullname="David M'Raihi" initials="D." surname="M'Raihi">
      <organization>Verisign, Inc.</organization>
      <address>
        <postal>
          <street>685 E. Middlefield Road</street>
          <city>Mountain View</city>
          <region>CA</region>
          <code>94043</code>
          <country>USA</country>
        </postal>
        <email>davidietf@gmail.com</email>
      </address>
    </author>
    <author fullname="Salah Machani" initials="S." surname="Machani">
      <organization>Diversinet Corp.</organization>
      <address>
        <postal>
          <street>2225 Sheppard Avenue East, Suite 1801</street>
          <city>Toronto</city>
          <region>Ontario</region>
          <code>M2J 5C2</code>
          <country>Canada</country>
        </postal>
        <email>smachani@diversinet.com</email>
      </address>
    </author>
    <author fullname="Mingliang Pei" initials="M." surname="Pei">
      <organization>Symantec</organization>
      <address>
        <postal>
          <street>510 E. Middlefield Road</street>
          <city>Mountain View</city>
          <region>CA</region>
          <code>94043</code>
          <country>USA</country>
        </postal>
        <email>Mingliang_Pei@symantec.com</email>
      </address>
    </author>
    <author fullname="Johan Rydell" initials="J." surname="Rydell">
      <organization>Portwise, Inc.</organization>
      <address>
        <postal>
          <street>275 Hawthorne Ave, Suite 119</street>
          <city>Palo Alto</city>
          <region>CA</region>
          <code>94301</code>
          <country>USA</country>
        </postal>
        <email>johan.rydell@portwise.com</email>
      </address>
    </author>    
    <date day="24" month="February" year="2011" />
    <area>General</area>
    <workgroup>Internet Engineering Task Force</workgroup>
    <abstract>
      <t>This document describes an extension of one-time password (OTP) algorithm, namely
      the HMAC-Based One-Time Password (HOTP) Algorithm as defined in RFC 4226,  
      to support time-based moving factor. The HOTP algorithm specifies an event
      based OTP algorithm where the moving factor is an event counter. The present work 
      bases the moving factor on a time value.  A time-based variant of the OTP algorithm 
      provides short-lived OTP values, which are desirable for enhanced security.</t>
      
      <t>The proposed algorithm can be used across a wide range of network applications ranging from 
      remote Virtual Private Network (VPN) access, Wi-Fi network logon to transaction-oriented Web
      applications. The authors believe that a common and shared algorithm will facilitate adoption of 
      two-factor authentication on the Internet by enabling interoperability across commercial and 
      open-source implementations.</t>
    </abstract>
  </front>

  <middle>
    <!-- ////////////////////////////////////////////////////////////////////////////////// -->

    <section anchor="Section-Introduction" title="Introduction">
      <section title="Scope">
        <t>This document describes an extension of one-time password 
        (OTP) algorithm HMAC-Based One-Time Password (HOTP) as defined in <xref target="RFC4226"></xref> 
        to support time based moving factor.
        </t>
      </section>

      <section title="Background">
        <t>As defined in <xref target="RFC4226"></xref> the HOTP algorithm is based on the HMAC-SHA-1 algorithm, 
        as specified in <xref target="RFC2104"></xref> applied to an increasing counter value representing the message in the HMAC computation.</t>
        <t>Basically, the output of the HMAC-SHA-1 calculation is truncated to obtain user-friendly values:</t>
        <t>HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))</t>
        <t>where Truncate represents the function that can convert an HMAC-SHA-1 value into an HOTP value. 
        K and C reprensent the shared secret and counter value, see <xref target="RFC4226"></xref> for their detail definition. <vspace blankLines="1" /></t>        
        <t>TOTP is the time-based variant of this algorithm where a value T derived from a time reference and a time step 
        replaces the counter C in the HOTP computation.</t>
        <t>TOTP implementations MAY use HMAC-SHA-256 or HMAC-SHA-512 functions, based on SHA-256 or
        SHA-512 [SHA2] hash functions, instead of HMAC-SHA-1 function that has been specified for HOTP
        computation in <xref target="RFC4226"></xref>.</t>              
      </section>
    </section>

    <!-- ////////////////////////////////////////////////////////////////////////////////// -->

    <section anchor="terms" title="Notation and Terminology">
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
      "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
      document are to be interpreted as described in <xref target="RFC2119"></xref></t>
    </section>

    <section anchor="AlgorithmRequirements" title="Algorithm Requirements">
                
          <t> This section summarizes the requirements taken into account for designing the TOTP algorithm. </t>        
        <t> R1 - The prover (e.g. token, soft token) and verifier (authentication or validation server) MUST know or be able to derive the current Unix time (i.e. the number of seconds elapsed since midnight UTC of January 1, 1970) for OTP generation. See [UT] for more detail definition of the commonly known "Unix time". The precision of the time used by the prover affects how often the clock synchronization should be done, see Section 6.</t>
        <t> R2 - The prover and verifier MUST either share a same secret or the knowledge of a secret transformation to generate a shared secret </t>
        <t> R3 - The algorithm MUST use HOTP [RFC4226] as a key building block. </t>
        <t> R4 - The prover and verifier MUST use the same time step value X. </t>
        <t> R5 - There MUST be a unique secret (key) for each prover. </t>
        <t> R6 - The keys SHOULD be randomly generated or derived using a key derivation algorithms. </t>
        <t> R7 - The keys MAY be stored in a tamper-resistant device and SHOULD be protected against unauthorized access and usage. </t>
      
    </section>

    <!-- ////////////////////////////////////////////////////////////////////////////////// -->
   
    <section anchor="Section-Time-based-Variant" title="TOTP Algorithm">

        <t>This variant of the HOTP algorithm specifies the calculation of a one-time 
        password value, based on a representation of the counter as a time factor.</t>

        <section anchor="Notations" title="Notations">
            <t>- X represents the time step in seconds (default value X = 30 seconds) and is a system parameter;</t>
            <t>- T0 is the Unix time to start counting time steps (default value is 0, Unix epoch) and is also a system parameter.</t>
        </section>

        <section title="Description">
            <t> Basically, we define TOTP as TOTP = HOTP(K, T) where T is an integer and represents the number of time steps between 
            the initial counter time T0 and the current Unix time.</t>
            <t> More specifically T = (Current Unix time - T0) / X where:</t>
            <t>- X represents the time step in seconds (default value X = 30 seconds) and is a system parameter.</t>
            <t>- T0 is the Unix time to start counting time steps (default value is 0, Unix epoch) and is also a system parameter;</t>
            <t>- The default floor function is used in the computation. For example, with T0 = 0 and time step X = 30, T = 1 if the current 
            Unix time is 59 seconds and T = 2 if the current Unix time is 60 seconds.</t>
            <t>The implementation of this algorithm MUST support the time value T larger than 32-bit integer when it is beyond year 2038. 
            The value of the system parameters X and T0 are pre-established during the provisioning process and communicated 
            between a prover and verifier as part of the provisioning step. The provisioning flow is out of scope of this document, 
            refer to [RFC6030] for such provisioning container specification.</t>
        </section>
   
    </section>
    
    <!-- ////////////////////////////////////////////////////////////////////////////////// -->

    <section anchor="Section-Security" title="Security Considerations">
      <section title="General">
  
    <t> The security and strength of this algorithm depends on the 
    properties of the underlying building block HOTP, which is a 
    construction based on HMAC <xref target="RFC2104"></xref> using
    SHA-1 as the hash function. </t> 
     
    <t> The conclusion of the security analysis detailed in 
    <xref target="RFC4226"></xref> is that, for all practical 
    purposes, the outputs of the dynamic truncation on distinct 
    inputs are uniformly and independently distributed strings. </t>
     
    <t> The analysis demonstrates that the best possible attack against the 
    HOTP function is the brute force attack. </t>

    <t> As indicated in the algorithm requirement section, keys SHOULD be 
    chosen at random or using a cryptographically strong pseudo-random 
    generator properly seeded with a random value. </t> 
    
    <t> Keys SHOULD be of the length of the HMAC output to facilitate
    interoperability. </t>
    
    <t> We RECOMMEND following the recommendations in 
    <xref target="RFC4086"></xref> for all pseudo-random and 
    random generations. The pseudo-random numbers used for
    generating the keys SHOULD successfully pass the 
    randomness test specified in <xref target="CN"></xref> or
    a similar well-recognized test. </t>
     
    <t> All the communications SHOULD take place over a secure 
    channel e.g. SSL/TLS [RFC5246], IPsec connections [RFC4301]. </t>
  
    <t> We also RECOMMEND storing the keys securely in the 
    validation system, and more specifically encrypting them using 
    tamper-resistant hardware encryption and exposing them only when 
    required: for example, the key is decrypted when needed to verify 
    an OTP value, and re-encrypted immediately to limit exposure in 
    the RAM for a short period of time. </t>
    
    <t> The key store MUST be in a secure area, to avoid as much as possible 
    direct attack on the validation system and secrets database. 
    Particularly, access to the key material should be limited to programs 
    and processes required by the validation system only. </t>
     
    </section>

      <section title="Validation and Time-step Size">
         <t>An OTP generated within the same Time-step will be the same.  
            When an OTP is received at a validation system, it doesn't 
            know a client's exact timestamp when an OTP was generated. The
            validation system may typically use the timestamp when an OTP is 
            received for OTP comparison. Due to the network latency for an OTP
            to transmit from a requesting application to a validation system
            and user's actual input time of an OTP to a receiving system, such
            timestamp gap between the actual OTP generation time and server's
            receiving time may be large. The receiving time at the validation
            system and the actual OTP generation may not fall within the 
            same Time-step window that produce the same OTP. When an OTP
            is generated at the end of a Time-step window, the receiving time
            most likely falls into the next Time-step window. 
            A validation system SHOULD typically set a policy for an 
            acceptable OTP transmission delay window for validation. 
            The validation system should compare OTPs not only with the 
            receiving timestamp but also the past timesteps that are 
            within the transmission delay. A larger acceptable delay window
            would introduce some OTP attack window. We RECOMMEND that 
            at most one time step is allowed as the network delay. </t>

          <t>The Time-step size has impact on both security and usability.
            A larger Time-step size means larger validity window for an OTP
            to be accepted by a validation system. There are the following
            implications with a larger Time-step size.</t>

         <t>At first, a larger Time-step size exposes larger window for
            attack. When an OTP is generated and exposed to a third party
            before it is consumed, the third party can consume the OTP within
            the Time-step window.</t>

         <t>We RECOMMEND default Time-step size for 30 seconds. This default value of 30 
         seconds is selected to balance between security and usability.</t>

         <t>Secondly, the next different OTP must be generated in the next 
            Time-step window. A user must wait till the clock moves to the
            next Time-step window from the last submission. The waiting time
            may not be exactly the length of Time-step depending on when
            the last OTP was generated. For example, if the last OTP was 
            generated at the half way in a Time-step window, the waiting
            time for the next OTP is half of length of Time-step. In general,
            a larger Time-step window means larger waiting time for
            a user to get the next valid OTP after the last successfully 
            OTP validation. A too large window, for example 10 minutes,
            most probably won't be suitable for typical internet login 
            use cases; a user may not be able to get the next OTP within
            10 minutes and therefore re-login back to the same site
            in 10 minutes.</t>
            
      <t>Note that a prover may send the same OTP inside a given time window multiple times to a verifier. 
      The verifier MUST not accept the second attempt of the OTP after the successful validation
      has been issued for the first OTP, which ensures one-time only use of an OTP.</t>
        
      </section>
     
    </section>

     <section title="Resynchronization">
        <t> Because of possible clock drifts between a client and a validation
            server, we RECOMMEND that the validator be set with a specific
            limit to the number of time steps a prover can be 'out of synch' 
            before being rejected.</t>
            
        <t> This limit can be set both forward and backwards from the calculated
            time step on receipt of the OTP value. If the time step is 30 seconds 
            as recommended, and the validator is set to only accept 2 time step 
            backwards then the maximum elapsed time drift would be around 
            89 seconds, i.e. 29 seconds in the calculated time step and 60 for 
            two backward time steps. </t>
            
     <t> This would mean the validator could perform a validation against
         the current time and then further two validations for each backward
            step (for a total of 3 validations). Upon successful validation,
            the validation server can record the detected clock drift for
            the token in terms of number of Time-step. When a new OTP
            is received after this step, the validator can validate the OTP with
            current timestamp adjusted with recorded number of Time-step clock 
            drifts for the token.</t>
           
        <t> Also, it is important to note that the longer a prover has not sent 
            an OTP to a validation system, the longer (potentially) the accumulated 
            clock drift between the prover and the verifier. In such cases, the automatic 
            resynchronization described above may not work if the drift exceeds the 
            allowed threshold. Additional authentication measures should be used to
            safely authenticate the prover and explicitly resynchronize the clock drift 
            between the prover and the validator.</t>
     </section>
    
    <!-- ////////////////////////////////////////////////////////////////////////////////// -->
    
    <section title="IANA Considerations">
      <t>This document has no actions for IANA.</t>
    </section>

    <section anchor="Section-Acknowledgements" title="Acknowledgements">
      <t>The authors of this draft would like to thank the following people
   for their contributions and support to make this a better
   specification: Hannes Tschofenig, Jonathan Tuliani, David Dix, Siddharth Bajaj, 
   Stu Veath, Shuh Chang, Oanh Hoang, John Huang, and Siddhartha Mohapatra.
</t>
    </section>

    <!-- ////////////////////////////////////////////////////////////////////////////////// -->
  </middle>

  <back>
    <references title="Normative references">
      <reference anchor="RFC4226" target="http://www.ietf.org/rfc/rfc4226.txt">
        <front>
          <title>HOTP: An HMAC-Based One-Time Password Algorithm</title>
          <author initials="D." surname="M'Raihi">
            <organization>VeriSign</organization>
          </author>
          <author initials="M." surname="Bellare">
            <organization>UCSD</organization>
          </author>
          <author initials="F." surname="Hoornaert">
            <organization>Vasco</organization>
          </author>
          <author initials="D." surname="Naccache">
            <organization>Gemplus</organization>
          </author>
          <author initials="O." surname="Ranen">
            <organization>Aladdin</organization>
          </author>
          <date month="December" year="2005" />
        </front>
        <seriesInfo name="RFC" value="4226" />
      </reference>

      <reference anchor="RFC4086" target="http://www.ietf.org/rfc/rfc4086.txt">
        <front>
          <title>Randomness Recommendations for Security</title>
          <author initials="D." surname="Eastlake">
            <organization>Motorola Lab</organization>
          </author>
          <author initials="J." surname="Schiller">
            <organization>MIT</organization>
          </author>
          <author initials="S." surname="Crocker">
            <organization/>
          </author>
          <date month="June" year="2005" />
        </front>
        <seriesInfo name="RFC" value="4086" />
      </reference>
      
      <reference anchor="RFC2119" target="http://www.ietf.org/rfc/rfc2119.txt">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement
          Levels</title>
          <author fullname="">
            <organization></organization>
          </author>
          <date month="March" year="1997" />
        </front>
        <seriesInfo name="BCP" value="14" />
        <seriesInfo name="RFC" value="2119" />
      </reference>

      <reference anchor="RFC2104" target="http://www.ietf.org/rfc/rfc2104.txt">
        <front>
        <title>HMAC: Keyed-Hashing for Message Authentication</title>
          <author initials="H." surname="Krawczyk">
            <organization>IBM</organization>
          </author>
          <author initials="M." surname="Bellare">
            <organization>UCSD</organization>
          </author>
          <author initials="R." surname="Canetti">
            <organization>IBM</organization>
          </author>
          <date month="February" year="1997" />
        </front>
        <seriesInfo name="RFC" value="2104" />
      </reference>

      <reference anchor="SHA2" target="http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf">
        <front>
        <title>FIPS PUB 180-3: Secure Hash Standard (SHS)</title>
          <author surname="NIST">
			  <organization>IBM</organization>
          </author>
          <date month="October" year="2008" />
        </front>
      </reference>
    </references>
    
      <references title="Informative References">
      
      <reference anchor="CN" target="http://www.gemplus.com/smart/rd/publications/pdf/CN99maur.pdf">
        <front>
        <title>An accurate evaluation of Maurer's universal test</title>
          <author initials="J.S." surname="Coron">
            <organization>University of Luxembourg</organization>
          </author>
          <author initials="D." surname="Naccache">
            <organization>ENS</organization>
          </author>
          <date month="February" year="1999" />
        </front>
        <seriesInfo name="LNCS" value="1556" />
       </reference>

       <reference anchor="RFC4301" target="http://www.ietf.org/rfc/rfc4301.txt">
        <front>
          <title>Security Architecture for the Internet Protocol</title>
          <author initials="S." surname="Kent">
            <organization>BBN Technologies</organization>
          </author>
          <author initials="K." surname="Seo">
            <organization>BBN Technologies</organization>
          </author>
          <date month="December" year="2005" />
        </front>
        <seriesInfo name="RFC" value="4301" />
      </reference>

       <reference anchor="RFC5246" target="http://www.ietf.org/rfc/rfc5246.txt">
        <front>
          <title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
          <author initials="T." surname="Dierks">
            <organization>Independent</organization>
          </author>
          <author initials="E." surname="Rescorla">
            <organization>ETFM</organization>
          </author>
          <date month="August" year="2008" />
        </front>
        <seriesInfo name="RFC" value="5246" />
      </reference>
      
       <reference anchor="RFC6030" target="http://www.ietf.org/rfc/rfc6030.txt">
        <front>
          <title>Portable Symmetric Key Container (PSKC)</title>
          <author initials="P." surname="Hoyer">
            <organization>ActivIdentity</organization>
          </author>
          <author initials="M." surname="Pei">
            <organization>VeriSign</organization>
          </author>
          <author initials="S." surname="Machani">
            <organization>Diversinet</organization>
          </author>
          <date month="October" year="2010" />
        </front>
        <seriesInfo name="RFC" value="6030" />
      </reference>

       <reference anchor="UT" target="http://en.wikipedia.org/wiki/Unix_time">
        <front>
          <title>Unix time</title>
          <author surname="">
            <organization>Wikipedia</organization>
          </author>
          <date month="February" year="2011" />
        </front>
      </reference>
      
    </references>

    <section anchor="Section-Reference-Impl" title="TOTP Algorithm: Reference Implementation">
        <figure>
        <preamble/>
        <artwork><![CDATA[
<CODE BEGINS>

/**    
Copyright (c) 2011 IETF Trust and the persons identified as authors of 
the code. All rights reserved.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.lang.reflect.UndeclaredThrowableException;
import java.security.GeneralSecurityException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.TimeZone;

/**
 * This an example implementation of the OATH TOTP algorithm. 
 * Visit www.openauthentication.org for more information.
 * 
 * @author Johan Rydell, PortWise, Inc.
 */
public class TOTP {

    private TOTP() {}

    /**
     * This method uses the JCE to provide the crypto
     * algorithm.
     * HMAC computes a Hashed Message Authentication Code with the
     * crypto hash algorithm as a parameter.
     *
     * @param crypto the crypto algorithm (HmacSHA1, HmacSHA256,
     *                            HmacSHA512)
     * @param keyBytes the bytes to use for the HMAC key
     * @param text the message or text to be authenticated.
     */
    private static byte[] hmac_sha(String crypto, byte[] keyBytes, 
            byte[] text){
        try {
            Mac hmac;
            hmac = Mac.getInstance(crypto);
            SecretKeySpec macKey =
                new SecretKeySpec(keyBytes, "RAW");
            hmac.init(macKey);
            return hmac.doFinal(text);
        } catch (GeneralSecurityException gse) {
            throw new UndeclaredThrowableException(gse);
        }
    }

    /**
     * This method converts HEX string to Byte[]
     *
     * @param hex the HEX string
     * 
     * @return A byte array  
     */
    private static byte[] hexStr2Bytes(String hex){
        // Adding one byte to get the right conversion
        // values starting with "0" can be converted
        byte[] bArray = new BigInteger("10" + hex,16).toByteArray();    

        // Copy all the REAL bytes, not the "first"
        byte[] ret = new byte[bArray.length - 1];
        for (int i = 0; i < ret.length ; i++) 
            ret[i] = bArray[i+1];
        return ret;
    }


    private static final int[] DIGITS_POWER
    // 0 1  2   3    4     5      6       7        8                 
    = {1,10,100,1000,10000,100000,1000000,10000000,100000000 };


    /**
     * This method generates an TOTP value for the given
     * set of parameters.
     *
     * @param key the shared secret, HEX encoded
     * @param time a value that reflects a time 
     * @param returnDigits number of digits to return 
     * 
     * @return A numeric String in base 10 that includes
     *              {@link truncationDigits} digits 
     */
    public static String generateTOTP(String key,
            String time,
            String returnDigits){
        return generateTOTP(key, time, returnDigits, "HmacSHA1");
    }


    /**
     * This method generates an TOTP value for the given
     * set of parameters.
     *
     * @param key the shared secret, HEX encoded
     * @param time a value that reflects a time 
     * @param returnDigits number of digits to return 
     * 
     * @return A numeric String in base 10 that includes
     *              {@link truncationDigits} digits 
     */
    public static String generateTOTP256(String key,
            String time,
            String returnDigits){
        return generateTOTP(key, time, returnDigits, "HmacSHA256");
    }


    /**
     * This method generates an TOTP value for the given
     * set of parameters.
     *
     * @param key the shared secret, HEX encoded
     * @param time a value that reflects a time 
     * @param returnDigits number of digits to return 
     * 
     * @return A numeric String in base 10 that includes
     *              {@link truncationDigits} digits 
     */
    public static String generateTOTP512(String key,
            String time,
            String returnDigits){
        return generateTOTP(key, time, returnDigits, "HmacSHA512");
    }


    /**
     * This method generates an TOTP value for the given
     * set of parameters.
     *
     * @param key the shared secret, HEX encoded
     * @param time a value that reflects a time 
     * @param returnDigits number of digits to return 
     * @param crypto the crypto function to use 
     * 
     * @return A numeric String in base 10 that includes
     *              {@link truncationDigits} digits 
     */
    public static String generateTOTP(String key,
            String time,
            String returnDigits,
            String crypto){
        int codeDigits = Integer.decode(returnDigits).intValue();
        String result = null;

        // Using the counter
        // First 8 bytes are for the movingFactor
        // Complaint with base RFC 4226 (HOTP)
        while(time.length() < 16 )
            time = "0" + time;

        // Get the HEX in a Byte[]
        byte[] msg = hexStr2Bytes(time);
        byte[] k = hexStr2Bytes(key);

        byte[] hash = hmac_sha(crypto, k, msg);

        // put selected bytes into result int
        int offset = hash[hash.length - 1] & 0xf;

        int binary =
            ((hash[offset] & 0x7f) << 24) | 
            ((hash[offset + 1] & 0xff) << 16) | 
            ((hash[offset + 2] & 0xff) << 8) | 
            (hash[offset + 3] & 0xff);

        int otp = binary % DIGITS_POWER[codeDigits];

        result = Integer.toString(otp);
        while (result.length() < codeDigits) {
            result = "0" + result;
        }
        return result;
    }


    public static void main(String[] args) {
        // Seed for HMAC-SHA1 - 20 bytes
        String seed = "3132333435363738393031323334353637383930";
        // Seed for HMAC-SHA256 - 32 bytes
        String seed32 = "3132333435363738393031323334353637383930" +
        "313233343536373839303132"; 
        // Seed for HMAC-SHA512 - 64 bytes
        String seed64 = "3132333435363738393031323334353637383930" +
        "3132333435363738393031323334353637383930" +
        "3132333435363738393031323334353637383930" +
        "31323334";
        long T0 = 0;
        long X = 30;
        long testTime[] = {59L, 1111111109L, 1111111111L, 
                1234567890L, 2000000000L, 20000000000L};

        String steps = "0";
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));

        try{
            System.out.println(
                    "+---------------+-----------------------+" +
            "------------------+--------+--------+");
            System.out.println(
                    "|  Time(sec)    |   Time (UTC format)   " +
            "| Value of T(Hex)  |  TOTP  | Mode   |");
            System.out.println(
                    "+---------------+-----------------------+" +
            "------------------+--------+--------+");

            for(int i=0; i<testTime.length; i++) {       
                long T = (testTime[i] - T0)/X;
                steps = Long.toHexString(T).toUpperCase();
                while(steps.length() < 16) steps = "0" + steps;
                String fmtTime = String.format("%1$-11s", testTime[i]);
                String utcTime = df.format(new Date(testTime[i]*1000));
                System.out.print("|  " + fmtTime + "  |  " + utcTime +  
                        "  | " + steps + " |");
                System.out.println(generateTOTP(seed, steps, "8", 
                "HmacSHA1") + "| SHA1   |");
                System.out.print("|  " + fmtTime + "  |  " + utcTime +  
                        "  | " + steps + " |");
                System.out.println(generateTOTP(seed32, steps, "8", 
                "HmacSHA256") + "| SHA256 |");
                System.out.print("|  " + fmtTime + "  |  " + utcTime +  
                        "  | " + steps + " |");
                System.out.println(generateTOTP(seed64, steps, "8", 
                "HmacSHA512") + "| SHA512 |");

                System.out.println(
                        "+---------------+-----------------------+" +
                "------------------+--------+--------+");
            }
        }catch (final Exception e){
            System.out.println("Error : " + e);
        }
    }
}

<CODE ENDS>
]]></artwork>
            <postamble/>
    </figure>        
    </section>
    <section anchor="Section-Test-Vectors" title="Test Vectors">
      <t>This section provides test values that can be used for HOTP time-based 
      variant algorithm interoperability test.</t>
      
      <t>The test token shared secret uses the ASCII string value 
      "12345678901234567890". 
      
      With Time Step X = 30, and Unix epoch as initial value to count time steps
      where T0 = 0, the TOTP algorithm will display the following  values 
      for specified modes and timestamps.</t>
      
            
      <texttable anchor="TOTPTable" title="TOTP Table">
          <ttcol align="center">Time (sec)</ttcol>
          <ttcol align="center">UTC Time</ttcol>          
          <ttcol align="center">Value of T (hex)</ttcol>          
          <ttcol align="center">TOTP</ttcol>
          <ttcol align="center">Mode</ttcol>

          <c>59</c>
          <c>1970-01-01 00:00:59</c>
          <c>0000000000000001</c>
          <c>94287082</c>
          <c>SHA1</c>
          
          <c>59</c>
          <c>1970-01-01 00:00:59</c>
          <c>0000000000000001</c>
          <c>46119246</c>
          <c>SHA256</c>
          
          <c>59</c>
          <c>1970-01-01 00:00:59</c>
          <c>0000000000000001</c>
          <c>90693936</c>
          <c>SHA512</c>

          <c>1111111109</c>
          <c>2005-03-18 01:58:29</c>
          <c>00000000023523EC</c>
          <c>07081804</c>
          <c>SHA1</c>
          
          <c>1111111109</c>
          <c>2005-03-18 01:58:29</c>
          <c>00000000023523EC</c>
          <c>68084774</c>
          <c>SHA256</c>
          
          <c>1111111109</c>
          <c>2005-03-18 01:58:29</c>
          <c>00000000023523EC</c>
          <c>25091201</c>
          <c>SHA512</c>
                    
          <c>1111111111</c>
          <c>2005-03-18 01:58:31</c>
          <c>00000000023523ED</c>
          <c>14050471</c>
          <c>SHA1</c>
          
          <c>1111111111</c>
          <c>2005-03-18 01:58:31</c>
          <c>00000000023523ED</c>
          <c>67062674</c>
          <c>SHA256</c>
          
          <c>1111111111</c>
          <c>2005-03-18 01:58:31</c>
          <c>00000000023523ED</c>
          <c>99943326</c>
          <c>SHA512</c>
          
          <c>1234567890</c>
          <c>2009-02-13 23:31:30</c>
          <c>000000000273EF07</c>
          <c>89005924</c>
          <c>SHA1</c>
         
          <c>1234567890</c>
          <c>2009-02-13 23:31:30</c>
          <c>000000000273EF07</c>
          <c>91819424</c>
          <c>SHA256</c>
          
          <c>1234567890</c>
          <c>2009-02-13 23:31:30</c>
          <c>000000000273EF07</c>
          <c>93441116</c>
          <c>SHA512</c>

          <c>2000000000</c>
          <c>2033-05-18 03:33:20</c>
          <c>0000000003F940AA</c>
          <c>69279037</c>
          <c>SHA1</c>

          <c>2000000000</c>
          <c>2033-05-18 03:33:20</c>
          <c>0000000003F940AA</c>
          <c>90698825</c>
          <c>SHA256</c>

          <c>2000000000</c>
          <c>2033-05-18 03:33:20</c>
          <c>0000000003F940AA</c>
          <c>38618901</c>
          <c>SHA512</c>
          
          <c>20000000000</c>
          <c>2603-10-11 11:33:20</c>
          <c>0000000027BC86AA</c>
          <c>65353130</c>
          <c>SHA1</c>

          <c>20000000000</c>
          <c>2603-10-11 11:33:20</c>
          <c>0000000027BC86AA</c>
          <c>77737706</c>
          <c>SHA256</c>

          <c>20000000000</c>
          <c>2603-10-11 11:33:20</c>
          <c>0000000027BC86AA</c>
          <c>47863826</c>
          <c>SHA512</c>
                                        
        </texttable>     
    </section>    
</back>
</rfc>
