Relevant RFCs.
git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@645 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
bbcd45ace7
commit
374a1769ca
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,619 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group H. Krawczyk
|
||||
Request for Comments: 2104 IBM
|
||||
Category: Informational M. Bellare
|
||||
UCSD
|
||||
R. Canetti
|
||||
IBM
|
||||
February 1997
|
||||
|
||||
|
||||
HMAC: Keyed-Hashing for Message Authentication
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. This memo
|
||||
does not specify an Internet standard of any kind. Distribution of
|
||||
this memo is unlimited.
|
||||
|
||||
Abstract
|
||||
|
||||
This document describes HMAC, a mechanism for message authentication
|
||||
using cryptographic hash functions. HMAC can be used with any
|
||||
iterative cryptographic hash function, e.g., MD5, SHA-1, in
|
||||
combination with a secret shared key. The cryptographic strength of
|
||||
HMAC depends on the properties of the underlying hash function.
|
||||
|
||||
1. Introduction
|
||||
|
||||
Providing a way to check the integrity of information transmitted
|
||||
over or stored in an unreliable medium is a prime necessity in the
|
||||
world of open computing and communications. Mechanisms that provide
|
||||
such integrity check based on a secret key are usually called
|
||||
"message authentication codes" (MAC). Typically, message
|
||||
authentication codes are used between two parties that share a secret
|
||||
key in order to validate information transmitted between these
|
||||
parties. In this document we present such a MAC mechanism based on
|
||||
cryptographic hash functions. This mechanism, called HMAC, is based
|
||||
on work by the authors [BCK1] where the construction is presented and
|
||||
cryptographically analyzed. We refer to that work for the details on
|
||||
the rationale and security analysis of HMAC, and its comparison to
|
||||
other keyed-hash methods.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 1]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
HMAC can be used in combination with any iterated cryptographic hash
|
||||
function. MD5 and SHA-1 are examples of such hash functions. HMAC
|
||||
also uses a secret key for calculation and verification of the
|
||||
message authentication values. The main goals behind this
|
||||
construction are
|
||||
|
||||
* To use, without modifications, available hash functions.
|
||||
In particular, hash functions that perform well in software,
|
||||
and for which code is freely and widely available.
|
||||
|
||||
* To preserve the original performance of the hash function without
|
||||
incurring a significant degradation.
|
||||
|
||||
* To use and handle keys in a simple way.
|
||||
|
||||
* To have a well understood cryptographic analysis of the strength of
|
||||
the authentication mechanism based on reasonable assumptions on the
|
||||
underlying hash function.
|
||||
|
||||
* To allow for easy replaceability of the underlying hash function in
|
||||
case that faster or more secure hash functions are found or
|
||||
required.
|
||||
|
||||
This document specifies HMAC using a generic cryptographic hash
|
||||
function (denoted by H). Specific instantiations of HMAC need to
|
||||
define a particular hash function. Current candidates for such hash
|
||||
functions include SHA-1 [SHA], MD5 [MD5], RIPEMD-128/160 [RIPEMD].
|
||||
These different realizations of HMAC will be denoted by HMAC-SHA1,
|
||||
HMAC-MD5, HMAC-RIPEMD, etc.
|
||||
|
||||
Note: To the date of writing of this document MD5 and SHA-1 are the
|
||||
most widely used cryptographic hash functions. MD5 has been recently
|
||||
shown to be vulnerable to collision search attacks [Dobb]. This
|
||||
attack and other currently known weaknesses of MD5 do not compromise
|
||||
the use of MD5 within HMAC as specified in this document (see
|
||||
[Dobb]); however, SHA-1 appears to be a cryptographically stronger
|
||||
function. To this date, MD5 can be considered for use in HMAC for
|
||||
applications where the superior performance of MD5 is critical. In
|
||||
any case, implementers and users need to be aware of possible
|
||||
cryptanalytic developments regarding any of these cryptographic hash
|
||||
functions, and the eventual need to replace the underlying hash
|
||||
function. (See section 6 for more information on the security of
|
||||
HMAC.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 2]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
2. Definition of HMAC
|
||||
|
||||
The definition of HMAC requires a cryptographic hash function, which
|
||||
we denote by H, and a secret key K. We assume H to be a cryptographic
|
||||
hash function where data is hashed by iterating a basic compression
|
||||
function on blocks of data. We denote by B the byte-length of such
|
||||
blocks (B=64 for all the above mentioned examples of hash functions),
|
||||
and by L the byte-length of hash outputs (L=16 for MD5, L=20 for
|
||||
SHA-1). The authentication key K can be of any length up to B, the
|
||||
block length of the hash function. Applications that use keys longer
|
||||
than B bytes will first hash the key using H and then use the
|
||||
resultant L byte string as the actual key to HMAC. In any case the
|
||||
minimal recommended length for K is L bytes (as the hash output
|
||||
length). See section 3 for more information on keys.
|
||||
|
||||
We define two fixed and different strings ipad and opad as follows
|
||||
(the 'i' and 'o' are mnemonics for inner and outer):
|
||||
|
||||
ipad = the byte 0x36 repeated B times
|
||||
opad = the byte 0x5C repeated B times.
|
||||
|
||||
To compute HMAC over the data `text' we perform
|
||||
|
||||
H(K XOR opad, H(K XOR ipad, text))
|
||||
|
||||
Namely,
|
||||
|
||||
(1) append zeros to the end of K to create a B byte string
|
||||
(e.g., if K is of length 20 bytes and B=64, then K will be
|
||||
appended with 44 zero bytes 0x00)
|
||||
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
|
||||
(1) with ipad
|
||||
(3) append the stream of data 'text' to the B byte string resulting
|
||||
from step (2)
|
||||
(4) apply H to the stream generated in step (3)
|
||||
(5) XOR (bitwise exclusive-OR) the B byte string computed in
|
||||
step (1) with opad
|
||||
(6) append the H result from step (4) to the B byte string
|
||||
resulting from step (5)
|
||||
(7) apply H to the stream generated in step (6) and output
|
||||
the result
|
||||
|
||||
For illustration purposes, sample code based on MD5 is provided as an
|
||||
appendix.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 3]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
3. Keys
|
||||
|
||||
The key for HMAC can be of any length (keys longer than B bytes are
|
||||
first hashed using H). However, less than L bytes is strongly
|
||||
discouraged as it would decrease the security strength of the
|
||||
function. Keys longer than L bytes are acceptable but the extra
|
||||
length would not significantly increase the function strength. (A
|
||||
longer key may be advisable if the randomness of the key is
|
||||
considered weak.)
|
||||
|
||||
Keys need to be chosen at random (or using a cryptographically strong
|
||||
pseudo-random generator seeded with a random seed), and periodically
|
||||
refreshed. (Current attacks do not indicate a specific recommended
|
||||
frequency for key changes as these attacks are practically
|
||||
infeasible. However, periodic key refreshment is a fundamental
|
||||
security practice that helps against potential weaknesses of the
|
||||
function and keys, and limits the damage of an exposed key.)
|
||||
|
||||
4. Implementation Note
|
||||
|
||||
HMAC is defined in such a way that the underlying hash function H can
|
||||
be used with no modification to its code. In particular, it uses the
|
||||
function H with the pre-defined initial value IV (a fixed value
|
||||
specified by each iterative hash function to initialize its
|
||||
compression function). However, if desired, a performance
|
||||
improvement can be achieved at the cost of (possibly) modifying the
|
||||
code of H to support variable IVs.
|
||||
|
||||
The idea is that the intermediate results of the compression function
|
||||
on the B-byte blocks (K XOR ipad) and (K XOR opad) can be precomputed
|
||||
only once at the time of generation of the key K, or before its first
|
||||
use. These intermediate results are stored and then used to
|
||||
initialize the IV of H each time that a message needs to be
|
||||
authenticated. This method saves, for each authenticated message,
|
||||
the application of the compression function of H on two B-byte blocks
|
||||
(i.e., on (K XOR ipad) and (K XOR opad)). Such a savings may be
|
||||
significant when authenticating short streams of data. We stress
|
||||
that the stored intermediate values need to be treated and protected
|
||||
the same as secret keys.
|
||||
|
||||
Choosing to implement HMAC in the above way is a decision of the
|
||||
local implementation and has no effect on inter-operability.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 4]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
5. Truncated output
|
||||
|
||||
A well-known practice with message authentication codes is to
|
||||
truncate the output of the MAC and output only part of the bits
|
||||
(e.g., [MM, ANSI]). Preneel and van Oorschot [PV] show some
|
||||
analytical advantages of truncating the output of hash-based MAC
|
||||
functions. The results in this area are not absolute as for the
|
||||
overall security advantages of truncation. It has advantages (less
|
||||
information on the hash result available to an attacker) and
|
||||
disadvantages (less bits to predict for the attacker). Applications
|
||||
of HMAC can choose to truncate the output of HMAC by outputting the t
|
||||
leftmost bits of the HMAC computation for some parameter t (namely,
|
||||
the computation is carried in the normal way as defined in section 2
|
||||
above but the end result is truncated to t bits). We recommend that
|
||||
the output length t be not less than half the length of the hash
|
||||
output (to match the birthday attack bound) and not less than 80 bits
|
||||
(a suitable lower bound on the number of bits that need to be
|
||||
predicted by an attacker). We propose denoting a realization of HMAC
|
||||
that uses a hash function H with t bits of output as HMAC-H-t. For
|
||||
example, HMAC-SHA1-80 denotes HMAC computed using the SHA-1 function
|
||||
and with the output truncated to 80 bits. (If the parameter t is not
|
||||
specified, e.g. HMAC-MD5, then it is assumed that all the bits of the
|
||||
hash are output.)
|
||||
|
||||
6. Security
|
||||
|
||||
The security of the message authentication mechanism presented here
|
||||
depends on cryptographic properties of the hash function H: the
|
||||
resistance to collision finding (limited to the case where the
|
||||
initial value is secret and random, and where the output of the
|
||||
function is not explicitly available to the attacker), and the
|
||||
message authentication property of the compression function of H when
|
||||
applied to single blocks (in HMAC these blocks are partially unknown
|
||||
to an attacker as they contain the result of the inner H computation
|
||||
and, in particular, cannot be fully chosen by the attacker).
|
||||
|
||||
These properties, and actually stronger ones, are commonly assumed
|
||||
for hash functions of the kind used with HMAC. In particular, a hash
|
||||
function for which the above properties do not hold would become
|
||||
unsuitable for most (probably, all) cryptographic applications,
|
||||
including alternative message authentication schemes based on such
|
||||
functions. (For a complete analysis and rationale of the HMAC
|
||||
function the reader is referred to [BCK1].)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 5]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
Given the limited confidence gained so far as for the cryptographic
|
||||
strength of candidate hash functions, it is important to observe the
|
||||
following two properties of the HMAC construction and its secure use
|
||||
for message authentication:
|
||||
|
||||
1. The construction is independent of the details of the particular
|
||||
hash function H in use and then the latter can be replaced by any
|
||||
other secure (iterative) cryptographic hash function.
|
||||
|
||||
2. Message authentication, as opposed to encryption, has a
|
||||
"transient" effect. A published breaking of a message authentication
|
||||
scheme would lead to the replacement of that scheme, but would have
|
||||
no adversarial effect on information authenticated in the past. This
|
||||
is in sharp contrast with encryption, where information encrypted
|
||||
today may suffer from exposure in the future if, and when, the
|
||||
encryption algorithm is broken.
|
||||
|
||||
The strongest attack known against HMAC is based on the frequency of
|
||||
collisions for the hash function H ("birthday attack") [PV,BCK2], and
|
||||
is totally impractical for minimally reasonable hash functions.
|
||||
|
||||
As an example, if we consider a hash function like MD5 where the
|
||||
output length equals L=16 bytes (128 bits) the attacker needs to
|
||||
acquire the correct message authentication tags computed (with the
|
||||
_same_ secret key K!) on about 2**64 known plaintexts. This would
|
||||
require the processing of at least 2**64 blocks under H, an
|
||||
impossible task in any realistic scenario (for a block length of 64
|
||||
bytes this would take 250,000 years in a continuous 1Gbps link, and
|
||||
without changing the secret key K during all this time). This attack
|
||||
could become realistic only if serious flaws in the collision
|
||||
behavior of the function H are discovered (e.g. collisions found
|
||||
after 2**30 messages). Such a discovery would determine the immediate
|
||||
replacement of the function H (the effects of such failure would be
|
||||
far more severe for the traditional uses of H in the context of
|
||||
digital signatures, public key certificates, etc.).
|
||||
|
||||
Note: this attack needs to be strongly contrasted with regular
|
||||
collision attacks on cryptographic hash functions where no secret key
|
||||
is involved and where 2**64 off-line parallelizable (!) operations
|
||||
suffice to find collisions. The latter attack is approaching
|
||||
feasibility [VW] while the birthday attack on HMAC is totally
|
||||
impractical. (In the above examples, if one uses a hash function
|
||||
with, say, 160 bit of output then 2**64 should be replaced by 2**80.)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 6]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
A correct implementation of the above construction, the choice of
|
||||
random (or cryptographically pseudorandom) keys, a secure key
|
||||
exchange mechanism, frequent key refreshments, and good secrecy
|
||||
protection of keys are all essential ingredients for the security of
|
||||
the integrity verification mechanism provided by HMAC.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 7]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
Appendix -- Sample Code
|
||||
|
||||
For the sake of illustration we provide the following sample code for
|
||||
the implementation of HMAC-MD5 as well as some corresponding test
|
||||
vectors (the code is based on MD5 code as described in [MD5]).
|
||||
|
||||
/*
|
||||
** Function: hmac_md5
|
||||
*/
|
||||
|
||||
void
|
||||
hmac_md5(text, text_len, key, key_len, digest)
|
||||
unsigned char* text; /* pointer to data stream */
|
||||
int text_len; /* length of data stream */
|
||||
unsigned char* key; /* pointer to authentication key */
|
||||
int key_len; /* length of authentication key */
|
||||
caddr_t digest; /* caller digest to be filled in */
|
||||
|
||||
{
|
||||
MD5_CTX context;
|
||||
unsigned char k_ipad[65]; /* inner padding -
|
||||
* key XORd with ipad
|
||||
*/
|
||||
unsigned char k_opad[65]; /* outer padding -
|
||||
* key XORd with opad
|
||||
*/
|
||||
unsigned char tk[16];
|
||||
int i;
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64) {
|
||||
|
||||
MD5_CTX tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 8]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected
|
||||
*/
|
||||
|
||||
/* start out by storing key in pads */
|
||||
bzero( k_ipad, sizeof k_ipad);
|
||||
bzero( k_opad, sizeof k_opad);
|
||||
bcopy( key, k_ipad, key_len);
|
||||
bcopy( key, k_opad, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i=0; i<64; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
/*
|
||||
* perform inner MD5
|
||||
*/
|
||||
MD5Init(&context); /* init context for 1st
|
||||
* pass */
|
||||
MD5Update(&context, k_ipad, 64) /* start with inner pad */
|
||||
MD5Update(&context, text, text_len); /* then text of datagram */
|
||||
MD5Final(digest, &context); /* finish up 1st pass */
|
||||
/*
|
||||
* perform outer MD5
|
||||
*/
|
||||
MD5Init(&context); /* init context for 2nd
|
||||
* pass */
|
||||
MD5Update(&context, k_opad, 64); /* start with outer pad */
|
||||
MD5Update(&context, digest, 16); /* then results of 1st
|
||||
* hash */
|
||||
MD5Final(digest, &context); /* finish up 2nd pass */
|
||||
}
|
||||
|
||||
Test Vectors (Trailing '\0' of a character string not included in test):
|
||||
|
||||
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
|
||||
key_len = 16 bytes
|
||||
data = "Hi There"
|
||||
data_len = 8 bytes
|
||||
digest = 0x9294727a3638bb1c13f48ef8158bfc9d
|
||||
|
||||
key = "Jefe"
|
||||
data = "what do ya want for nothing?"
|
||||
data_len = 28 bytes
|
||||
digest = 0x750c783e6ab0b503eaa86e310a5db738
|
||||
|
||||
key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 9]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
key_len 16 bytes
|
||||
data = 0xDDDDDDDDDDDDDDDDDDDD...
|
||||
..DDDDDDDDDDDDDDDDDDDD...
|
||||
..DDDDDDDDDDDDDDDDDDDD...
|
||||
..DDDDDDDDDDDDDDDDDDDD...
|
||||
..DDDDDDDDDDDDDDDDDDDD
|
||||
data_len = 50 bytes
|
||||
digest = 0x56be34521d144c88dbb8c733f0e8b3f6
|
||||
|
||||
Acknowledgments
|
||||
|
||||
Pau-Chen Cheng, Jeff Kraemer, and Michael Oehler, have provided
|
||||
useful comments on early drafts, and ran the first interoperability
|
||||
tests of this specification. Jeff and Pau-Chen kindly provided the
|
||||
sample code and test vectors that appear in the appendix. Burt
|
||||
Kaliski, Bart Preneel, Matt Robshaw, Adi Shamir, and Paul van
|
||||
Oorschot have provided useful comments and suggestions during the
|
||||
investigation of the HMAC construction.
|
||||
|
||||
References
|
||||
|
||||
[ANSI] ANSI X9.9, "American National Standard for Financial
|
||||
Institution Message Authentication (Wholesale)," American
|
||||
Bankers Association, 1981. Revised 1986.
|
||||
|
||||
[Atk] Atkinson, R., "IP Authentication Header", RFC 1826, August
|
||||
1995.
|
||||
|
||||
[BCK1] M. Bellare, R. Canetti, and H. Krawczyk,
|
||||
"Keyed Hash Functions and Message Authentication",
|
||||
Proceedings of Crypto'96, LNCS 1109, pp. 1-15.
|
||||
(http://www.research.ibm.com/security/keyed-md5.html)
|
||||
|
||||
[BCK2] M. Bellare, R. Canetti, and H. Krawczyk,
|
||||
"Pseudorandom Functions Revisited: The Cascade Construction",
|
||||
Proceedings of FOCS'96.
|
||||
|
||||
[Dobb] H. Dobbertin, "The Status of MD5 After a Recent Attack",
|
||||
RSA Labs' CryptoBytes, Vol. 2 No. 2, Summer 1996.
|
||||
http://www.rsa.com/rsalabs/pubs/cryptobytes.html
|
||||
|
||||
[PV] B. Preneel and P. van Oorschot, "Building fast MACs from hash
|
||||
functions", Advances in Cryptology -- CRYPTO'95 Proceedings,
|
||||
Lecture Notes in Computer Science, Springer-Verlag Vol.963,
|
||||
1995, pp. 1-14.
|
||||
|
||||
[MD5] Rivest, R., "The MD5 Message-Digest Algorithm",
|
||||
RFC 1321, April 1992.
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 10]
|
||||
|
||||
RFC 2104 HMAC February 1997
|
||||
|
||||
|
||||
[MM] Meyer, S. and Matyas, S.M., Cryptography, New York Wiley,
|
||||
1982.
|
||||
|
||||
[RIPEMD] H. Dobbertin, A. Bosselaers, and B. Preneel, "RIPEMD-160: A
|
||||
strengthened version of RIPEMD", Fast Software Encryption,
|
||||
LNCS Vol 1039, pp. 71-82.
|
||||
ftp://ftp.esat.kuleuven.ac.be/pub/COSIC/bosselae/ripemd/.
|
||||
|
||||
[SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.
|
||||
|
||||
[Tsu] G. Tsudik, "Message authentication with one-way hash
|
||||
functions", In Proceedings of Infocom'92, May 1992.
|
||||
(Also in "Access Control and Policy Enforcement in
|
||||
Internetworks", Ph.D. Dissertation, Computer Science
|
||||
Department, University of Southern California, April 1991.)
|
||||
|
||||
[VW] P. van Oorschot and M. Wiener, "Parallel Collision
|
||||
Search with Applications to Hash Functions and Discrete
|
||||
Logarithms", Proceedings of the 2nd ACM Conf. Computer and
|
||||
Communications Security, Fairfax, VA, November 1994.
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Hugo Krawczyk
|
||||
IBM T.J. Watson Research Center
|
||||
P.O.Box 704
|
||||
Yorktown Heights, NY 10598
|
||||
|
||||
EMail: hugo@watson.ibm.com
|
||||
|
||||
Mihir Bellare
|
||||
Dept of Computer Science and Engineering
|
||||
Mail Code 0114
|
||||
University of California at San Diego
|
||||
9500 Gilman Drive
|
||||
La Jolla, CA 92093
|
||||
|
||||
EMail: mihir@cs.ucsd.edu
|
||||
|
||||
Ran Canetti
|
||||
IBM T.J. Watson Research Center
|
||||
P.O.Box 704
|
||||
Yorktown Heights, NY 10598
|
||||
|
||||
EMail: canetti@watson.ibm.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Krawczyk, et. al. Informational [Page 11]
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
||||
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]
|
||||
|
Loading…
Reference in New Issue