summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc6238.txt
blob: 8c964f4c393148980045dea7e0cd7efff77c45f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
Internet Engineering Task Force (IETF)                        D. M'Raihi
Request for Comments: 6238                                Verisign, Inc.
Category: Informational                                       S. Machani
ISSN: 2070-1721                                         Diversinet Corp.
                                                                  M. Pei
                                                                Symantec
                                                               J. Rydell
                                                          Portwise, Inc.
                                                                May 2011


              TOTP: Time-Based One-Time Password Algorithm

Abstract

   This document describes an extension of the One-Time Password (OTP)
   algorithm, namely the HMAC-based One-Time Password (HOTP) algorithm,
   as defined in RFC 4226, to support the 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.

   The proposed algorithm can be used across a wide range of network
   applications, from remote Virtual Private Network (VPN) access and
   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.

Status of This Memo

   This document is not an Internet Standards Track specification; it is
   published for informational purposes.

   This document is a product of the Internet Engineering Task Force
   (IETF).  It represents the consensus of the IETF community.  It has
   received public review and has been approved for publication by the
   Internet Engineering Steering Group (IESG).  Not all documents
   approved by the IESG are a candidate for any level of Internet
   Standard; see Section 2 of RFC 5741.

   Information about the current status of this document, any errata,
   and how to provide feedback on it may be obtained at
   http://www.rfc-editor.org/info/rfc6238.





M'Raihi, et al.               Informational                     [Page 1]
^L
RFC 6238                      HOTPTimeBased                     May 2011


Copyright Notice

   Copyright (c) 2011 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (http://trustee.ietf.org/license-info) in effect on the date of
   publication of this document.  Please review these documents
   carefully, as they describe your rights and restrictions with respect
   to this document.  Code Components extracted from this document must
   include Simplified BSD License text as described in Section 4.e of
   the Trust Legal Provisions and are provided without warranty as
   described in the Simplified BSD License.

Table of Contents

   1. Introduction ....................................................2
      1.1. Scope ......................................................2
      1.2. Background .................................................3
   2. Notation and Terminology ........................................3
   3. Algorithm Requirements ..........................................3
   4. TOTP Algorithm ..................................................4
      4.1. Notations ..................................................4
      4.2. Description ................................................4
   5. Security Considerations .........................................5
      5.1. General ....................................................5
      5.2. Validation and Time-Step Size ..............................6
   6. Resynchronization ...............................................7
   7. Acknowledgements ................................................7
   8. References ......................................................8
      8.1. Normative References .......................................8
      8.2. Informative References .....................................8
   Appendix A. TOTP Algorithm: Reference Implementation ...............9
   Appendix B. Test Vectors ..........................................14

1.  Introduction

1.1.  Scope

   This document describes an extension of the One-Time Password (OTP)
   algorithm, namely the HMAC-based One-Time Password (HOTP) algorithm,
   as defined in [RFC4226], to support the time-based moving factor.








M'Raihi, et al.               Informational                     [Page 2]
^L
RFC 6238                      HOTPTimeBased                     May 2011


1.2.  Background

   As defined in [RFC4226], the HOTP algorithm is based on the
   HMAC-SHA-1 algorithm (as specified in [RFC2104]) and applied to an
   increasing counter value representing the message in the HMAC
   computation.

   Basically, the output of the HMAC-SHA-1 calculation is truncated to
   obtain user-friendly values:

      HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

   where Truncate represents the function that can convert an HMAC-SHA-1
   value into an HOTP value.  K and C represent the shared secret and
   counter value; see [RFC4226] for detailed definitions.

   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.

   TOTP implementations MAY use HMAC-SHA-256 or HMAC-SHA-512 functions,
   based on SHA-256 or SHA-512 [SHA2] hash functions, instead of the
   HMAC-SHA-1 function that has been specified for the HOTP computation
   in [RFC4226].

2.  Notation and Terminology

   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 [RFC2119].

3.  Algorithm Requirements

   This section summarizes the requirements taken into account for
   designing the TOTP algorithm.

   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 a more
       detailed 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.

   R2: The prover and verifier MUST either share the same secret or the
       knowledge of a secret transformation to generate a shared secret.

   R3: The algorithm MUST use HOTP [RFC4226] as a key building block.



M'Raihi, et al.               Informational                     [Page 3]
^L
RFC 6238                      HOTPTimeBased                     May 2011


   R4: The prover and verifier MUST use the same time-step value X.

   R5: There MUST be a unique secret (key) for each prover.

   R6: The keys SHOULD be randomly generated or derived using key
       derivation algorithms.

   R7: The keys MAY be stored in a tamper-resistant device and SHOULD be
       protected against unauthorized access and usage.

4.  TOTP Algorithm

   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.

4.1.  Notations

   o  X represents the time step in seconds (default value X =
      30 seconds) and is a system parameter.

   o  T0 is the Unix time to start counting time steps (default value is
      0, i.e., the Unix epoch) and is also a system parameter.

4.2.  Description

   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.

   More specifically, T = (Current Unix time - T0) / X, where 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.

   The implementation of this algorithm MUST support a time value T
   larger than a 32-bit integer when it is beyond the 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 specifications.







M'Raihi, et al.               Informational                     [Page 4]
^L
RFC 6238                      HOTPTimeBased                     May 2011


5.  Security Considerations

5.1.  General

   The security and strength of this algorithm depend on the properties
   of the underlying building block HOTP, which is a construction based
   on HMAC [RFC2104] using SHA-1 as the hash function.

   The conclusion of the security analysis detailed in [RFC4226] is
   that, for all practical purposes, the outputs of the dynamic
   truncation on distinct inputs are uniformly and independently
   distributed strings.

   The analysis demonstrates that the best possible attack against the
   HOTP function is the brute force attack.

   As indicated in the algorithm requirement section, keys SHOULD be
   chosen at random or using a cryptographically strong pseudorandom
   generator properly seeded with a random value.

   Keys SHOULD be of the length of the HMAC output to facilitate
   interoperability.

   We RECOMMEND following the recommendations in [RFC4086] for all
   pseudorandom and random number generations.  The pseudorandom numbers
   used for generating the keys SHOULD successfully pass the randomness
   test specified in [CN], or a similar well-recognized test.

   All the communications SHOULD take place over a secure channel, e.g.,
   Secure Socket Layer/Transport Layer Security (SSL/TLS) [RFC5246] or
   IPsec connections [RFC4301].

   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 to a short
   period of time.

   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.








M'Raihi, et al.               Informational                     [Page 5]
^L
RFC 6238                      HOTPTimeBased                     May 2011


5.2.  Validation and Time-Step Size

   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 network latency, the gap (as measured by T, that
   is, the number of time steps since T0) between the time that the OTP
   was generated and the time that the OTP arrives at the receiving
   system 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 produced 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 timestamps that are within
   the transmission delay.  A larger acceptable delay window would
   expose a larger window for attacks.  We RECOMMEND that at most one
   time step is allowed as the network delay.

   The time-step size has an impact on both security and usability.  A
   larger time-step size means a larger validity window for an OTP to be
   accepted by a validation system.  There are implications for using a
   larger time-step size, as follows:

   First, a larger time-step size exposes a larger window to 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.

   We RECOMMEND a default time-step size of 30 seconds.  This default
   value of 30 seconds is selected as a balance between security and
   usability.

   Second, the next different OTP must be generated in the next time-
   step window.  A user must wait until the clock moves to the next
   time-step window from the last submission.  The waiting time may not
   be exactly the length of the time step, depending on when the last
   OTP was generated.  For example, if the last OTP was generated at the
   halfway point in a time-step window, the waiting time for the next
   OTP is half the length of the time step.  In general, a larger time-
   step window means a longer waiting time for a user to get the next
   valid OTP after the last successful 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 will have to re-login to the
   same site in 10 minutes.



M'Raihi, et al.               Informational                     [Page 6]
^L
RFC 6238                      HOTPTimeBased                     May 2011


   Note that a prover may send the same OTP inside a given time-step
   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.

6.  Resynchronization

   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.

   This limit can be set both forward and backward 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
   two time steps backward, then the maximum elapsed time drift would be
   around 89 seconds, i.e., 29 seconds in the calculated time step and
   60 seconds for two backward time steps.

   This would mean the validator could perform a validation against the
   current time and then two further 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 the number of time steps.  When a new OTP is received
   after this step, the validator can validate the OTP with the current
   timestamp adjusted with the recorded number of time-step clock drifts
   for the token.

   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.

7.  Acknowledgements

   The authors of this document 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.






M'Raihi, et al.               Informational                     [Page 7]
^L
RFC 6238                      HOTPTimeBased                     May 2011


8.  References

8.1.  Normative References

   [RFC2104]  Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
              Hashing for Message Authentication", RFC 2104,
              February 1997.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.

   [RFC4086]  Eastlake 3rd, D., Schiller, J., and S. Crocker,
              "Randomness Recommendations for Security", BCP 106,
              RFC 4086, June 2005.

   [RFC4226]  M'Raihi, D., Bellare, M., Hoornaert, F., Naccache, D., and
              O. Ranen, "HOTP: An HMAC-Based One-Time Password
              Algorithm", RFC 4226, December 2005.

   [SHA2]     NIST, "FIPS PUB 180-3: Secure Hash Standard (SHS)",
              October 2008, <http://csrc.nist.gov/publications/fips/
              fips180-3/fips180-3_final.pdf>.

8.2.  Informative References

   [CN]       Coron, J. and D. Naccache, "An Accurate Evaluation of
              Maurer's Universal Test", LNCS 1556, February 1999,
              <http://www.gemplus.com/smart/rd/publications/pdf/
              CN99maur.pdf>.

   [RFC4301]  Kent, S. and K. Seo, "Security Architecture for the
              Internet Protocol", RFC 4301, December 2005.

   [RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
              (TLS) Protocol Version 1.2", RFC 5246, August 2008.

   [RFC6030]  Hoyer, P., Pei, M., and S. Machani, "Portable Symmetric
              Key Container (PSKC)", RFC 6030, October 2010.

   [UT]       Wikipedia, "Unix time", February 2011,
              <http://en.wikipedia.org/wiki/Unix_time>.










M'Raihi, et al.               Informational                     [Page 8]
^L
RFC 6238                      HOTPTimeBased                     May 2011


Appendix A.  TOTP Algorithm: Reference Implementation

 <CODE BEGINS>

 /**
 Copyright (c) 2011 IETF Trust and the persons identified as
 authors of the code. All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, is permitted pursuant to, and subject to the license
 terms contained in, the Simplified BSD License set forth in Section
 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
 (http://trustee.ietf.org/license-info).
 */

 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 is 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
      */



M'Raihi, et al.               Informational                     [Page 9]
^L
RFC 6238                      HOTPTimeBased                     May 2011


     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 a 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 };













M'Raihi, et al.               Informational                    [Page 10]
^L
RFC 6238                      HOTPTimeBased                     May 2011


     /**
      * This method generates a 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 a 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");
     }















M'Raihi, et al.               Informational                    [Page 11]
^L
RFC 6238                      HOTPTimeBased                     May 2011


     /**
      * This method generates a 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 a 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
         // Compliant 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);



M'Raihi, et al.               Informational                    [Page 12]
^L
RFC 6238                      HOTPTimeBased                     May 2011


         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"));












M'Raihi, et al.               Informational                    [Page 13]
^L
RFC 6238                      HOTPTimeBased                     May 2011


         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>

Appendix B.  Test Vectors

   This section provides test values that can be used for the HOTP time-
   based variant algorithm interoperability test.





M'Raihi, et al.               Informational                    [Page 14]
^L
RFC 6238                      HOTPTimeBased                     May 2011


   The test token shared secret uses the ASCII string value
   "12345678901234567890".  With Time Step X = 30, and the Unix epoch as
   the initial value to count time steps, where T0 = 0, the TOTP
   algorithm will display the following values for specified modes and
   timestamps.

  +-------------+--------------+------------------+----------+--------+
  |  Time (sec) |   UTC Time   | Value of T (hex) |   TOTP   |  Mode  |
  +-------------+--------------+------------------+----------+--------+
  |      59     |  1970-01-01  | 0000000000000001 | 94287082 |  SHA1  |
  |             |   00:00:59   |                  |          |        |
  |      59     |  1970-01-01  | 0000000000000001 | 46119246 | SHA256 |
  |             |   00:00:59   |                  |          |        |
  |      59     |  1970-01-01  | 0000000000000001 | 90693936 | SHA512 |
  |             |   00:00:59   |                  |          |        |
  |  1111111109 |  2005-03-18  | 00000000023523EC | 07081804 |  SHA1  |
  |             |   01:58:29   |                  |          |        |
  |  1111111109 |  2005-03-18  | 00000000023523EC | 68084774 | SHA256 |
  |             |   01:58:29   |                  |          |        |
  |  1111111109 |  2005-03-18  | 00000000023523EC | 25091201 | SHA512 |
  |             |   01:58:29   |                  |          |        |
  |  1111111111 |  2005-03-18  | 00000000023523ED | 14050471 |  SHA1  |
  |             |   01:58:31   |                  |          |        |
  |  1111111111 |  2005-03-18  | 00000000023523ED | 67062674 | SHA256 |
  |             |   01:58:31   |                  |          |        |
  |  1111111111 |  2005-03-18  | 00000000023523ED | 99943326 | SHA512 |
  |             |   01:58:31   |                  |          |        |
  |  1234567890 |  2009-02-13  | 000000000273EF07 | 89005924 |  SHA1  |
  |             |   23:31:30   |                  |          |        |
  |  1234567890 |  2009-02-13  | 000000000273EF07 | 91819424 | SHA256 |
  |             |   23:31:30   |                  |          |        |
  |  1234567890 |  2009-02-13  | 000000000273EF07 | 93441116 | SHA512 |
  |             |   23:31:30   |                  |          |        |
  |  2000000000 |  2033-05-18  | 0000000003F940AA | 69279037 |  SHA1  |
  |             |   03:33:20   |                  |          |        |
  |  2000000000 |  2033-05-18  | 0000000003F940AA | 90698825 | SHA256 |
  |             |   03:33:20   |                  |          |        |
  |  2000000000 |  2033-05-18  | 0000000003F940AA | 38618901 | SHA512 |
  |             |   03:33:20   |                  |          |        |
  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 65353130 |  SHA1  |
  |             |   11:33:20   |                  |          |        |
  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 77737706 | SHA256 |
  |             |   11:33:20   |                  |          |        |
  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 47863826 | SHA512 |
  |             |   11:33:20   |                  |          |        |
  +-------------+--------------+------------------+----------+--------+

                            Table 1: TOTP Table



M'Raihi, et al.               Informational                    [Page 15]
^L
RFC 6238                      HOTPTimeBased                     May 2011


Authors' Addresses

   David M'Raihi
   Verisign, Inc.
   685 E. Middlefield Road
   Mountain View, CA  94043
   USA

   EMail: davidietf@gmail.com


   Salah Machani
   Diversinet Corp.
   2225 Sheppard Avenue East, Suite 1801
   Toronto, Ontario  M2J 5C2
   Canada

   EMail: smachani@diversinet.com


   Mingliang Pei
   Symantec
   510 E. Middlefield Road
   Mountain View, CA  94043
   USA

   EMail: Mingliang_Pei@symantec.com


   Johan Rydell
   Portwise, Inc.
   275 Hawthorne Ave., Suite 119
   Palo Alto, CA  94301
   USA

   EMail: johanietf@gmail.com















M'Raihi, et al.               Informational                    [Page 16]
^L