Internet Engineering Task Force (IETF)                        D. M'Raihi
Request for Comments: 6287                                Verisign, Inc.
Category: Informational                                        J. Rydell
ISSN: 2070-1721                                           Portwise, Inc.
                                                                S. Bajaj
                                                          Symantec Corp.
                                                              S. Machani
                                                        Diversinet Corp.
                                                             D. Naccache
                                                Ecole Normale Superieure
                                                               June 2011
        
Internet Engineering Task Force (IETF)                        D. M'Raihi
Request for Comments: 6287                                Verisign, Inc.
Category: Informational                                        J. Rydell
ISSN: 2070-1721                                           Portwise, Inc.
                                                                S. Bajaj
                                                          Symantec Corp.
                                                              S. Machani
                                                        Diversinet Corp.
                                                             D. Naccache
                                                Ecole Normale Superieure
                                                               June 2011
        

OCRA: OATH Challenge-Response Algorithm

OCRA:誓言挑战响应算法

Abstract

摘要

This document describes an algorithm for challenge-response authentication developed by the Initiative for Open Authentication (OATH). The specified mechanisms leverage the HMAC-based One-Time Password (HOTP) algorithm and offer one-way and mutual authentication, and electronic signature capabilities.

本文档描述了由开放式身份验证计划(SWORD)开发的质询-响应身份验证算法。指定的机制利用基于HMAC的一次性密码(HOTP)算法,并提供单向和相互身份验证以及电子签名功能。

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.

本文件是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。它已经接受了公众审查,并已被互联网工程指导小组(IESG)批准出版。并非IESG批准的所有文件都适用于任何级别的互联网标准;见RFC 5741第2节。

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/rfc6287.

有关本文件当前状态、任何勘误表以及如何提供反馈的信息,请访问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.

版权所有(c)2011 IETF信托基金和确定为文件作者的人员。版权所有。

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

本文件受BCP 78和IETF信托有关IETF文件的法律规定的约束(http://trustee.ietf.org/license-info)自本文件出版之日起生效。请审阅这些文件

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.

请仔细阅读,因为他们描述了您对本文件的权利和限制。从本文件中提取的代码组件必须包括信托法律条款第4.e节中所述的简化BSD许可证文本,并提供简化BSD许可证中所述的无担保。

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
        
   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
        
1. Introduction
1. 介绍

The Initiative for Open Authentication (OATH) [OATH] has identified several use cases and scenarios that require an asynchronous variant to accommodate users who do not want to maintain a synchronized authentication system. A commonly accepted method for this is to use a challenge-response scheme.

开放身份验证计划(OREAN)[OREAN]已经确定了几个用例和场景,这些用例和场景需要一个异步变体来适应不希望维护同步身份验证系统的用户。对此,一种普遍接受的方法是使用质询-响应方案。

Such a challenge-response mode of authentication is widely adopted in the industry. Several vendors already offer software applications and hardware devices implementing challenge-response -- but each of those uses vendor-specific proprietary algorithms. For the benefits of users there is a need for a standardized challenge-response algorithm that allows multi-sourcing of token purchases and validation systems to facilitate the democratization of strong authentication.

这种认证的质询-响应模式在业界被广泛采用。一些供应商已经提供了实现质询响应的软件应用程序和硬件设备,但它们都使用特定于供应商的专有算法。为了用户的利益,需要一种标准化的质询-响应算法,该算法允许代币购买和验证系统的多来源,以促进强身份验证的民主化。

Additionally, this specification describes the means to create symmetric key-based short 'electronic signatures'. Such signatures are variants of challenge-response mode where the data to be signed becomes the challenge or is used to derive the challenge. Note that the term 'electronic signature' and 'signature' are used interchangeably in this document.

此外,本规范描述了创建基于对称密钥的短“电子签名”的方法。此类签名是质询响应模式的变体,其中待签名的数据成为质询或用于导出质询。请注意,“电子签名”和“签名”在本文件中互换使用。

2. Notation and Terminology
2. 符号和术语

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

本文件中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“应”、“不应”、“建议”、“可”和“可选”应按照[RFC2119]中所述进行解释。

3. Algorithm Requirements
3. 算法要求

This section presents the main requirements that drove this algorithm design. A lot of emphasis was placed on flexibility and usability, under the constraints and specificity of the HMAC-based One-Time Password (HOTP) algorithm [RFC4226] and hardware token capabilities.

本节介绍了驱动该算法设计的主要需求。在基于HMAC的一次性密码(HOTP)算法[RFC4226]和硬件令牌功能的约束和特殊性下,人们非常重视灵活性和可用性。

R1 - The algorithm MUST support challenge-response-based authentication.

R1-算法必须支持基于质询-响应的身份验证。

R2 - The algorithm MUST be capable of supporting symmetric key-based short electronic signatures. Essentially, this is a variation of challenge-response where the challenge is derived from the data that needs to be signed.

R2-算法必须能够支持基于对称密钥的短电子签名。本质上,这是质询响应的一种变体,质询来自需要签名的数据。

R3 - The algorithm MUST be capable of supporting server authentication, whereby the user can verify that he/she is talking to a trusted server.

R3-该算法必须能够支持服务器身份验证,用户可以通过该算法验证他/她是否正在与受信任的服务器通信。

R4 - The algorithm SHOULD use HOTP [RFC4226] as a key building block.

R4-算法应使用HOTP[RFC4226]作为关键构建块。

R5 - The length and format of the input challenge SHOULD be configurable.

R5-输入质询的长度和格式应该是可配置的。

R6 - The output length and format of the generated response SHOULD be configurable.

R6-生成响应的输出长度和格式应该是可配置的。

R7 - The challenge MAY be generated with integrity checking (e.g., parity bits). This will allow tokens with pin pads to perform simple error checking when the user enters the challenge value into a token.

R7-质询可通过完整性检查(例如奇偶校验位)生成。这将允许带有pin焊盘的令牌在用户将质询值输入令牌时执行简单的错误检查。

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.

R8-令牌和身份验证服务器之间共享的每个令牌/软令牌必须具有唯一的密钥。必须使用密钥派生算法随机生成或派生密钥。

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.

R9-该算法可使额外的数据属性(如时间戳或会话信息)包括在计算中。这些数据输入可以单独使用,也可以一起使用。

4. OCRA Background
4. OCRA背景

OATH introduced the HOTP algorithm as a first open, freely available building block towards strengthening authentication for end-users in a variety of applications. One-time passwords are very efficient at solving specific security issues thanks to the dynamic nature of OTP computations.

誓言将HOTP算法作为第一个开放的、免费可用的构建块引入,以加强各种应用中最终用户的身份验证。由于OTP计算的动态特性,一次性密码在解决特定安全问题时非常有效。

After carefully analyzing different use cases, OATH came to the conclusion that providing for extensions to the HOTP algorithms was important. A very natural extension is to introduce a challenge mode for computing HOTP values based on random questions. Equally beneficial is being able to perform mutual authentication between two parties, or short-signature computation for authenticating transaction to improve the security of e-commerce applications.

在仔细分析了不同的用例之后,誓言得出结论,为HOTP算法提供扩展非常重要。一个非常自然的扩展是引入一种基于随机问题计算HOTP值的挑战模式。同样有益的是,能够在双方之间执行相互认证,或短签名计算来认证交易,以提高电子商务应用程序的安全性。

4.1. HOTP Algorithm
4.1. HOTP算法

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.

[RFC4226]中定义的HOTP算法基于递增的计数器值和仅验证方和验证方已知的静态对称密钥。

   As a reminder:
                     HOTP(K,C) = Truncate(HMAC-SHA1(K,C))
        
   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.

其中Truncate表示将HMAC-SHA-1值转换为HOTP值的函数。

We refer the reader to [RFC4226] for the full description and further details on the rationale and security analysis of HOTP.

我们请读者参考[RFC4226]以获取有关HOTP的基本原理和安全性分析的完整描述和进一步详细信息。

The present document describes the different variants based on similar constructions as HOTP.

本文件描述了基于与HOTP类似结构的不同变体。

5. Definition of OCRA
5. OCRA的定义

The OATH Challenge-Response Algorithm (OCRA) is a generalization of HOTP with variable data inputs not solely based on an incremented counter and secret key values.

誓言挑战响应算法(OCRA)是HOTP的推广,具有可变数据输入,而不仅仅基于递增计数器和密钥值。

The definition of OCRA requires a cryptographic function, a key K and a set of DataInput parameters. This section first formally introduces OCRA and then introduces the definitions and default values recommended for all parameters.

OCRA的定义需要加密函数、密钥K和一组数据输入参数。本节首先正式介绍OCRA,然后介绍为所有参数推荐的定义和默认值。

In a nutshell, OCRA = CryptoFunction(K, DataInput)

简而言之,OCRA=加密函数(K,数据输入)

where:

哪里:

o K: a shared secret key known to both parties

o K:双方都知道的共享密钥

o DataInput: a structure that contains the concatenation of the various input data values defined in details in section 5.1

o DataInput:包含第5.1节中详细定义的各种输入数据值的串联的结构

o CryptoFunction: this is the function performing the OCRA computation from the secret key K and the DataInput material;

o CryptoFunction:这是从密钥K和数据输入材料执行OCRA计算的函数;

CryptoFunction is described in details in Section 5.2

第5.2节详细描述了加密函数

5.1. DataInput Parameters
5.1. 数据输入参数

This structure is the concatenation over byte array of the OCRASuite value as defined in section 6 with the different parameters used in the computation, save for the secret key K.

该结构是第6节中定义的OCRASuite值的字节数组与计算中使用的不同参数的串联,除了密钥K。

   DataInput = {OCRASuite | 00 | C | Q | P | S | T} where:
        
   DataInput = {OCRASuite | 00 | C | Q | P | S | T} where:
        

o OCRASuite is a value representing the suite of operations to compute an OCRA response

o OCRASuite是一个值,表示计算OCRA响应的一系列操作

o 00 is a byte value used as a separator

o 00是用作分隔符的字节值

o C is 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.

o C是一个无符号8字节计数器值,首先处理高阶位,并且必须在各方之间同步;它从“{Hex}0”循环到“{Hex}ffffffffffff”,然后从“{Hex}0”开始。请注意,对于本文档中描述的所有OCRA模式,“C”是可选的。

o 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

o Q、 必填项,是由双方生成的(串联)质询问题的128字节列表;如果Q小于128字节,则应在右侧用零填充

o P is 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

o P是算法执行期间各方已知的PIN/密码的散列值(支持SHA-1[RFC3174]、SHA-256和SHA-512[SHA2]);P的长度取决于所使用的哈希函数

o S is 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

o S是一个UTF-8[RFC3629]编码字符串,长度为512字节,包含有关当前会话的信息;S的长度在OCRASuite字符串中定义

o T is 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

o T是一个8字节的无符号整数,以大端顺序(即网络字节顺序)表示自1970年1月1日[UT]UTC午夜以来的时间步数(秒、分钟、小时或天,具体取决于指定的粒度)。更具体地说,如果OCRA计算包括时间戳T,则应首先将当前本地时间转换为UTC时间;然后,您可以以适当的格式导出UTC时间(即从历元时间起经过的秒、分钟、小时或天);时间步长的大小在OCRASuite字符串中指定,如第6.3节所述

When computing a response, the concatenation order is always the following:

计算响应时,连接顺序始终如下所示:

C |

C|

OTHER-PARTY-GENERATED-CHALLENGE-QUESTION |

对方提出的挑战问题|

YOUR-GENERATED-CHALLENGE-QUESTION |

你的问题|

P| S | T

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.

如果某个值为空(即,计算中未使用某个输入),则该值不在字符串中表示。

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.

每次用户请求新计算时,令牌或客户端上的计数器都必须递增。只有在成功进行OCRA身份验证后,服务器的计数器值才能增加。

5.2. CryptoFunction
5.2. 加密函数

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.

默认的加密函数是HOTP-SHA1-6,即OCRA的默认计算模式是HOTP,默认的6位动态截断和数据输入值的组合作为计算HMAC-SHA1摘要的消息。

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.

我们将t表示为截断输出的十进制数长度。例如,如果t=6,则截断的输出为6位(十进制)值。

We define the HOTP family of functions as an extension to HOTP:

我们将HOTP函数族定义为HOTP的扩展:

1. 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

1. HOTP-H-t:这些是HOTP的不同可能的截断版本,使用动态截断方法从HMAC输出中提取HOTP值

2. 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

2. 我们将HOTP-H-t表示为HOTP函数的实现,该函数使用HMAC函数和散列函数H,以及[RFC4226]中所述的动态截断来提取t位值

3. t=0 means that no truncation is performed and the full HMAC value is used for authentication purposes

3. t=0表示不执行截断,完整的HMAC值用于身份验证

We list the following preferred modes of computation, where * denotes the default CryptoFunction:

我们列出了以下首选计算模式,其中*表示默认加密函数:

o 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

o HOTP-SHA1-4:HOTP使用SHA-1作为HMAC的哈希函数,并动态截断为4位值;一般情况下不建议使用此模式,但当应用程序需要非常短的身份验证代码时,此模式非常有用

o HOTP-SHA1-6: HOTP with SHA-1 as the hash function for HMAC and a dynamic truncation to a 6-digit value

o HOTP-SHA1-6:HOTP使用SHA-1作为HMAC的哈希函数,并动态截断为6位值

o HOTP-SHA1-8: HOTP with SHA-1 as the hash function for HMAC and a dynamic truncation to an 8-digit value

o HOTP-SHA1-8:HOTP使用SHA-1作为HMAC的哈希函数,并动态截断为8位值

o HOTP-SHA256-6: HOTP with SHA-256 as the hash function for HMAC and a dynamic truncation to a 6-digit value

o HOTP-SHA256-6:HOTP使用SHA-256作为HMAC的哈希函数,并动态截断为6位值

o HOTP-SHA512-6: HOTP with SHA-512 as the hash function for HMAC and a dynamic truncation to a 6-digit value

o HOTP-SHA512-6:HOTP使用SHA-512作为HMAC的哈希函数,并动态截断为6位值

This table summarizes all possible values for the CryptoFunction:

此表总结了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 |
     +---------------+--------------------+-------------------------+
        
     +---------------+--------------------+-------------------------+
     |      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

表1:加密函数表

6. The OCRASuite
6. 奥克拉苏岩

An OCRASuite value is a text string that captures one mode of operation for OCRA, completely specifying the various options for that computation. An OCRASuite value is represented as follows:

OCRASuite值是一个文本字符串,用于捕获OCRA的一种操作模式,完全指定该计算的各种选项。OCRASuite值表示如下:

                  <Algorithm>:<CryptoFunction>:<DataInput>
        
                  <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.

OCRASuite值是下面描述的三个子组件的串联。第6.4节介绍了一些OCRASuite字符串示例。

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.

客户端和服务器需要就OCRASuite的一个或两个值达成一致。这些值可以在令牌供应时商定,或者,对于更复杂的客户机-服务器交互,可以为每个事务协商这些值。

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.

OCRA密钥和相关元数据(如OCRASuite)的提供超出了本文档的范围。[RFC6030]指定一个密钥容器规范,该规范有助于在客户端和服务器之间提供此类数据。

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.

请注意,对于具有服务器身份验证模式的相互质询响应或签名,客户端和服务器需要在OCRASuite的两个值上达成一致——一个用于服务器计算,另一个用于客户端计算。

6.1. Algorithm
6.1. 算法

Description: Indicates the version of OCRA.

描述:表示OCRA的版本。

Values: OCRA-v where v represents the version number (e.g., 1, 2). This document specifies version 1 of OCRA.

值:OCRA-v,其中v表示版本号(例如,1、2)。本文件规定了OCRA的第1版。

6.2. CryptoFunction
6.2. 加密函数

Description: Indicates the function used to compute OCRA values

描述:表示用于计算OCRA值的函数

Values: Permitted values are described in Section 5.2.

值:第5.2节描述了允许值。

6.3. DataInput
6.3. 数据输入

Description: This component of the OCRASuite string captures the list of valid inputs for that computation; [] indicates a value is optional:

描述:OCRASuite字符串的此组件捕获该计算的有效输入列表;[]表示值是可选的:

[C] | QFxx | [PH | Snnn | TG] : Challenge-Response computation

[C] | QFxx |[PH | Snnn | TG]:挑战响应计算

[C] | QFxx | [PH | TG] : Plain Signature computation

[C] | QFxx |[PH | TG]:普通签名计算

Each input that is used for the computation is represented by a single letter (except Q), and they are separated by a hyphen.

用于计算的每个输入都用一个字母表示(Q除外),并用连字符分隔。

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       |
                 +------------------+-------------------+
        
                 +------------------+-------------------+
                 |    Format (F)    | Up to Length (xx) |
                 +------------------+-------------------+
                 | A (alphanumeric) |       04-64       |
                 |    N (numeric)   |       04-64       |
                 |  H (hexadecimal) |       04-64       |
                 +------------------+-------------------+
        

Table 2: Challenge Format Table

表2:挑战格式表

The default challenge format is N08, numeric and up to 8 digits.

默认质询格式为N08,数字,最多8位。

The input for P is further qualified by the hash function used for the PIN/password. Supported values for hash function can be:

P的输入由用于PIN/密码的哈希函数进一步限定。哈希函数支持的值可以是:

Hash function (H) - SHA1, SHA256, SHA512.

散列函数(H)-SHA1、SHA256、SH512。

The default hash function for P is SHA1.

P的默认哈希函数是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:

会话数据的长度(以字节为单位)进一步限定S的输入。客户机和服务器可以同意任何长度,但典型值为:

Length (nnn) - 064, 128, 256, and 512.

长度(nnn)-064、128、256和512。

The default length is 064 bytes.

默认长度为064字节。

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:

时间戳的输入进一步由时间步长的大小G限定。G可以以秒、分钟或小时为单位指定:

           +--------------------+------------------------------+
           | 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  |
           +--------------------+------------------------------+
        
           +--------------------+------------------------------+
           | 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

表3:时间步长表

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

G的默认值为1M,即时间步长为1分钟,T表示自历元时间[UT]以来的分钟数。

6.4. OCRASuite Examples
6.4. 奥克拉苏岩实例

Here are some examples of OCRASuite strings:

以下是OCRASuite字符串的一些示例:

o "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

o “OCRA-1:HOTP-SHA512-8:C-QN08-PSHA1”指具有HMAC-SHA512功能的OCRA版本1,使用计数器、随机质询和PIN/密码的SHA1摘要作为参数,将其截断为8位数值。它还表示客户端仅支持长度不超过8位的数字质询

o "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

o “OCRA-1:HOTP-SHA256-6:QA10-T1M”是指具有HMAC-SHA256功能的OCRA第1版,使用随机字母数字挑战,长度不超过10个字符,时间戳自历元时间起以分钟为单位,截断为6位数值

o "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

o “OCRA-1:HOTP-SHA1-4:QH8-S512”指带有HMAC-SHA1函数的OCRA版本1,使用随机十六进制质询(最多8个半字节)和512字节的会话值,将其截断为4位值

7. Algorithm Modes for Authentication
7. 身份验证的算法模式

This section describes the typical modes in which the above defined computation can be used for authentication.

本节描述了使用上述定义的计算进行身份验证的典型模式。

7.1. One-Way Challenge-Response
7.1. 单向挑战响应

A challenge-response is a security mechanism in which the verifier presents a question (challenge) to the prover, who must provide a valid answer (response) to be authenticated.

质询-响应是一种安全机制,其中验证者向验证者提出问题(质询),验证者必须提供有效答案(响应)以进行身份验证。

To use this algorithm for a one-way challenge-response, the verifier will communicate a challenge value (typically randomly generated) to the prover. The prover will use the challenge in the computation as described above. The prover then communicates the response to the verifier to authenticate.

为了将该算法用于单向质询响应,验证者将向验证者传达质询值(通常随机生成)。验证人将在上述计算中使用质询。验证方随后将响应传递给验证方进行验证。

Therefore in this mode, the typical data inputs will be:

因此,在此模式下,典型的数据输入为:

C - Counter, optional.

C-计数器,可选。

Q - Challenge question, mandatory, supplied by the verifier.

Q-质询问题,强制性,由验证者提供。

P - Hashed version of PIN/password, optional.

P-PIN/密码的哈希版本,可选。

S - Session information, optional.

S-会话信息,可选。

T - Timestamp, optional.

T-时间戳,可选。

The diagram below shows the message exchange between the client (prover) and the server (verifier) to complete a one-way challenge-response authentication.

下图显示了客户端(验证程序)和服务器(验证程序)之间的消息交换,以完成单向质询-响应身份验证。

It is assumed that the client and server have a pre-shared key K that is used for the computation.

假定客户端和服务器具有用于计算的预共享密钥K。

              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 |
                |<---------------------------------------|
                |                                        |
        
              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
7.2. 相互挑战响应

Mutual challenge-response is a variation of one-way challenge-response where both the client and server mutually authenticate each other.

相互质询响应是单向质询响应的一种变体,其中客户端和服务器相互验证。

To use this algorithm, the client will first send a random client-challenge to the server. The server computes the server-response and sends it to the client along with a server-challenge.

要使用此算法,客户端将首先向服务器发送随机客户端质询。服务器计算服务器响应并将其与服务器质询一起发送给客户端。

The client will first verify the server-response to be assured that it is talking to a valid server. It will then compute the client-response and send it to the server to authenticate. The server verifies the client-response to complete the two-way authentication process.

客户机将首先验证服务器响应,以确保它正在与有效的服务器通信。然后,它将计算客户端响应并将其发送到服务器进行身份验证。服务器验证客户端响应以完成双向身份验证过程。

In this mode there are two computations: client-response and server-response. There are two separate challenge questions, generated by both parties. We denote these challenge questions Q1 and Q2.

在这种模式下,有两种计算:客户端响应和服务器响应。双方提出了两个独立的质疑问题。我们表示这些挑战问题Q1和Q2。

Typical data inputs for server-response computation will be:

服务器响应计算的典型数据输入为:

C - Counter, optional.

C-计数器,可选。

QC - Challenge question, mandatory, supplied by the client.

QC-质询问题,强制性,由客户提供。

QS - Challenge question, mandatory, supplied by the server.

QS-质询问题,必填,由服务器提供。

S - Session information, optional.

S-会话信息,可选。

T - Timestamp, optional.

T-时间戳,可选。

Typical data inputs for client-response computation will be:

客户响应计算的典型数据输入为:

C - Counter, optional.

C - Counter, optional.translate error, please retry

QS - Challenge question, mandatory, supplied by the server.

QS-质询问题,必填,由服务器提供。

QC - Challenge question, mandatory, supplied by the client.

QC-质询问题,强制性,由客户提供。

P - Hashed version of PIN/password, optional.

P-PIN/密码的哈希版本,可选。

S - Session information, optional.

S-会话信息,可选。

T - Timestamp, optional.

T-时间戳,可选。

The following diagram shows the messages that are exchanged between the client and the server to complete a two-way mutual challenge-response authentication.

下图显示了客户端和服务器之间为完成双向相互质询-响应身份验证而交换的消息。

It is assumed that the client and server have a pre-shared key K (or pair of keys if using dual-key mode of computation) that is used for the computation.

假定客户端和服务器具有用于计算的预共享密钥K(如果使用双密钥计算模式,则为一对密钥)。

         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                                  |
           |<-------------------------------------------------|
           |                                                  |
        
         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
7.3. 签名的算法模式

In this section we describe the typical modes in which the above defined computation can be used for electronic signatures.

在本节中,我们将描述上述定义的计算可用于电子签名的典型模式。

7.3.1. Plain Signature
7.3.1. 普通签名

To use this algorithm in plain signature mode, the server will communicate a signature-challenge value to the client (signer). The signature-challenge is either the data to be signed or derived from the data to be signed using a hash function, for example.

要在普通签名模式下使用此算法,服务器将向客户端(签名者)传递签名质询值。例如,签名质询是要签名的数据或使用哈希函数从要签名的数据派生的数据。

The client will use the signature-challenge in the computation as described above. The client then communicates the signature value (response) to the server to authenticate.

客户端将在上述计算中使用签名质询。然后,客户端将签名值(响应)传递给服务器进行身份验证。

Therefore in this mode, the data inputs will be:

因此,在此模式下,数据输入将为:

C - Counter, optional.

C-计数器,可选。

QS - Signature-challenge, mandatory, supplied by the server.

QS-签名质询,必填,由服务器提供。

P - Hashed version of PIN/password, optional.

P-PIN/密码的哈希版本,可选。

T - Timestamp, optional.

T-时间戳,可选。

The picture below shows the messages that are exchanged between the client (prover) and the server (verifier) to complete a plain signature operation.

下图显示了客户端(验证程序)和服务器(验证程序)之间交换的消息,以完成普通签名操作。

It is assumed that the client and server have a pre-shared key K that is used for the computation.

假定客户端和服务器具有用于计算的预共享密钥K。

             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                          |
               |<------------------------------------------|
               |                                           |
        
             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
7.3.2. 具有服务器身份验证的签名

This mode is a variation of the plain signature mode where the client can first authenticate the server before generating a electronic signature.

此模式是普通签名模式的一种变体,其中客户端可以在生成电子签名之前首先对服务器进行身份验证。

To use this algorithm, the client will first send a random client-challenge to the server. The server computes the server-response and sends it to the client along with a signature-challenge.

要使用此算法,客户端将首先向服务器发送随机客户端质询。服务器计算服务器响应并将其与签名质询一起发送给客户端。

The client will first verify the server-response to authenticate that it is talking to a valid server. It will then compute the signature and send it to the server.

客户端将首先验证服务器响应,以验证它是否正在与有效的服务器通信。然后,它将计算签名并将其发送到服务器。

In this mode there are two computations: client-signature and server-response.

In this mode there are two computations: client-signature and server-response.translate error, please retry

Typical data inputs for server-response computation will be:

服务器响应计算的典型数据输入为:

C - Counter, optional.

C-计数器,可选。

QC - Challenge question, mandatory, supplied by the client.

QC-质询问题,强制性,由客户提供。

QS - Signature-challenge, mandatory, supplied by the server.

QS-签名质询,必填,由服务器提供。

T - Timestamp, optional.

T-时间戳,可选。

Typical data inputs for client-signature computation will be:

客户签名计算的典型数据输入为:

C - Counter, optional.

C-计数器,可选。

QC - Challenge question, mandatory, supplied by the client.

QC-质询问题,强制性,由客户提供。

QS - Signature-challenge, mandatory, supplied by the server.

QS-签名质询,必填,由服务器提供。

P - Hashed version of PIN/password, optional.

P-PIN/密码的哈希版本,可选。

T - Timestamp, optional.

T-时间戳,可选。

The diagram below shows the messages that are exchanged between the client and the server to complete a signature with server authentication transaction.

下图显示了客户端和服务器之间交换的消息,以完成带有服务器身份验证的签名事务。

It is assumed that the client and server have a pre-shared key K (or pair of keys if using dual-key mode of computation) that is used for the computation.

假定客户端和服务器具有用于计算的预共享密钥K(如果使用双密钥计算模式,则为一对密钥)。

        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                                  |
          |<--------------------------------------------------|
          |                                                   |
        
        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
8. 安全考虑

Any algorithm is only as secure as the application and the authentication protocols that implement it. Therefore, this section discusses the critical security requirements that our choice of algorithm imposes on the authentication protocol and validation software.

任何算法的安全性都取决于应用程序和实现它的身份验证协议。因此,本节讨论了我们选择的算法对身份验证协议和验证软件提出的关键安全要求。

8.1. Security Analysis of OCRA
8.1. OCRA的安全性分析

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 [RFC3174] (or SHA-256 or SHA-512 [SHA2]) as the hash function.

该算法的安全性和强度取决于底层构建块HOTP的属性,它是基于HMAC[RFC2104]的构造,使用SHA-1[RFC3174](或SHA-256或SHA-512[SHA2])作为哈希函数。

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

[RFC4226]中详述的安全性分析的结论是,出于所有实际目的,不同计数器输入上的动态截断输出是均匀和独立分布的字符串。

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

分析表明,针对HOTP函数的最佳可能攻击是蛮力攻击。

8.2. Implementation Considerations
8.2. 实施考虑

IC1 - In the authentication mode, the client MUST support two-factor authentication, i.e., the communication and verification of something you know (secret code such as a password, pass phrase, PIN code, etc.) and something you have (token). The secret code is known only to the user and usually entered with the Response value for authentication purpose (two-factor authentication). Alternatively, instead of sending something you know to the server, the client may use a hash of the password or PIN code in the computation itself, thus implicitly enabling two-factor authentication.

IC1-在身份验证模式中,客户端必须支持双因素身份验证,即对您知道的内容(密码、密码短语、PIN码等)和您拥有的内容(令牌)进行通信和验证。密码仅为用户所知,通常与响应值一起输入以用于身份验证(双因素身份验证)。或者,客户端可以在计算本身中使用密码或PIN码的散列,从而隐式地启用双因素身份验证,而不是向服务器发送您知道的内容。

IC2 - Keys SHOULD be of the length of the CryptoFunction output to facilitate interoperability.

IC2-密钥的长度应与CryptoFunction输出相同,以促进互操作性。

IC3 - Keys SHOULD be chosen at random or using a cryptographically strong pseudo-random generator properly seeded with a random value. We RECOMMEND following the recommendations in [RFC4086] for all pseudo-random and random generations. The pseudo-random numbers used for generating the keys SHOULD successfully pass the randomness test specified in [CN].

IC3-密钥应随机选择,或使用加密强伪随机生成器(使用随机值正确播种)。对于所有伪随机和随机生成,我们建议遵循[RFC4086]中的建议。用于生成密钥的伪随机数应成功通过[CN]中规定的随机性测试。

IC4 - Challenge questions SHOULD be 20-byte values and MUST be at least t-byte values where t stands for the digit-length of the OCRA truncation output.

IC4-挑战问题应为20字节值,且必须至少为t字节值,其中t代表OCRA截断输出的数字长度。

IC5 - On the client side, the keys SHOULD be embedded in a tamper-resistant device or securely implemented in a software application. Additionally, by embedding the keys in a hardware device, you also have the advantage of improving the flexibility (mobility) of the authentication system.

IC5-在客户端,密钥应嵌入防篡改设备或在软件应用程序中安全实现。此外,通过将密钥嵌入硬件设备,还可以提高身份验证系统的灵活性(移动性)。

IC6 - All the communications SHOULD take place over a secure channel, e.g., SSL/TLS [RFC5246], IPsec connections.

IC6-所有通信应通过安全通道进行,例如SSL/TLS[RFC5246],IPsec连接。

IC7 - OCRA, when used in mutual authentication mode or in signature with server authentication mode, MAY use dual-key mode -- i.e., there are two keys that are shared between the client and the server. One shared key is used to generate the server response on the server side and to verify it on the client side. The other key is used to create the response or signature on the client side and to verify it on the server side.

IC7-OCRA在相互身份验证模式或服务器签名身份验证模式下使用时,可以使用双密钥模式——即,客户端和服务器之间共享两个密钥。一个共享密钥用于在服务器端生成服务器响应,并在客户端验证它。另一个密钥用于在客户端创建响应或签名,并在服务器端验证它。

IC8 - We recommend that implementations MAY use the session information, S, as an additional input in the computation. For example, S could be the session identifier from the TLS session.

IC8-我们建议实现可以使用会话信息S作为计算中的额外输入。例如,S可以是TLS会话中的会话标识符。

This will mitigate against certain types of man-in-the-middle attacks. However, this will introduce the additional dependency that first of all the prover needs to have access to the session identifier to compute the response and the verifier will need access to the session identifier to verify the response. [RFC5056] contains a relevant discussion of using Channel Bindings to Secure Channels.

这将缓解某些类型的中间人攻击。然而,这将引入额外的依赖性,首先验证者需要访问会话标识符来计算响应,而验证者需要访问会话标识符来验证响应。[RFC5056]包含使用通道绑定保护通道的相关讨论。

IC9 - In the signature mode, whenever the counter or time (defined as optional elements) are not used in the computation, there might be a risk of replay attack and the implementers should carefully consider this issue in the light of their specific application requirements and security guidelines. The server SHOULD also provide whenever possible a mean for the client (if able) to verify the validity of the signature challenge.

IC9-在签名模式中,每当计数器或时间(定义为可选元素)在计算中不使用时,可能存在重放攻击的风险,并且实施者应根据其特定的应用要求和安全准则仔细考虑此问题。服务器还应尽可能为客户端(如果能够)提供验证签名质询有效性的方法。

IC10 - 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 OCRA response, and re-encrypted immediately to limit exposure in the RAM for 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.

IC10-我们还建议将密钥安全地存储在验证系统中,更具体地说,使用防篡改硬件加密进行加密,并仅在需要时公开密钥:例如,在需要验证OCRA响应时解密密钥,并立即重新加密,以限制在RAM中的短时间暴露。密钥存储必须位于安全区域,以尽可能避免对验证系统和机密数据库的直接攻击。特别是,对关键材料的访问应仅限于验证系统所需的程序和过程。

9. Conclusion
9. 结论

This document introduced several variants of HOTP for challenge-response-based authentication and short signature-like computations.

本文档介绍了几种用于基于质询-响应的身份验证和类似于短签名的计算的HOTP变体。

The OCRASuite provides for an easy integration and support of different flavors within an authentication and validation system.

OCRASuite在身份验证和验证系统中提供了对不同口味的轻松集成和支持。

Finally, OCRA should enable mutual authentication both in connected and off-line modes, with the support of different response sizes and mode of operations.

最后,OCRA应在连接和离线模式下支持相互认证,并支持不同的响应大小和操作模式。

10. Acknowledgements
10. 致谢

We would like to thank 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 to improve this document.

我们要感谢Jeff Burstein、Shuh Chang、Oanh Hoang、Philip Hoyer、Jon Martinsson、Frederik Mennes、Pei Mingliang、Jonathan Tuliani、Stu Vaeth、Enrique Rodriguez和Robert Zuccherato为改进本文件提出的意见和建议。

11. References
11. 工具书类
11.1. Normative References
11.1. 规范性引用文件

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

[RFC2104]Krawczyk,H.,Bellare,M.,和R.Canetti,“HMAC:用于消息认证的键控哈希”,RFC 2104,1997年2月。

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

[RFC2119]Bradner,S.,“RFC中用于表示需求水平的关键词”,BCP 14,RFC 2119,1997年3月。

[RFC3174] Eastlake, D. and P. Jones, "US Secure Hash Algorithm 1 (SHA1)", RFC 3174, September 2001.

[RFC3174]Eastlake,D.和P.Jones,“美国安全哈希算法1(SHA1)”,RFC 3174,2001年9月。

[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.

[RFC3629]Yergeau,F.,“UTF-8,ISO 10646的转换格式”,STD 63,RFC 3629,2003年11月。

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

[RFC4086]Eastlake,D.,Schiller,J.,和S.Crocker,“安全的随机性要求”,BCP 106,RFC 4086,2005年6月。

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

[RFC4226]M'Raihi,D.,Bellare,M.,Hoornaert,F.,Naccache,D.,和O.Ranen,“HOTP:基于HMAC的一次性密码算法”,RFC 42262005年12月。

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

[SHA2]NIST,“FIPS发布180-3:安全哈希标准(SHS)”,2008年10月<http://csrc.nist.gov/publications/fips/ fips180-3/fips180-3_final.pdf>。

11.2. Informative References
11.2. 资料性引用

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

[CN]Coron,J.和D.Naccache,“Maurer万能试验的准确评估”,LNCS 15561999年2月,<http://www.gemplus.com/smart/rd/publications/pdf/CN99maur.pdf>。

[OATH] Initiative for Open Authentication, "OATH Vision", <http://www.openauthentication.org/about>.

[誓言]开放认证倡议,“誓言愿景”<http://www.openauthentication.org/about>.

[RFC5056] Williams, N., "On the Use of Channel Bindings to Secure Channels", RFC 5056, November 2007.

[RFC5056]Williams,N.,“关于使用通道绑定保护通道”,RFC 5056,2007年11月。

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

[RFC5246]Dierks,T.和E.Rescorla,“传输层安全(TLS)协议版本1.2”,RFC 5246,2008年8月。

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

[RFC6030]Hoyer,P.,Pei,M.和S.Machani,“便携式对称密钥容器(PSKC)”,RFC 603012010年10月。

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

[UT]维基百科,“Unix时代”<http://en.wikipedia.org/wiki/Unix_time>.

Appendix A. Reference Implementation
附录A.参考实施

<CODE BEGINS>

<代码开始>

  /**
     Copyright (c) 2011 IETF Trust and the persons identified as
     authors of the code. All rights reserved.
        
  /**
     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). */

根据IETF信托有关IETF文件的法律规定第4.c节规定的简化BSD许可证中包含的许可条款,允许以源代码和二进制格式重新分发和使用,无论是否修改(http://trustee.ietf.org/license-info). */

  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.math.BigInteger;
        
  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 {
        
  /**
   * This an example implementation of OCRA.
   * Visit www.openauthentication.org for more information.
   *
   * @author Johan Rydell, PortWise
   */
  public class OCRA {
        
      private 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.
       */
        
      /**
       * 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");
        
      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;
      }
        
              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 };
        
      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();
        
      /**
       * 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;
      }
        
          // 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
        
      /**
       * 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){

*/静态公共字符串生成器CRA(字符串ocraSuite、字符串键、字符串计数器、字符串问题、字符串密码、字符串会话信息、字符串时间戳){

          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;
        
          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];
        
          // 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";
        
          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));
        
          // 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";
        
          // 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;
          }
        
              questionLength=128;
          }
        
          // Password - sha1
          if(DataInput.toLowerCase().indexOf("psha1") > 1){
              while(password.length() < 40)
                  password = "0" + password;
              passwordLength=20;
          }
        
          // 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 - 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;
          }
        
          // 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 - 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 - 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 - 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 - s512
          if(DataInput.toLowerCase().indexOf("s512") > 1){
              while(sessionInformation.length() < 1024)
        
                  sessionInformation = "0" + sessionInformation;
              sessionInformationLength=512;
          }
        
                  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;
          }
        
          // 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];
        
          // 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);
        
          // 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;
        
          // 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 "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 "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
        
          // 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);
        
          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 "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);
          }
        
          // 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);
        
          bArray = hexStr2Bytes(key);
        
          byte[] hash = hmac_sha1(crypto, bArray, msg);
        
          byte[] hash = hmac_sha1(crypto, bArray, msg);
        
          // put selected bytes into result int
          int offset = hash[hash.length - 1] & 0xf;
        
          // 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 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];

int otp=二进制%DIGITS_幂[码位];

          result = Integer.toString(otp);
          while (result.length() < codeDigits) {
              result = "0" + result;
          }
          return result;
      }
  }
        
          result = Integer.toString(otp);
          while (result.length() < codeDigits) {
              result = "0" + result;
          }
          return result;
      }
  }
        

<CODE ENDS>

<代码结束>

Appendix B. Test Vectors Generation
附录B.测试向量生成

<CODE BEGINS>

<代码开始>

  /**
     Copyright (c) 2011 IETF Trust and the persons identified as
     authors of the code. All rights reserved.
        
  /**
     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). */

根据IETF信托有关IETF文件的法律规定第4.c节规定的简化BSD许可证中包含的许可条款,允许以源代码和二进制格式重新分发和使用,无论是否修改(http://trustee.ietf.org/license-info). */

  import java.math.BigInteger;
  import java.util.*;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
        
  import java.math.BigInteger;
  import java.util.*;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
        

public class TestOCRA {

公共类TestOCRA{

  public static String asHex (byte buf[]) {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;
        
  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();
  }
        
      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) {
        
  /**
   * @param args
   */
  public static void main(String[] args) {
        
      String ocra = "";
      String seed = "";
      String ocraSuite = "";
      String counter = "";
      String password = "";
      String sessionInformation = "";
      String question = "";
        
      String ocra = "";
      String seed = "";
      String ocraSuite = "";
      String counter = "";
      String password = "";
      String sessionInformation = "";
      String question = "";
        
      String qHex = "";
      String timeStamp = "";
        
      String qHex = "";
      String timeStamp = "";
        
      // PASS1234 is SHA1 hash of "1234"
      String PASS1234 = "7110eda4d09e062aa5e4a390b0a572ac0d2c0220";
        
      // PASS1234 is SHA1 hash of "1234"
      String PASS1234 = "7110eda4d09e062aa5e4a390b0a572ac0d2c0220";
        
      String SEED = "3132333435363738393031323334353637383930";
      String SEED32 = "31323334353637383930313233343536373839" +
          "30313233343536373839303132";
      String SEED64 = "31323334353637383930313233343536373839" +
          "3031323334353637383930313233343536373839" +
          "3031323334353637383930313233343536373839" +
          "3031323334";
      int STOP = 5;
        
      String SEED = "3132333435363738393031323334353637383930";
      String SEED32 = "31323334353637383930313233343536373839" +
          "30313233343536373839303132";
      String SEED64 = "31323334353637383930313233343536373839" +
          "3031323334353637383930313233343536373839" +
          "3031323334353637383930313233343536373839" +
          "3031323334";
      int STOP = 5;
        
      Date myDate = Calendar.getInstance().getTime();
      BigInteger b = new BigInteger("0");
      String sDate = "Mar 25 2008, 12:06:30 GMT";
        
      Date myDate = Calendar.getInstance().getTime();
      BigInteger b = new BigInteger("0");
      String sDate = "Mar 25 2008, 12:06:30 GMT";
        
      try{
          DateFormat df =
              new SimpleDateFormat("MMM dd yyyy, HH:mm:ss zzz");
          myDate = df.parse(sDate);
          b = new BigInteger("0" + myDate.getTime());
          b = b.divide(new BigInteger("60000"));
        
      try{
          DateFormat df =
              new SimpleDateFormat("MMM dd yyyy, HH:mm:ss zzz");
          myDate = df.parse(sDate);
          b = new BigInteger("0" + myDate.getTime());
          b = b.divide(new BigInteger("60000"));
        
          System.out.println("Time of \"" + sDate + "\" is in");
          System.out.println("milli sec: " + myDate.getTime());
          System.out.println("minutes: " + b.toString());
          System.out.println("minutes (HEX encoded): "
              + b.toString(16).toUpperCase());
          System.out.println("Time of \"" + sDate
              + "\" is the same as this localized");
          System.out.println("time, \""
              + new Date(myDate.getTime()) + "\"");
        
          System.out.println("Time of \"" + sDate + "\" is in");
          System.out.println("milli sec: " + myDate.getTime());
          System.out.println("minutes: " + b.toString());
          System.out.println("minutes (HEX encoded): "
              + b.toString(16).toUpperCase());
          System.out.println("Time of \"" + sDate
              + "\" is the same as this localized");
          System.out.println("time, \""
              + new Date(myDate.getTime()) + "\"");
        
          System.out.println();
          System.out.println("Standard 20Byte key: " +
              "3132333435363738393031323334353637383930");
          System.out.println("Standard 32Byte key: " +
              "3132333435363738393031323334353637383930");
          System.out.println("                     " +
              "313233343536373839303132");
          System.out.println("Standard 64Byte key: 313233343536373839"
              + "3031323334353637383930");
          System.out.println("                     313233343536373839"
              + "3031323334353637383930");
        
          System.out.println();
          System.out.println("Standard 20Byte key: " +
              "3132333435363738393031323334353637383930");
          System.out.println("Standard 32Byte key: " +
              "3132333435363738393031323334353637383930");
          System.out.println("                     " +
              "313233343536373839303132");
          System.out.println("Standard 64Byte key: 313233343536373839"
              + "3031323334353637383930");
          System.out.println("                     313233343536373839"
              + "3031323334353637383930");
        
          System.out.println("                     313233343536373839"
              + "3031323334353637383930");
          System.out.println("                     31323334");
        
          System.out.println("                     313233343536373839"
              + "3031323334353637383930");
          System.out.println("                     31323334");
        
          System.out.println();
          System.out.println("Plain challenge response");
          System.out.println("========================");
          System.out.println();
        
          System.out.println();
          System.out.println("Plain challenge response");
          System.out.println("========================");
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA1-6:QN08";
          System.out.println(ocraSuite);
          System.out.println("=======================");
          seed = SEED;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              question = "" + i + i + i + i + i + i + i + i;
              qHex = new String((new BigInteger(question,10))
                         .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                             qHex,password,
                             sessionInformation,timeStamp);
               System.out.println("Key: Standard 20Byte  Q: "
                      + question + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA1-6:QN08";
          System.out.println(ocraSuite);
          System.out.println("=======================");
          seed = SEED;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              question = "" + i + i + i + i + i + i + i + i;
              qHex = new String((new BigInteger(question,10))
                         .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                             qHex,password,
                             sessionInformation,timeStamp);
               System.out.println("Key: Standard 20Byte  Q: "
                      + question + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1";
          System.out.println(ocraSuite);
          System.out.println("=================================");
          seed = SEED32;
          counter = "";
          question = "12345678";
          password = PASS1234;
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              counter = "" + i;
              qHex = new String((new BigInteger(question,10))
                         .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                         qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 32Byte  C: "
                           + counter + "  Q: "
                           + question + "  PIN(1234): ");
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1";
          System.out.println(ocraSuite);
          System.out.println("=================================");
          seed = SEED32;
          counter = "";
          question = "12345678";
          password = PASS1234;
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              counter = "" + i;
              qHex = new String((new BigInteger(question,10))
                         .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                         qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 32Byte  C: "
                           + counter + "  Q: "
                           + question + "  PIN(1234): ");
        
              System.out.println(password + "  OCRA: " + ocra);
          }
          System.out.println();
        
              System.out.println(password + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QN08-PSHA1";
          System.out.println(ocraSuite);
          System.out.println("===============================");
          seed = SEED32;
          counter = "";
          question = "";
          password = PASS1234;
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "" + i + i + i + i + i + i + i + i;
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QN08-PSHA1";
          System.out.println(ocraSuite);
          System.out.println("===============================");
          seed = SEED32;
          counter = "";
          question = "";
          password = PASS1234;
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "" + i + i + i + i + i + i + i + i;
        
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 32Byte  Q: "
                          + question + "  PIN(1234): ");
              System.out.println(password + "  OCRA: " + ocra);
          }
          System.out.println();
        
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 32Byte  Q: "
                          + question + "  PIN(1234): ");
              System.out.println(password + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:C-QN08";
          System.out.println(ocraSuite);
          System.out.println("===========================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              question = "" + i + i + i + i + i + i + i + i;
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              counter = "0000" + i;
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 64Byte  C: "
                       + counter + "  Q: "
                       + question + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:C-QN08";
          System.out.println(ocraSuite);
          System.out.println("===========================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < 10; i++){
              question = "" + i + i + i + i + i + i + i + i;
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              counter = "0000" + i;
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
              System.out.println("Key: Standard 64Byte  C: "
                       + counter + "  Q: "
                       + question + "  OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:QN08-T1M";
          System.out.println(ocraSuite);
          System.out.println("=============================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = b.toString(16);
          for(int i=0; i < STOP; i++){
              question = "" + i + i + i + i + i + i + i + i;
              counter = "";
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:QN08-T1M";
          System.out.println(ocraSuite);
          System.out.println("=============================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = b.toString(16);
          for(int i=0; i < STOP; i++){
              question = "" + i + i + i + i + i + i + i + i;
              counter = "";
              qHex = new String((new BigInteger(question,10))
                          .toString(16)).toUpperCase();
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                       qHex,password,sessionInformation,timeStamp);
        
              System.out.println("Key: Standard 64Byte  Q: "
                          + question +"  T: "
                            + timeStamp.toUpperCase()
                          + "  OCRA: " + ocra);
          }
          System.out.println();
        
              System.out.println("Key: Standard 64Byte  Q: "
                          + question +"  T: "
                            + timeStamp.toUpperCase()
                          + "  OCRA: " + ocra);
          }
          System.out.println();
        
          System.out.println();
          System.out.println("Mutual Challenge Response");
          System.out.println("=========================");
          System.out.println();
        
          System.out.println();
          System.out.println("Mutual Challenge Response");
          System.out.println("=========================");
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QA08";
          System.out.println("OCRASuite (server computation) = "
                             + ocraSuite);
          System.out.println("OCRASuite (client computation) = "
                             + ocraSuite);
          System.out.println("===============================" +
              "===========================");
          seed = SEED32;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "CLI2222" + i + "SRV1111" + i;
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
        
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QA08";
          System.out.println("OCRASuite (server computation) = "
                             + ocraSuite);
          System.out.println("OCRASuite (client computation) = "
                             + ocraSuite);
          System.out.println("===============================" +
              "===========================");
          seed = SEED32;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "CLI2222" + i + "SRV1111" + i;
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
        
                       "(server)Key: Standard 32Byte  Q: "
                       + question + "  OCRA: "
                       + ocra);
              question = "SRV1111" + i + "CLI2222" + i;
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                       "(client)Key: Standard 32Byte  Q: "
                       + question + "  OCRA: "
                       + ocra);
          }
          System.out.println();
        
                       "(server)Key: Standard 32Byte  Q: "
                       + question + "  OCRA: "
                       + ocra);
              question = "SRV1111" + i + "CLI2222" + i;
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                       "(client)Key: Standard 32Byte  Q: "
                       + question + "  OCRA: "
                       + ocra);
          }
          System.out.println();
        
          String ocraSuite1 = "OCRA-1:HOTP-SHA512-8:QA08";
          String ocraSuite2 = "OCRA-1:HOTP-SHA512-8:QA08-PSHA1";
          System.out.println("OCRASuite (server computation) = "
                             + ocraSuite1);
          System.out.println("OCRASuite (client computation) = "
                             + ocraSuite2);
          System.out.println("===============================" +
              "=================================");
          ocraSuite = "";
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              ocraSuite = ocraSuite1;
              question = "CLI2222" + i + "SRV1111" + i;
              qHex = asHex(question.getBytes());
              password = "";
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                          "(server)Key: Standard 64Byte  Q: "
                          + question + "  OCRA: "
                          + ocra);
              ocraSuite = ocraSuite2;
              question = "SRV1111" + i + "CLI2222" + i;
              qHex = asHex(question.getBytes());
              password = PASS1234;
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println("(client)Key: Standard 64Byte  Q: "
                           + question);
        
          String ocraSuite1 = "OCRA-1:HOTP-SHA512-8:QA08";
          String ocraSuite2 = "OCRA-1:HOTP-SHA512-8:QA08-PSHA1";
          System.out.println("OCRASuite (server computation) = "
                             + ocraSuite1);
          System.out.println("OCRASuite (client computation) = "
                             + ocraSuite2);
          System.out.println("===============================" +
              "=================================");
          ocraSuite = "";
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              ocraSuite = ocraSuite1;
              question = "CLI2222" + i + "SRV1111" + i;
              qHex = asHex(question.getBytes());
              password = "";
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                          "(server)Key: Standard 64Byte  Q: "
                          + question + "  OCRA: "
                          + ocra);
              ocraSuite = ocraSuite2;
              question = "SRV1111" + i + "CLI2222" + i;
              qHex = asHex(question.getBytes());
              password = PASS1234;
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println("(client)Key: Standard 64Byte  Q: "
                           + question);
        
              System.out.println("P: " + password.toUpperCase()
                           + "  OCRA: " + ocra);
          }
          System.out.println();
        
              System.out.println("P: " + password.toUpperCase()
                           + "  OCRA: " + ocra);
          }
          System.out.println();
        
          System.out.println();
          System.out.println("Plain Signature");
          System.out.println("===============");
          System.out.println();
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QA08";
          System.out.println(ocraSuite);
          System.out.println("=========================");
          seed = SEED32;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "SIG1" + i + "000";
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                      "Key: Standard 32Byte  Q(Signature challenge): "
                      + question);
              System.out.println("   OCRA: " + ocra);
          }
          System.out.println();
        
          System.out.println();
          System.out.println("Plain Signature");
          System.out.println("===============");
          System.out.println();
          ocraSuite = "OCRA-1:HOTP-SHA256-8:QA08";
          System.out.println(ocraSuite);
          System.out.println("=========================");
          seed = SEED32;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = "";
          for(int i=0; i < STOP; i++){
              question = "SIG1" + i + "000";
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,qHex,
                           password,sessionInformation,timeStamp);
              System.out.println(
                      "Key: Standard 32Byte  Q(Signature challenge): "
                      + question);
              System.out.println("   OCRA: " + ocra);
          }
          System.out.println();
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:QA10-T1M";
          System.out.println(ocraSuite);
          System.out.println("=============================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = b.toString(16);
          for(int i=0; i < STOP; i++){
              question = "SIG1" + i + "00000";
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                           qHex,password,sessionInformation,timeStamp);
              System.out.println(
                      "Key: Standard 64Byte  Q(Signature challenge): "
                      + question);
              System.out.println("   T: "
        
          ocraSuite = "OCRA-1:HOTP-SHA512-8:QA10-T1M";
          System.out.println(ocraSuite);
          System.out.println("=============================");
          seed = SEED64;
          counter = "";
          question = "";
          password = "";
          sessionInformation = "";
          timeStamp = b.toString(16);
          for(int i=0; i < STOP; i++){
              question = "SIG1" + i + "00000";
              qHex = asHex(question.getBytes());
              ocra = OCRA.generateOCRA(ocraSuite,seed,counter,
                           qHex,password,sessionInformation,timeStamp);
              System.out.println(
                      "Key: Standard 64Byte  Q(Signature challenge): "
                      + question);
              System.out.println("   T: "
        
                      + timeStamp.toUpperCase() + "  OCRA: "
                      + ocra);
          }
        
                      + timeStamp.toUpperCase() + "  OCRA: "
                      + ocra);
          }
        
      }catch (Exception e){
                System.out.println("Error : " + e);
      }
  }
  }
  <CODE ENDS>
        
      }catch (Exception e){
                System.out.println("Error : " + e);
      }
  }
  }
  <CODE ENDS>
        
Appendix C. Test Vectors
附录C.测试向量

This section provides test values that can be used for the OCRA interoperability test.

本节提供可用于OCRA互操作性测试的测试值。

Standard 20Byte key:

标准20字节密钥:

   3132333435363738393031323334353637383930
        
   3132333435363738393031323334353637383930
        

Standard 32Byte key:

标准32字节密钥:

   3132333435363738393031323334353637383930313233343536373839303132
        
   3132333435363738393031323334353637383930313233343536373839303132
        

Standard 64Byte key:

标准64字节密钥:

   313233343536373839303132333435363738393031323334353637383930313233343
   53637383930313233343536373839303132333435363738393031323334
        
   313233343536373839303132333435363738393031323334353637383930313233343
   53637383930313233343536373839303132333435363738393031323334
        

PIN (1234) SHA1 hash value:

PIN(1234)SHA1哈希值:

   7110eda4d09e062aa5e4a390b0a572ac0d2c0220
        
   7110eda4d09e062aa5e4a390b0a572ac0d2c0220
        
C.1. One-Way Challenge Response
C.1. 单向挑战响应
                +-----------------+----------+------------+
                |       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   |
                +-----------------+----------+------------+
        
                +-----------------+----------+------------+
                |       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   |
                +-----------------+----------+------------+
        

OCRA-1:HOTP-SHA1-6:QN08

OCRA-1:HOTP-SHA1-6:QN08

              +-----------------+---+----------+------------+
              |       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  |
              +-----------------+---+----------+------------+
        
              +-----------------+---+----------+------------+
              |       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  |
              +-----------------+---+----------+------------+
        

OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1

OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1

                +-----------------+----------+------------+
                |       Key       |     Q    | OCRA Value |
                +-----------------+----------+------------+
                | Standard 32Byte | 00000000 |  83238735  |
                | Standard 32Byte | 11111111 |  01501458  |
                | Standard 32Byte | 22222222 |  17957585  |
                | Standard 32Byte | 33333333 |  86776967  |
                | Standard 32Byte | 44444444 |  86807031  |
                +-----------------+----------+------------+
        
                +-----------------+----------+------------+
                |       Key       |     Q    | OCRA Value |
                +-----------------+----------+------------+
                | Standard 32Byte | 00000000 |  83238735  |
                | Standard 32Byte | 11111111 |  01501458  |
                | Standard 32Byte | 22222222 |  17957585  |
                | Standard 32Byte | 33333333 |  86776967  |
                | Standard 32Byte | 44444444 |  86807031  |
                +-----------------+----------+------------+
        

OCRA-1:HOTP-SHA256-8:QN08-PSHA1

OCRA-1:HOTP-SHA256-8:QN08-PSHA1

            +-----------------+-------+----------+------------+
            |       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  |
            +-----------------+-------+----------+------------+
        
            +-----------------+-------+----------+------------+
            |       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  |
            +-----------------+-------+----------+------------+
        

OCRA-1:HOTP-SHA512-8:C-QN08

OCRA-1:HOTP-SHA512-8:C-QN08

           +-----------------+----------+---------+------------+
           |       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  |
           +-----------------+----------+---------+------------+
        
           +-----------------+----------+---------+------------+
           |       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  |
           +-----------------+----------+---------+------------+
        

OCRA-1:HOTP-SHA512-8:QN08-T1M

OCRA-1:HOTP-SHA512-8:QN08-T1M

C.2. Mutual Challenge-Response
C.2. 相互挑战响应
   OCRASuite (server computation) = OCRA-1:HOTP-SHA256-8:QA08
        
   OCRASuite (server computation) = OCRA-1:HOTP-SHA256-8:QA08
        
   OCRASuite (client computation) = OCRA-1:HOTP-SHA256-8:QA08
        
   OCRASuite (client computation) = OCRA-1:HOTP-SHA256-8:QA08
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 32Byte | CLI22220SRV11110 |  28247970  |
            | Standard 32Byte | CLI22221SRV11111 |  01984843  |
            | Standard 32Byte | CLI22222SRV11112 |  65387857  |
            | Standard 32Byte | CLI22223SRV11113 |  03351211  |
            | Standard 32Byte | CLI22224SRV11114 |  83412541  |
            +-----------------+------------------+------------+
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 32Byte | CLI22220SRV11110 |  28247970  |
            | Standard 32Byte | CLI22221SRV11111 |  01984843  |
            | Standard 32Byte | CLI22222SRV11112 |  65387857  |
            | Standard 32Byte | CLI22223SRV11113 |  03351211  |
            | Standard 32Byte | CLI22224SRV11114 |  83412541  |
            +-----------------+------------------+------------+
        
                    Server -- OCRA-1:HOTP-SHA256-8:QA08
        
                    Server -- OCRA-1:HOTP-SHA256-8:QA08
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 32Byte | SRV11110CLI22220 |  15510767  |
            | Standard 32Byte | SRV11111CLI22221 |  90175646  |
            | Standard 32Byte | SRV11112CLI22222 |  33777207  |
            | Standard 32Byte | SRV11113CLI22223 |  95285278  |
            | Standard 32Byte | SRV11114CLI22224 |  28934924  |
            +-----------------+------------------+------------+
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 32Byte | SRV11110CLI22220 |  15510767  |
            | Standard 32Byte | SRV11111CLI22221 |  90175646  |
            | Standard 32Byte | SRV11112CLI22222 |  33777207  |
            | Standard 32Byte | SRV11113CLI22223 |  95285278  |
            | Standard 32Byte | SRV11114CLI22224 |  28934924  |
            +-----------------+------------------+------------+
        
                    Client -- OCRA-1:HOTP-SHA256-8:QA08
        
                    Client -- OCRA-1:HOTP-SHA256-8:QA08
        
   OCRASuite (server computation) = OCRA-1:HOTP-SHA512-8:QA08
        
   OCRASuite (server computation) = OCRA-1:HOTP-SHA512-8:QA08
        
   OCRASuite (client computation) = OCRA-1:HOTP-SHA512-8:QA08-PSHA1
        
   OCRASuite (client computation) = OCRA-1:HOTP-SHA512-8:QA08-PSHA1
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 64Byte | CLI22220SRV11110 |  79496648  |
            | Standard 64Byte | CLI22221SRV11111 |  76831980  |
            | Standard 64Byte | CLI22222SRV11112 |  12250499  |
            | Standard 64Byte | CLI22223SRV11113 |  90856481  |
            | Standard 64Byte | CLI22224SRV11114 |  12761449  |
            +-----------------+------------------+------------+
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 64Byte | CLI22220SRV11110 |  79496648  |
            | Standard 64Byte | CLI22221SRV11111 |  76831980  |
            | Standard 64Byte | CLI22222SRV11112 |  12250499  |
            | Standard 64Byte | CLI22223SRV11113 |  90856481  |
            | Standard 64Byte | CLI22224SRV11114 |  12761449  |
            +-----------------+------------------+------------+
        
                    Server -- OCRA-1:HOTP-SHA512-8:QA08
        
                    Server -- OCRA-1:HOTP-SHA512-8:QA08
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 64Byte | SRV11110CLI22220 |  18806276  |
            | Standard 64Byte | SRV11111CLI22221 |  70020315  |
            | Standard 64Byte | SRV11112CLI22222 |  01600026  |
            | Standard 64Byte | SRV11113CLI22223 |  18951020  |
            | Standard 64Byte | SRV11114CLI22224 |  32528969  |
            +-----------------+------------------+------------+
        
            +-----------------+------------------+------------+
            |       Key       |         Q        | OCRA Value |
            +-----------------+------------------+------------+
            | Standard 64Byte | SRV11110CLI22220 |  18806276  |
            | Standard 64Byte | SRV11111CLI22221 |  70020315  |
            | Standard 64Byte | SRV11112CLI22222 |  01600026  |
            | Standard 64Byte | SRV11113CLI22223 |  18951020  |
            | Standard 64Byte | SRV11114CLI22224 |  32528969  |
            +-----------------+------------------+------------+
        
                 Client -- OCRA-1:HOTP-SHA512-8:QA08-PSHA1
        
                 Client -- OCRA-1:HOTP-SHA512-8:QA08-PSHA1
        
C.3. Plain Signature
C.3. 普通签名

In this mode of operation, Q represents the signature challenge.

在此操作模式中,Q表示签名质询。

                +-----------------+----------+------------+
                |       Key       |     Q    | OCRA Value |
                +-----------------+----------+------------+
                | Standard 32Byte | SIG10000 |  53095496  |
                | Standard 32Byte | SIG11000 |  04110475  |
                | Standard 32Byte | SIG12000 |  31331128  |
                | Standard 32Byte | SIG13000 |  76028668  |
                | Standard 32Byte | SIG14000 |  46554205  |
                +-----------------+----------+------------+
        
                +-----------------+----------+------------+
                |       Key       |     Q    | OCRA Value |
                +-----------------+----------+------------+
                | Standard 32Byte | SIG10000 |  53095496  |
                | Standard 32Byte | SIG11000 |  04110475  |
                | Standard 32Byte | SIG12000 |  31331128  |
                | Standard 32Byte | SIG13000 |  76028668  |
                | Standard 32Byte | SIG14000 |  46554205  |
                +-----------------+----------+------------+
        

OCRA-1:HOTP-SHA256-8:QA08

OCRA-1:HOTP-SHA256-8:QA08

          +-----------------+------------+---------+------------+
          |       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  |
          +-----------------+------------+---------+------------+
        
          +-----------------+------------+---------+------------+
          |       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  |
          +-----------------+------------+---------+------------+
        

OCRA-1:HOTP-SHA512-8:QA10-T1M

OCRA-1:HOTP-SHA512-8:QA10-T1M

Authors' Addresses

作者地址

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

David M'Raihi Verisign,Inc.美国加利福尼亚州米德尔菲尔德路山景大道东487号,邮编94043

   EMail: davidietf@gmail.com
        
   EMail: davidietf@gmail.com
        

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

Johan Rydell Portwise,Inc.美国加利福尼亚州帕洛阿尔托市霍桑大道275号119室,邮编94301

   EMail: johanietf@gmail.com
        
   EMail: johanietf@gmail.com
        

Siddharth Bajaj Symantec Corp. 350 Ellis Street Mountain View, CA 94043 USA

Siddharth Bajaj Symantec Corp.美国加利福尼亚州埃利斯街山景城350号,邮编94043

   EMail: siddharthietf@gmail.com
        
   EMail: siddharthietf@gmail.com
        

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

Salah Machani Diversinet Corp.加拿大安大略省多伦多Sheppard大道东2225号1801室M2J 5C2

   EMail: smachani@diversinet.com
        
   EMail: smachani@diversinet.com
        

David Naccache Ecole Normale Superieure ENS DI, 45 rue d'Ulm Paris, 75005 France

David Naccache法国巴黎乌尔姆街45号高等师范学院,75005

   EMail: david.naccache@ens.fr
        
   EMail: david.naccache@ens.fr