RFC 6287
OCRA: OATH Challenge-Response Algorithm
OCRA: OATH Challenge-Response Algorithm π¦
Title block, the tea β
- RFC 6287, Category: Informational, ISSN 2070-1721
- Published June 2011 by the Internet Engineering Task Force (IETF) πΈ
- Authors: D. M'Raihi (Verisign, Inc.), J. Rydell (Portwise, Inc.), S. Bajaj (Symantec Corp.), S. Machani (Diversinet Corp.), and D. Naccache (Ecole Normale Superieure) π
- It doesn't obsolete or update anything. The title block lists nothing for either one π«Ά
Table of Contents
1. Introduction ....................................................3
2. Notation and Terminology ........................................3
3. Algorithm Requirements ..........................................3
4. OCRA Background .................................................4
4.1. HOTP Algorithm .............................................4
5. Definition of OCRA ..............................................5
5.1. DataInput Parameters .......................................5
5.2. CryptoFunction .............................................7
6. The OCRASuite ...................................................8
6.1. Algorithm ..................................................9
6.2. CryptoFunction .............................................9
6.3. DataInput ..................................................9
6.4. OCRASuite Examples ........................................10
7. Algorithm Modes for Authentication .............................10
7.1. One-Way Challenge-Response ................................11
7.2. Mutual Challenge-Response .................................12
7.3. Algorithm Modes for Signature .............................13
7.3.1. Plain Signature ....................................13
7.3.2. Signature with Server Authentication ...............14
8. Security Considerations ........................................16
8.1. Security Analysis of OCRA .................................16
8.2. Implementation Considerations .............................17
9. Conclusion .....................................................18
10. Acknowledgements ..............................................18
11. References ....................................................19
11.1. Normative References .....................................19
11.2. Informative References ...................................19
Appendix A. Reference Implementation ..............................20
Appendix B. Test Vectors Generation ...............................26
Appendix C. Test Vectors ..........................................33
C.1. One-Way Challenge Response .................................34
C.2. Mutual Challenge-Response ..................................35
C.3. Plain Signature ............................................37
Abstract β¨
okay so this doc describes a challenge-response authentication algorithm that the Initiative for Open Authentication (OATH) cooked up π it's built on the HMAC-based One-Time Password (HOTP) algorithm, and it gives you one-way authentication, mutual authentication, and electronic signature capabilities. iconic π₯
Status of This Memo π
bestie, this doc is not an Internet Standards Track specification π it's published purely 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 π
Info about the current status of this document, any errata, and how to send feedback on it lives at http://www.rfc-editor.org/info/rfc6287 π§
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, since 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 they are provided without warranty as described in the Simplified BSD License. π«Ά
1. Introduction β¨
so the Initiative for Open Authentication (OATH) [OATH] has spotted a bunch of use cases and scenarios that need an asynchronous variant, for people who don't want to keep an authentication system in sync π¦ a commonly accepted way to do this is a challenge-response scheme.
This challenge-response mode of authentication is already widely adopted across the industry. Several vendors already ship software applications and hardware devices that implement challenge-response, but each one uses vendor-specific proprietary algorithms π for the benefit of users, there's a real need for a standardized challenge-response algorithm. That allows multi-sourcing of token purchases and validation systems, which helps democratize strong authentication π
Also, this specification describes how to create short symmetric key-based "electronic signatures". These signatures are variants of challenge-response mode, where the data to be signed becomes the challenge or is used to derive the challenge π heads up that the terms 'electronic signature' and 'signature' are used interchangeably in this document π
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 lays out the main requirements that drove the design of this algorithm π a lot of emphasis went on flexibility and usability, within the constraints and specificity of the HMAC-based One-Time Password (HOTP) algorithm [RFC4226] and hardware token capabilities. main character energy π
- R1 - The algorithm MUST support challenge-response-based authentication. β¨
- R2 - The algorithm MUST be capable of supporting symmetric key-based short electronic signatures. Basically, this is a variation of challenge-response where the challenge is derived from the data that needs to be signed π₯
- R3 - The algorithm MUST be capable of supporting server authentication, whereby the user can verify that he/she is talking to a trusted server. Trust check, periodt π
- R4 - The algorithm SHOULD use HOTP [RFC4226] as a key building block. π§
- R5 - The length and format of the input challenge SHOULD be configurable. π¦
- R6 - The output length and format of the generated response SHOULD be configurable. π
- R7 - The challenge MAY be generated with integrity checking (e.g., parity bits). This lets tokens with pin pads do simple error checking when the user enters the challenge value into a token π
- R8 - There MUST be a unique secret (key) for each token/soft token that is shared between the token and the authentication server. The keys MUST be randomly generated or derived using a key derivation algorithm. no cap, this one's serious π
- R9 - The algorithm MAY enable additional data attributes, such as a timestamp or session information, to be included in the computation. These data inputs MAY be used individually or all together. β
4. OCRA Background πΈ
OATH introduced the HOTP algorithm as a first open, freely available building block for strengthening authentication for end-users in a variety of applications π one-time passwords are super efficient at solving specific security issues, thanks to the dynamic nature of OTP computations. β¨
After carefully analyzing different use cases, OATH concluded that providing extensions to the HOTP algorithms was important π¦ a very natural extension is a challenge mode for computing HOTP values based on random questions. Just as valuable is being able to do mutual authentication between two parties, or short-signature computation for authenticating transactions to improve the security of e-commerce applications π
4.1. HOTP Algorithm π§
The HOTP algorithm, as defined in [RFC4226], is based on an increasing counter value and a static symmetric key known only to the prover and verifier parties.
As a reminder:
HOTP(K,C) = Truncate(HMAC-SHA1(K,C))
where Truncate represents the function that converts an HMAC-SHA-1 value into an HOTP value.
We refer the reader to [RFC4226] for the full description and further details on the rationale and security analysis of HOTP π
The present document describes the different variants based on similar constructions as HOTP. π«Ά
5. Definition of OCRA π
The OATH Challenge-Response Algorithm (OCRA) is a generalization of HOTP, with variable data inputs that are not solely based on an incremented counter and secret key values π
The definition of OCRA requires a cryptographic function, a key K, and a set of DataInput parameters. This section first formally introduces OCRA, then introduces the definitions and default values recommended for all parameters. π
In a nutshell:
OCRA = CryptoFunction(K, DataInput)
where:
- K: a shared secret key known to both parties π
- DataInput: a structure that contains the concatenation of the various input data values, defined in detail in section 5.1 π
- CryptoFunction: this is the function that performs the OCRA computation from the secret key K and the DataInput material π§
CryptoFunction is described in detail in Section 5.2 β¨
5.1. DataInput Parameters β¨
Okay bestie, this structure is basically one big byte array π§΅ made by gluing together the OCRASuite value from section 6 and all the other parameters, except the secret key K π. K stays out of the mix.
DataInput = {OCRASuite | 00 | C | Q | P | S | T} where:
OCRASuiteis a value representing the suite of operations to compute an OCRA response00is a byte value used as a separatorCis an unsigned 8-byte counter value processed high-order bit first, and MUST be synchronized between all parties; It loops around from"{Hex}0"to"{Hex}FFFFFFFFFFFFFFFF"and then starts over at"{Hex}0". Note that 'C' is optional for all OCRA modes described in this document. πQ, mandatory, is a 128-byte list of (concatenated) challenge question(s) generated by the parties; if Q is less than 128 bytes, then it should be padded with zeroes to the right π§©Pis a hash (SHA-1 [RFC3174], SHA-256 and SHA-512 [SHA2] are supported) value of PIN/password that is known to all parties during the execution of the algorithm; the length of P will depend on the hash function that is used πSis a UTF-8 [RFC3629] encoded string of length up to 512 bytes that contains information about the current session; the length of S is defined in the OCRASuite string ποΈTis an 8-byte unsigned integer in big-endian order (i.e., network byte order) representing the number of time-steps (seconds, minutes, hours, or days depending on the specified granularity) since midnight UTC of January 1, 1970 [UT]. More specifically, if the OCRA computation includes a timestamp T, you should first convert your current local time to UTC time; you can then derive the UTC time in the proper format (i.e., seconds, minutes, hours, or days elapsed from epoch time); the size of the time-step is specified in the OCRASuite string as described in Section 6.3 β°
When you're computing a response, the concatenation order is always the following, no exceptions π :
C |
OTHER-PARTY-GENERATED-CHALLENGE-QUESTION |
YOUR-GENERATED-CHALLENGE-QUESTION |
P| S | T
If a value is empty (i.e., a certain input is not used in the computation) then the value is simply not represented in the string. So no empty placeholders, just skip it π
The counter on the token or client MUST be incremented every time a new computation is requested by the user. The server's counter value MUST only be incremented after a successful OCRA authentication. π¨ This part is so important, the counters are the whole reason things stay in sync π
5.2. CryptoFunction π§
The default CryptoFunction is HOTP-SHA1-6, i.e., the default mode of computation for OCRA is HOTP with the default 6-digit dynamic truncation and a combination of DataInput values as the message to compute the HMAC-SHA1 digest. Iconic default, no notes π
We denote t as the length in decimal digits of the truncation output. For instance, if t = 6, then the output of the truncation is a 6-digit (decimal) value. π’
We define the HOTP family of functions as an extension to HOTP:
- HOTP-H-t: these are the different possible truncated versions of HOTP, using the dynamic truncation method for extracting an HOTP value from the HMAC output
- We will denote HOTP-H-t as the realization of an HOTP function that uses an HMAC function with the hash function H, and the dynamic truncation as described in [RFC4226] to extract a t-digit value
- t=0 means that no truncation is performed and the full HMAC value is used for authentication purposes π¦
We list the following preferred modes of computation, where * denotes the default CryptoFunction:
HOTP-SHA1-4: HOTP with SHA-1 as the hash function for HMAC and a dynamic truncation to a 4-digit value; this mode is not recommended in the general case, but it can be useful when a very short authentication code is needed by an application πHOTP-SHA1-6: HOTP with SHA-1 as the hash function for HMAC and a dynamic truncation to a 6-digit value πΈHOTP-SHA1-8: HOTP with SHA-1 as the hash function for HMAC and a dynamic truncation to an 8-digit value β¨HOTP-SHA256-6: HOTP with SHA-256 as the hash function for HMAC and a dynamic truncation to a 6-digit value πHOTP-SHA512-6: HOTP with SHA-512 as the hash function for HMAC and a dynamic truncation to a 6-digit value π
This table summarizes all possible values for the CryptoFunction π:
+---------------+--------------------+-------------------------+
| Name | HMAC Function Used | Size of Truncation (t) |
+---------------+--------------------+-------------------------+
| HOTP-SHA1-t | HMAC-SHA1 | 0 (no truncation), 4-10 |
| HOTP-SHA256-t | HMAC-SHA256 | 0 (no truncation), 4-10 |
| HOTP-SHA512-t | HMAC-SHA512 | 0 (no truncation), 4-10 |
+---------------+--------------------+-------------------------+
Table 1: CryptoFunction Table
6. The OCRASuite π
An OCRASuite value is a text string that captures one mode of operation for OCRA, completely specifying the various options for that computation. It's basically the full outfit description for one computation π. An OCRASuite value is represented as follows:
<Algorithm>:<CryptoFunction>:<DataInput>
The OCRASuite value is the concatenation of three sub-components that are described below. Some example OCRASuite strings are described in Section 6.4 π§.
The client and server need to agree on one or two values of OCRASuite. These values may be agreed upon at the time of token provisioning or, for more sophisticated client-server interactions, these values may be negotiated for every transaction π€.
The provisioning of OCRA keys and related metadata such as OCRASuite is out of scope for this document. [RFC6030] specifies one key container specification that facilitates provisioning of such data between the client and the server π¦.
Note that for Mutual Challenge-Response or Signature with Server Authentication modes, the client and server will need to agree on two values of OCRASuite -- one for server computation and another for client computation π―.
6.1. Algorithm π§
Description: Indicates the version of OCRA.
Values: OCRA-v where v represents the version number (e.g., 1, 2). This document specifies version 1 of OCRA.
6.2. CryptoFunction π
Description: Indicates the function used to compute OCRA values.
Values: Permitted values are described in Section 5.2.
6.3. DataInput π
Description: This component of the OCRASuite string captures the list of valid inputs for that computation; [] indicates a value is optional:
[C] | QFxx | [PH | Snnn | TG] : Challenge-Response computation
[C] | QFxx | [PH | TG] : Plain Signature computation
Each input that is used for the computation is represented by a single letter (except Q), and they are separated by a hyphen. Cute and tidy π.
The input for challenge is further qualified by the formats supported by the client for challenge question(s). Supported values can be:
+------------------+-------------------+
| Format (F) | Up to Length (xx) |
+------------------+-------------------+
| A (alphanumeric) | 04-64 |
| N (numeric) | 04-64 |
| H (hexadecimal) | 04-64 |
+------------------+-------------------+
Table 2: Challenge Format Table
The default challenge format is N08, numeric and up to 8 digits. π’
The input for P is further qualified by the hash function used for the PIN/password. Supported values for hash function can be:
Hash function (H) - SHA1, SHA256, SHA512.
The default hash function for P is SHA1. π
The input for S is further qualified by the length of the session data in bytes. The client and server could agree to any length but the typical values are:
Length (nnn) - 064, 128, 256, and 512.
The default length is 064 bytes. ποΈ
The input for timestamps is further qualified by G, size of the time-step. G can be specified in number of seconds, minutes, or hours β±οΈ:
+--------------------+------------------------------+
| Time-Step Size (G) | Examples |
+--------------------+------------------------------+
| [1-59]S | number of seconds, e.g., 20S |
| [1-59]M | number of minutes, e.g., 5M |
| [0-48]H | number of hours, e.g., 24H |
+--------------------+------------------------------+
Table 3: Time-step Size Table
Default value for G is 1M, i.e., time-step size is one minute and the T represents the number of minutes since epoch time [UT]. Main character energy π.
6.4. OCRASuite Examples π
Here are some examples of OCRASuite strings, bestie π«Ά:
"OCRA-1:HOTP-SHA512-8:C-QN08-PSHA1"means version 1 of OCRA with HMAC-SHA512 function, truncated to an 8-digit value, using the counter, a random challenge, and a SHA1 digest of the PIN/password as parameters. It also indicates that the client supports only numeric challenge up to 8 digits in length π₯"OCRA-1:HOTP-SHA256-6:QA10-T1M"means version 1 of OCRA with HMAC-SHA256 function, truncated to a 6-digit value, using a random alphanumeric challenge up to 10 characters in length and a timestamp in number of minutes since epoch time π¦"OCRA-1:HOTP-SHA1-4:QH8-S512"means version 1 of OCRA with HMAC-SHA1 function, truncated to a 4-digit value, using a random hexadecimal challenge up to 8 nibbles and a session value of 512 bytes π§
7. Algorithm Modes for Authentication πβ¨
This section describes the typical modes in which the above defined computation can be used for authentication. Okay, the fun part is coming up, so stay with me π.
7.1. One-Way Challenge-Response
okay so a challenge-response is basically a security move where the verifier asks the prover a question (the challenge), and the prover has to come back with a correct answer (the response) to get authenticated πβ¨
so for one-way challenge-response, the verifier sends over a challenge value (usually randomly generated π²), the prover uses that challenge in the computation like we talked about above, and then the prover sends the response back so they can be authenticated π
in this mode, the typical data inputs look like this:
C- Counter, optional.Q- Challenge question, mandatory, supplied by the verifier.P- Hashed version of PIN/password, optional.S- Session information, optional.T- Timestamp, optional.
this diagram shows the message exchange between the client (prover) and the server (verifier) for a one-way challenge-response. it's giving very clean back-and-forth energy π¦
it's assumed that the client and server already share a pre-shared key K that gets used in the computation ποΈ
CLIENT SERVER
(PROVER) VERIFIER)
| |
| Verifier sends challenge to prover |
| Challenge = Q |
|<---------------------------------------|
| |
| Prover Computes Response |
| R = OCRA(K, {[C] | Q | [P | S | T]}) |
| Prover sends Response = R |
|--------------------------------------->|
| |
| Verifier Validates Response |
| If Response is valid, Server sends OK |
| If Response is not, Server sends NOK |
|<---------------------------------------|
| |
7.2. Mutual Challenge-Response
this one is a glow-up of the one-way version where the client and server both authenticate each other π«ΆπΈ
here's how it goes: the client starts by sending a random client-challenge to the server. then the server computes the server-response and sends it back to the client along with a server-challenge π
the client checks the server-response first so it knows it's actually talking to a legit server (no sus servers allowed π ββοΈ). after that, the client computes the client-response and sends it over to authenticate itself. the server verifies that client-response and that finishes off the two-way authentication π
in this mode there are two computations: the client-response and the server-response. there are two separate challenge questions, one generated by each party. we call these challenge questions Q1 and Q2 π§
typical data inputs for the server-response computation are:
C- Counter, optional.QC- Challenge question, mandatory, supplied by the client.QS- Challenge question, mandatory, supplied by the server.S- Session information, optional.T- Timestamp, optional.
typical data inputs for the client-response computation are:
C- Counter, optional.QS- Challenge question, mandatory, supplied by the server.QC- Challenge question, mandatory, supplied by the client.P- Hashed version of PIN/password, optional.S- Session information, optional.T- Timestamp, optional.
the following diagram shows the messages going back and forth between the client and server for a full two-way mutual challenge-response. it's so organized it's giving me a headache in the best way π€©
it's assumed that the client and server have a pre-shared key K (or a pair of keys if they're using dual-key mode of computation) that gets used in the computation π
CLIENT SERVER
(PROVER) (VERIFIER)
| |
| 1. Client sends client-challenge |
| QC = Client-challenge |
|------------------------------------------------->|
| |
| 2. Server computes server-response |
| and sends server-challenge |
| RS = OCRA(K, [C] | QC | QS | [S | T]) |
| QS = Server-challenge |
| Response = RS, QS |
|<-------------------------------------------------|
| |
| 3. Client verifies server-response |
| and computes client-response |
| OCRA(K, [C] | QC | QS | [S | T]) != RS -> STOP |
| RC = OCRA(K, [C] | QS | QC | [P | S | T]) |
| Response = RC |
|------------------------------------------------->|
| |
| 4. Server verifies client-response |
| OCRA(K, [C] | QS | QC | [P|S|T]) != RC -> STOP |
| Response = OK |
|<-------------------------------------------------|
| |
7.3. Algorithm Modes for Signature
okay now let's talk about the modes where this whole computation gets used for electronic signatures βοΈπ here are the typical ones we're covering π¦
7.3.1. Plain Signature
so in plain signature mode, the server sends a signature-challenge value to the client (the signer) π the signature-challenge is either the data you want signed, or something derived from that data using a hash function, for example π₯
the client uses the signature-challenge in the computation like we described above. then the client sends the signature value (the response) back to the server to authenticate β¨
in this mode, the data inputs are:
C- Counter, optional.QS- Signature-challenge, mandatory, supplied by the server.P- Hashed version of PIN/password, optional.T- Timestamp, optional.
the picture below shows the messages exchanged between the client (prover) and the server (verifier) for a plain signature operation πΌοΈ
it's assumed that the client and server have a pre-shared key K that gets used in the computation ποΈ
CLIENT SERVER
(PROVER) (VERIFIER)
| |
| Verifier sends signature-challenge |
| Challenge = QS |
|<------------------------------------------|
| |
| Client Computes Response |
| SIGN = OCRA(K, [C] | QS | [P | T]) |
| Response = SIGN |
|------------------------------------------>|
| |
| Verifier Validates Response |
| Response = OK |
|<------------------------------------------|
| |
7.3.2. Signature with Server Authentication
this mode is basically plain signature mode with a glow-up π the client can authenticate the server first before it generates an electronic signature, so nobody's signing for a fake server π
to use this one, the client starts by sending a random client-challenge to the server. the server computes the server-response and sends it back to the client along with a signature-challenge π
the client checks the server-response first to make sure it's talking to a valid server. only after that does it compute the signature and send it over π
in this mode there are two computations: the client-signature and the server-response.
typical data inputs for the server-response computation are:
C- Counter, optional.QC- Challenge question, mandatory, supplied by the client.QS- Signature-challenge, mandatory, supplied by the server.T- Timestamp, optional.
typical data inputs for the client-signature computation are:
C- Counter, optional.QC- Challenge question, mandatory, supplied by the client.QS- Signature-challenge, mandatory, supplied by the server.P- Hashed version of PIN/password, optional.T- Timestamp, optional.
the diagram below shows the messages exchanged between the client and server for a signature with server authentication transaction. it's the full package π
it's assumed that the client and server have a pre-shared key K (or a pair of keys if using dual-key mode of computation) that gets used in the computation π
CLIENT SERVER
(PROVER) VERIFIER)
| |
| 1. Client sends client-challenge |
| QC = Client-challenge |
|-------------------------------------------------->|
| |
| 2. Server computes server-response |
| and sends signature-challenge |
| RS = OCRA(K, [C] | QC | QS | [T]) |
| QS = signature-challenge |
| Response = RS, QS |
|<--------------------------------------------------|
| |
| 3. Client verifies server-response |
| and computes signature |
| OCRA(K, [C] | QC | QS | [T]) != RS -> STOP |
| SIGN = OCRA( K, [C] | QS | QC | [P | T]) |
| Response = SIGN |
|-------------------------------------------------->|
| |
| 4. Server verifies Signature |
| OCRA(K, [C] | QS | QC | [P|T]) != SIGN -> STOP |
| Response = OK |
|<--------------------------------------------------|
| |
8. Security Considerations π‘οΈβ οΈ
okay bestie, this part is serious, so let's get into it π₯Ί any algorithm is only as secure as the applications and authentication protocols that implement it π so this section talks about the critical security requirements that our algorithm choice puts on the authentication protocol and the validation software. no shortcuts π
8.1. Security Analysis of OCRA
the security and strength of this algorithm depend on the properties of the building block underneath it, HOTP. HOTP is built on HMAC [RFC2104] using SHA-1 [RFC3174] (or SHA-256 or SHA-512 [SHA2]) as the hash function π§©
the conclusion of the security analysis in [RFC4226] is that, for all practical purposes, the outputs of the dynamic truncation on distinct counter inputs are uniformly and independently distributed strings. β¨ that's a big deal, iykyk
the analysis also shows that the best possible attack against the HOTP function is the brute force attack π
8.2. Implementation Considerations β¨
okay so this is the implementation checklist, bestie π and it's giving "do these or your system gets weird." Here we go π
IC1 - In the authentication mode, the client MUST support two-factor authentication π. That means checking something you know (a secret code like a password, pass phrase, or PIN π) and something you have (a token πͺ). The secret code is only known by the user, and they usually type it in with the Response value for authentication. Or, instead of sending the something-you-know to the server, the client can use a hash of the password or PIN inside the computation itself, so two-factor happens implicitly. Iconic π
IC2 - Keys SHOULD be the same length as the CryptoFunction output so everyone plays nicely together π«Ά
IC3 - Keys SHOULD be picked at random, or with a cryptographically strong pseudo-random generator that's been properly seeded with a random value π². We RECOMMEND following [RFC4086] for all pseudo-random and random generations, no cap π§ . The pseudo-random numbers used for key generation SHOULD pass the randomness test in [CN] β
IC4 - Challenge questions SHOULD be 20-byte values, and they MUST be at least t-byte values, where t is the digit-length of the OCRA truncation output πΈ
IC5 - On the client side, the keys SHOULD live in a tamper-resistant device or be securely built into a software app π. Also, putting the keys in a hardware device gives you extra mobility for the whole auth system, which is lowkey a big win π¦
IC6 - All communication SHOULD happen over a secure channel, like SSL/TLS [RFC5246] or IPsec connections π‘οΈ
IC7 - OCRA in mutual authentication mode or in signature with server authentication mode MAY use dual-key mode ποΈβ¨. That means there are two keys shared between the client and the server. One key makes the server response on the server side and checks it on the client side. The other key makes the response or signature on the client side and checks it on the server side. Two keys, double the vibes π
IC8 - We recommend that implementations MAY use the session information, S, as an extra input in the computation π§. For example, S could be the session identifier from the TLS session. This helps guard against certain man-in-the-middle attacks π ββοΈ. BUT, it adds a dependency: the prover needs access to the session identifier to compute the response, and the verifier needs it too to check the response π« . [RFC5056] has a relevant discussion about using Channel Bindings to Secure Channels, so go read that if you're curious π
IC9 - In signature mode, if the counter or time (both optional elements) aren't used in the computation, there might be a risk of replay attacks β οΈ. Implementers should think carefully about this in light of their application requirements and security guidelines π€. The server SHOULD also, whenever possible, give the client (if it's able) a way to verify that the signature challenge is valid β
IC10 - We also RECOMMEND storing the keys securely in the validation system π. Specifically, encrypt them with tamper-resistant hardware encryption and only expose them when you actually need to. For example, decrypt the key when you need to verify an OCRA response, then re-encrypt it right away so it sits in RAM for as short a time as possible π. The key store MUST be in a secure area, to avoid direct attacks on the validation system and secrets database as much as possible π°. Especially, access to the key material should be limited to only the programs and processes the validation system needs π«Ά
9. Conclusion π
okay wrap-up time π This document introduced several variants of HOTP for challenge-response-based authentication and short signature-like computations β¨
The OCRASuite makes it super easy to integrate and support different flavors inside an authentication and validation system π
And finally, OCRA should enable mutual authentication in both connected and off-line modes, with support for different response sizes and modes of operation π¦ Literally the whole vibe β¨
10. Acknowledgements π«Ά
Huge thanks to Jeff Burstein, Shuh Chang, Oanh Hoang, Philip Hoyer, Jon Martinsson, Frederik Mennes, Mingliang Pei, Jonathan Tuliani, Stu Vaeth, Enrique Rodriguez, and Robert Zuccherato π for their comments and suggestions that made this document better πΈ
11. References π
11.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.
[RFC3174] Eastlake, D. and P. Jones, "US Secure Hash Algorithm 1
(SHA1)", RFC 3174, September 2001.
[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
10646", STD 63, RFC 3629, November 2003.
[RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness
Requirements 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>.
11.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>.
[OATH] Initiative for Open Authentication, "OATH Vision",
<http://www.openauthentication.org/about>.
[RFC5056] Williams, N., "On the Use of Channel Bindings to Secure
Channels", RFC 5056, November 2007.
[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",
<http://en.wikipedia.org/wiki/Unix_time>.
Appendix A. Reference Implementation π»β¨
okay bestie, here's the reference implementation π«Ά it's a Java OCRA class that builds the message, runs HMAC, and does the truncation. the copyright header is kept exactly as written π
/**
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 javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
/**
* This an example implementation of OCRA.
* Visit www.openauthentication.org for more information.
*
* @author Johan Rydell, PortWise
*/
public class OCRA {
private OCRA() {}
/**
* 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_sha1(String crypto,
byte[] keyBytes, byte[] text){
Mac hmac = null;
try {
hmac = Mac.getInstance(crypto);
SecretKeySpec macKey =
new SecretKeySpec(keyBytes, "RAW");
hmac.init(macKey);
return hmac.doFinal(text);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
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 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];
System.arraycopy(bArray, 1, ret, 0, ret.length);
return ret;
}
/**
* This method generates an OCRA HOTP value for the given
* set of parameters.
*
* @param ocraSuite the OCRA Suite
* @param key the shared secret, HEX encoded
* @param counter the counter that changes on a per use
* basis, HEX encoded
* @param question the challenge question, HEX encoded
* @param password a password that can be used, HEX encoded
* @param sessionInformation Static information that identifies
* the current session, Hex encoded
* @param timeStamp a value that reflects a time
*
* @return A numeric String in base 10 that includes
* {@link truncationDigits} digits
*/
static public String generateOCRA(String ocraSuite,
String key,
String counter,
String question,
String password,
String sessionInformation,
String timeStamp){
int codeDigits = 0;
String crypto = "";
String result = null;
int ocraSuiteLength = (ocraSuite.getBytes()).length;
int counterLength = 0;
int questionLength = 0;
int passwordLength = 0;
int sessionInformationLength = 0;
int timeStampLength = 0;
// The OCRASuites components
String CryptoFunction = ocraSuite.split(":")[1];
String DataInput = ocraSuite.split(":")[2];
if(CryptoFunction.toLowerCase().indexOf("sha1") > 1)
crypto = "HmacSHA1";
if(CryptoFunction.toLowerCase().indexOf("sha256") > 1)
crypto = "HmacSHA256";
if(CryptoFunction.toLowerCase().indexOf("sha512") > 1)
crypto = "HmacSHA512";
// How many digits should we return
codeDigits = Integer.decode(CryptoFunction.substring(
CryptoFunction.lastIndexOf("-")+1));
// The size of the byte array message to be encrypted
// Counter
if(DataInput.toLowerCase().startsWith("c")) {
// Fix the length of the HEX string
while(counter.length() < 16)
counter = "0" + counter;
counterLength=8;
}
// Question - always 128 bytes
if(DataInput.toLowerCase().startsWith("q") ||
(DataInput.toLowerCase().indexOf("-q") >= 0)) {
while(question.length() < 256)
question = question + "0";
questionLength=128;
}
// Password - sha1
if(DataInput.toLowerCase().indexOf("psha1") > 1){
while(password.length() < 40)
password = "0" + password;
passwordLength=20;
}
// Password - sha256
if(DataInput.toLowerCase().indexOf("psha256") > 1){
while(password.length() < 64)
password = "0" + password;
passwordLength=32;
}
// Password - sha512
if(DataInput.toLowerCase().indexOf("psha512") > 1){
while(password.length() < 128)
password = "0" + password;
passwordLength=64;
}
// sessionInformation - s064
if(DataInput.toLowerCase().indexOf("s064") > 1){
while(sessionInformation.length() < 128)
sessionInformation = "0" + sessionInformation;
sessionInformationLength=64;
}
// sessionInformation - s128
if(DataInput.toLowerCase().indexOf("s128") > 1){
while(sessionInformation.length() < 256)
sessionInformation = "0" + sessionInformation;
sessionInformationLength=128;
}
// sessionInformation - s256
if(DataInput.toLowerCase().indexOf("s256") > 1){
while(sessionInformation.length() < 512)
sessionInformation = "0" + sessionInformation;
sessionInformationLength=256;
}
// sessionInformation - s512
if(DataInput.toLowerCase().indexOf("s512") > 1){
while(sessionInformation.length() < 1024)
sessionInformation = "0" + sessionInformation;
sessionInformationLength=512;
}
// TimeStamp
if(DataInput.toLowerCase().startsWith("t") ||
(DataInput.toLowerCase().indexOf("-t") > 1)){
while(timeStamp.length() < 16)
timeStamp = "0" + timeStamp;
timeStampLength=8;
}
// Remember to add "1" for the "00" byte delimiter
byte[] msg = new byte[ocraSuiteLength +
counterLength +
questionLength +
passwordLength +
sessionInformationLength +
timeStampLength +
1];
// Put the bytes of "ocraSuite" parameters into the message
byte[] bArray = ocraSuite.getBytes();
System.arraycopy(bArray, 0, msg, 0, bArray.length);
// Delimiter
msg[bArray.length] = 0x00;
// Put the bytes of "Counter" to the message
// Input is HEX encoded
if(counterLength > 0 ){
bArray = hexStr2Bytes(counter);
System.arraycopy(bArray, 0, msg, ocraSuiteLength + 1,
bArray.length);
}
// Put the bytes of "question" to the message
// Input is text encoded
if(questionLength > 0 ){
bArray = hexStr2Bytes(question);
System.arraycopy(bArray, 0, msg, ocraSuiteLength + 1 +
counterLength, bArray.length);
}
// Put the bytes of "password" to the message
// Input is HEX encoded
if(passwordLength > 0){
bArray = hexStr2Bytes(password);
System.arraycopy(bArray, 0, msg, ocraSuiteLength + 1 +
counterLength + questionLength, bArray.length);
}
// Put the bytes of "sessionInformation" to the message
// Input is text encoded
if(sessionInformationLength > 0 ){
bArray = hexStr2Bytes(sessionInformation);
System.arraycopy(bArray, 0, msg, ocraSuiteLength + 1 +
counterLength + questionLength +
passwordLength, bArray.length);
}
// Put the bytes of "time" to the message
// Input is text value of minutes
if(timeStampLength > 0){
bArray = hexStr2Bytes(timeStamp);
System.arraycopy(bArray, 0, msg, ocraSuiteLength + 1 +
counterLength + questionLength +
passwordLength + sessionInformationLength,
bArray.length);
}
bArray = hexStr2Bytes(key);
byte[] hash = hmac_sha1(crypto, bArray, 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;
}
}
Appendix B. Test Vectors Generation π§ͺπ
ngl this one is the test vector generator π₯Ή it's a Java TestOCRA class with an asHex helper and a main that sets up the inputs, so you can check your own build against the RFC's numbers. the copyright header is the same one from Appendix A π
/**
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.math.BigInteger;
import java.util.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class TestOCRA {
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
String ocra = "";
String seed = "";
String ocraSuite = "";
String counter = "";
String password = "";
String sessionInformation = "";
String question = "";
String qHex = "";
String timeStamp = "";
// PASS1234 is SHA1 hash of "1234"
String PASS1234 = "7110eda4d09e062aa5e4a390b0a572ac0d2c0220";
Okay bestie, the test vector code keeps going π§π
System.out.println(
"Key: Standard 64Byte Q(Signature challenge): "
+ question);
System.out.println(" T: "
+ timeStamp.toUpperCase() + " OCRA: "
+ ocra);
}
}catch (Exception e){
System.out.println("Error : " + e);
}
}
}
<CODE ENDS>
Appendix C. Test Vectors π§ͺβ¨
Bestie, this is the goodie bag! π These are the test values you can use to check that your OCRA implementation plays nicely with everyone else's during interoperability testing π
Here are the keys we'll be using. The Standard 20Byte key: value is:
3132333435363738393031323334353637383930
The Standard 32Byte key: value is:
3132333435363738393031323334353637383930313233343536373839303132
The Standard 64Byte key: value is:
313233343536373839303132333435363738393031323334353637383930313233343
53637383930313233343536373839303132333435363738393031323334
And the PIN (1234) SHA1 hash value: is:
7110eda4d09e062aa5e4a390b0a572ac0d2c0220
C.1. One-Way Challenge Response πΈ
Okay so this is the one-way challenge-response set, and the first table is the Standard 20Byte key with a bunch of Q values. Each row pairs a challenge with the OCRA value it should produce π¦
+-----------------+----------+------------+
| Key | Q | OCRA Value |
+-----------------+----------+------------+
| Standard 20Byte | 00000000 | 237653 |
| Standard 20Byte | 11111111 | 243178 |
| Standard 20Byte | 22222222 | 653583 |
| Standard 20Byte | 33333333 | 740991 |
| Standard 20Byte | 44444444 | 608993 |
| Standard 20Byte | 55555555 | 388898 |
| Standard 20Byte | 66666666 | 816933 |
| Standard 20Byte | 77777777 | 224598 |
| Standard 20Byte | 88888888 | 750600 |
| Standard 20Byte | 99999999 | 294470 |
+-----------------+----------+------------+
This set uses the suite OCRA-1:HOTP-SHA1-6:QN08 π
OCRA-1:HOTP-SHA1-6:QN08
Next up is the Standard 32Byte key with a counter C in the mix π₯
+-----------------+---+----------+------------+
| Key | C | Q | OCRA Value |
+-----------------+---+----------+------------+
| Standard 32Byte | 0 | 12345678 | 65347737 |
| Standard 32Byte | 1 | 12345678 | 86775851 |
| Standard 32Byte | 2 | 12345678 | 78192410 |
| Standard 32Byte | 3 | 12345678 | 71565254 |
| Standard 32Byte | 4 | 12345678 | 10104329 |
| Standard 32Byte | 5 | 12345678 | 65983500 |
| Standard 32Byte | 6 | 12345678 | 70069104 |
| Standard 32Byte | 7 | 12345678 | 91771096 |
| Standard 32Byte | 8 | 12345678 | 75011558 |
| Standard 32Byte | 9 | 12345678 | 08522129 |
+-----------------+---+----------+------------+
That one runs on OCRA-1:HOTP-SHA1-6:QN08... wait, no, the suite for this table is the one below π Here it is:
OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1
Now the Standard 32Byte key with a fresh set of Q values, same vibe as before β¨
+-----------------+----------+------------+
| Key | Q | OCRA Value |
+-----------------+----------+------------+
| Standard 32Byte | 00000000 | 83238735 |
| Standard 32Byte | 11111111 | 01501458 |
| Standard 32Byte | 22222222 | 17957585 |
| Standard 32Byte | 33333333 | 86776967 |
| Standard 32Byte | 44444444 | 86807031 |
+-----------------+----------+------------+
And its suite:
OCRA-1:HOTP-SHA256-8:QN08-PSHA1
Next, the Standard 64Byte key goes full counter-mode with C values 00000 to 00009 π
+-----------------+-------+----------+------------+
| Key | C | Q | OCRA Value |
+-----------------+-------+----------+------------+
| Standard 64Byte | 00000 | 00000000 | 07016083 |
| Standard 64Byte | 00001 | 11111111 | 63947962 |
| Standard 64Byte | 00002 | 22222222 | 70123924 |
| Standard 64Byte | 00003 | 33333333 | 25341727 |
| Standard 64Byte | 00004 | 44444444 | 33203315 |
| Standard 64Byte | 00005 | 55555555 | 34205738 |
| Standard 64Byte | 00006 | 66666666 | 44343969 |
| Standard 64Byte | 00007 | 77777777 | 51946085 |
| Standard 64Byte | 00008 | 88888888 | 20403879 |
| Standard 64Byte | 00009 | 99999999 | 31409299 |
+-----------------+-------+----------+------------+
Suite time:
OCRA-1:HOTP-SHA512-8:C-QN08
The last one in this section adds a T (time) column, with the Standard 64Byte key and T value 132d0b6 π°οΈπ
+-----------------+----------+---------+------------+
| Key | Q | T | OCRA Value |
+-----------------+----------+---------+------------+
| Standard 64Byte | 00000000 | 132d0b6 | 95209754 |
| Standard 64Byte | 11111111 | 132d0b6 | 55907591 |
| Standard 64Byte | 22222222 | 132d0b6 | 22048402 |
| Standard 64Byte | 33333333 | 132d0b6 | 24218844 |
| Standard 64Byte | 44444444 | 132d0b6 | 36209546 |
+-----------------+----------+---------+------------+
And the suite for that one:
OCRA-1:HOTP-SHA512-8:QN08-T1M
C.2. Mutual Challenge-Response π€π
Mutual challenge-response means both sides compute, so the server and client each get their own suite lines π«Ά
The server computation uses this suite:
OCRASuite (server computation) = OCRA-1:HOTP-SHA256-8:QA08
And the client computation uses this one:
OCRASuite (client computation) = OCRA-1:HOTP-SHA256-8:QA08
First, the client-side challenges (the CLI values) with the Standard 32Byte key π
+-----------------+------------------+------------+
| Key | Q | OCRA Value |
+-----------------+------------------+------------+
| Standard 32Byte | CLI22220SRV11110 | 28247970 |
| Standard 32Byte | CLI22221SRV11111 | 01984843 |
| Standard 32Byte | CLI22222SRV11112 | 65387857 |
| Standard 32Byte | CLI22223SRV11113 | 03351211 |
| Standard 32Byte | CLI22224SRV11114 | 83412541 |
+-----------------+------------------+------------+
Then the server computes with this label:
Server -- OCRA-1:HOTP-SHA256-8:QA08
Now the server-side challenges (the SRV values) π
+-----------------+------------------+------------+
| Key | Q | OCRA Value |
+-----------------+------------------+------------+
| Standard 32Byte | SRV11110CLI22220 | 15510767 |
| Standard 32Byte | SRV11111CLI22221 | 90175646 |
| Standard 32Byte | SRV11112CLI22222 | 33777207 |
| Standard 32Byte | SRV11113CLI22223 | 95285278 |
| Standard 32Byte | SRV11114CLI22224 | 28934924 |
+-----------------+------------------+------------+
And the client's label for that one:
Client -- OCRA-1:HOTP-SHA256-8:QA08
Now the second mutual set uses SHA512, and the suites are different for server and client. Look at them! π
OCRASuite (server computation) = OCRA-1:HOTP-SHA512-8:QA08
OCRASuite (client computation) = OCRA-1:HOTP-SHA512-8:QA08-PSHA1
Client-side CLI challenges with the Standard 64Byte key πΈ
+-----------------+------------------+------------+
| Key | Q | OCRA Value |
+-----------------+------------------+------------+
| Standard 64Byte | CLI22220SRV11110 | 79496648 |
| Standard 64Byte | CLI22221SRV11111 | 76831980 |
| Standard 64Byte | CLI22222SRV11112 | 12250499 |
| Standard 64Byte | CLI22223SRV11113 | 90856481 |
| Standard 64Byte | CLI22224SRV11114 | 12761449 |
+-----------------+------------------+------------+
The server label for this set:
Server -- OCRA-1:HOTP-SHA512-8:QA08
Server-side SRV challenges, same key:
+-----------------+------------------+------------+
| Key | Q | OCRA Value |
+-----------------+------------------+------------+
| Standard 64Byte | SRV11110CLI22220 | 18806276 |
| Standard 64Byte | SRV11111CLI22221 | 70020315 |
| Standard 64Byte | SRV11112CLI22222 | 01600026 |
| Standard 64Byte | SRV11113CLI22223 | 18951020 |
| Standard 64Byte | SRV11114CLI22224 | 32528969 |
+-----------------+------------------+------------+
And the client label, with the PSHA1 suite π
Client -- OCRA-1:HOTP-SHA512-8:QA08-PSHA1
C.3. Plain Signature βοΈπ¦
In this mode, Q is the signature challenge, so it's giving signing vibes π«
Here's the Standard 32Byte key set with SIG challenges:
+-----------------+----------+------------+
| Key | Q | OCRA Value |
+-----------------+----------+------------+
| Standard 32Byte | SIG10000 | 53095496 |
| Standard 32Byte | SIG11000 | 04110475 |
| Standard 32Byte | SIG12000 | 31331128 |
| Standard 32Byte | SIG13000 | 76028668 |
| Standard 32Byte | SIG14000 | 46554205 |
+-----------------+----------+------------+
And its suite:
OCRA-1:HOTP-SHA256-8:QA08
Last but definitely not least, the Standard 64Byte key with longer SIG challenges and a T column π
+-----------------+------------+---------+------------+
| Key | Q | T | OCRA Value |
+-----------------+------------+---------+------------+
| Standard 64Byte | SIG1000000 | 132d0b6 | 77537423 |
| Standard 64Byte | SIG1100000 | 132d0b6 | 31970405 |
| Standard 64Byte | SIG1200000 | 132d0b6 | 10235557 |
| Standard 64Byte | SIG1300000 | 132d0b6 | 95213541 |
| Standard 64Byte | SIG1400000 | 132d0b6 | 65360607 |
+-----------------+------------+---------+------------+
And the final suite label:
OCRA-1:HOTP-SHA512-8:QA10-T1M
Authors' Addresses ππ
Meet the crew who built this! Here's where you can find each of them π«Ά
David M'Raihi:
David M'Raihi
Verisign, Inc.
487 E. Middlefield Road
Mountain View, CA 94043
USA
EMail: davidietf@gmail.com
Johan Rydell:
Johan Rydell
Portwise, Inc.
275 Hawthorne Ave, Suite 119
Palo Alto, CA 94301
USA
EMail: johanietf@gmail.com
Siddharth Bajaj:
Siddharth Bajaj
Symantec Corp.
350 Ellis Street
Mountain View, CA 94043
USA
EMail: siddharthietf@gmail.com
Salah Machani:
Salah Machani
Diversinet Corp.
2225 Sheppard Avenue East, Suite 1801
Toronto, Ontario M2J 5C2
Canada
EMail: smachani@diversinet.com
David Naccache:
David Naccache
Ecole Normale Superieure
ENS DI, 45 rue d'Ulm
Paris, 75005
France
EMail: david.naccache@ens.fr
That's a wrap, bestie! ππβ¨
π¦ where this page comes from
- ietf: rfc6287 2011-06
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms