仿新浪微盾客户端项目简介二

这个新浪微盾客户端的核心算法,就是这个OTP算法。

这个otp算法是什么了?

OTP是One-Time Password的简称,可称之为一次性口令,也称动态口令。每个口令只能使用一次,按照时间或使用次数不断动态变化,是随机、不可预测、不重复使用的数字组合。
这个OTP算法,在大型企业中,办公网的接入和VPN的访问或者其他重要数据的访问等通常都需要使用一次性口令来进行认证。
 
常用OTP算法说明

1.1 HOTP(基于事件)

1.1.1 算法概述

HOTP算法是基于一个加法计数器和一个静态对称密钥的,该密钥仅有令牌和认证服务器知道,如下:

C: 一个递增的值,可以看作是一个计数器

K: 一个静态对称密钥

每次进行密码验证的时候,双方都利用下面的算法来生成一个动态的值:

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

在这里HMAC-SHA-1指的是在RFC2104里定义的HASH算法。Truncate代表一个削减函数,以便把HMAC-SHA-1算法的结果变成一个便于用户输入的值(比如6位,8位)。

这里Truncate表示将HMAC-SHA-1值转换为HOTP值的函数,如2.1.2节所定义。

 

1.1.2 生成HOTP值

这里我们分三步来描述这个过程

第1步:

生成一个HMAC-SHA-1值,让 HS = HMAC-SHA-1(K,C) //HS为20位的String

 

第2步:

生成一个4位的String(Dynamic Truncation,动态削减)

    Sbits = DT(HS)  //DT运算的定义参照下面说明,返回31-bit string

 

第3步:

计算HOTP值

Snum  = StToNum(Sbits) // 把S转化成一个0至2^{31}-1的数

Return D = Snum mod 10^Digit // D是一个位于0至10{Digit}-1的数

 

削减函数Truncate执行第2步和第3步处理。

 

DT运算的定义:

DT(String)  //String = String[0]...String[19],HMAC-SHA-1运算的结果

让 OffsetBits等于String[19]的低位4字节

Offset = StToNum(OffsetBits) // 0 <= OffSet <= 15

让 P = String[OffSet]...String[OffSet+3]

返回P的最后31字节

 

1.1.3 计算6位HOTP的例子

下面的例子介绍怎样从HMAC-SHA-1运算结果抽取动态的二进制代码,hmac_result是存放HMAC-SHA-1结果的一个数组

//String[19]的低位4字节

int offset   =  hmac_result[19] & 0xf ;

//不使用最高位,利用 &0x7f

int bin_code = (hmac_result[offset]  & 0x7f) << 24

   | (hmac_result[offset+1] & 0xff) << 16

   | (hmac_result[offset+2] & 0xff) <<  8

   | (hmac_result[offset+3] & 0xff) ;

 

HMAC-SHA-1运算的例子

SHA-1 HMAC Bytes (Example)

 

-------------------------------------------------------------

| Byte Number                                               |

-------------------------------------------------------------

|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|

-------------------------------------------------------------

| Byte Value                                                |

-------------------------------------------------------------

|1f|86|98|69|0e|02|ca|16|61|85|50|ef|7f|19|da|8e|94|5b|55|5a|

-------------------------------***********----------------++|

 l  最后的字节(第19字节)的十六进制值是0x5a。

l  低位四字节是0xa (offset 值)。

l  offset 值为10 (0xa)。

l  从第十位开始的4位是 0x50ef7f19,这个就作为动态的二进制代码DBC1。

l  由于DBC1的最高位是 0x50,所以 DBC2 = DBC1 = 0x50ef7f19 = 135872921。

l  HOTP = DBC2 除以 10^6 的余 = 872921。

 这样用二进制代码 135872921 除以 1,000,000 (10^6) 的余就是一个 6 位十进制HOTP值 872921 。

 1.1.4  HOTP值的验证

HOTP客户端(软件或硬件令牌)将其计数器值加1后计算出HOTP客户端的下一个HOTP值。

如果HOTP服务器收到的值和客户端计算的值一致,则该HOTP值通过认证。在这种情况下,服务器把计数器的值加1。

如果HOTP服务器收到的值和客户端计算出来的值不一致,服务器在要求用户提供下一个动态口令之前将启动同步协议。(look-ahead window,即接受一定范围内的超前的HOTP值,比如将计数器的值加1,加2,加3后的值)。

如果同步失败,服务器会要求用户提供下一个动态口令,直到达到最大认证尝试次数。

如果达到了最大认证尝试次数,服务器应当锁定该帐户并通知该用户。

 

1.1.5 计数器的同步

虽然在一次成功的HOTP认证后,服务器才会增加服务器计数器的值,但是令牌上的计数器的值是只要用户请求一个新的HOTP就会增加。因此,服务器上的计数器和令牌上的计数器的值就可能不同步。

为了解决这个问题,可在服务器上设置一个超前(look-ahead)变量s ,让它来定义look-ahead window的大小。简单的说,就是服务器能计算接下来的s个服务器端HOTP的值,然后用它们来检测接收到的HOTP客户端的值,也就是与收到的HOTP客户端值进行比较。

在这种情况下,计数器的同步就仅仅是让服务器计算接下来的s个HOTP值并确定是否有一个匹配的。系统可以要求用户发送连续的几个HOTP值(比如2个, 3个)以用来同步,因为猜测连续的几个HOTP值比猜测单独的一个HOTP值要困难的多。

变量s设置的上限保证服务器不会一直在检测HOTP值(避免导致拒绝服务攻击)并且限制攻击者可能的猜测范围。在确保影响可用性的同事,s应当尽可能的小。

 

1.1.6 共享密钥的管理

用于生成和验证OTP值的共享密钥的操作必须被安全地进行。

这里我们考虑两种不同的用于生成和存储共享密钥的方式:

l  确定性生成:在提供和认证阶段,密钥由一个主种子得出,在需要时都能即时产生

l  随机生成:在提供阶段密钥随机产生,而且要被及时存储,并在整个有效周期中保持安全

 

确定性生成:

------------------------

从主密钥中得出共享密钥,这个主密钥只存储在服务器中。必须使用一种防篡改的装置来存储该主密钥,并能从该主密钥和公共信息中得出共享密钥。

 

我们区别两种不同的情形:

l  使用一个主密钥 MK 来产生共享密钥。每一个HOTP设备都有一个不同的密钥,K_i = SHA-1 (MK,i) 这里 i 代表一个用来识别HOTP设备的公开信息,比如一个序列号,一个令牌ID等。

l  使用若干主密钥 MK_i ,每一个HOTP设备存储一个个从中得到的互不相同的密钥。 {K_i,j = SHA-1(MK_i,j)} 这里 j 代表一个用来识别HOTP设备的公开信息。这样,如果一个主密钥 MK_i 泄露了,就只需要换用另一个而不必更换所有的设备。

 

确定性生成的缺点就是,当主密钥泄露后,攻击者很容易在正确公开信息的基础上重建任何共享密钥。

 

随机生成:

-----------------

随机生成共享密钥。我们可以按照在[RFC4086]里的建议选择一个好而安全的随机信号源来产生密钥。一个随机生成器需要一个自然发生的随机数源。从实际来看,有两个可以考虑的用来生成共享密钥的办法:

l  基于硬件的生成器: 通过物理现象产生随机数。可以利用振荡器来实现并以主动攻击更难以执行的方式完成。

l  基于软件的生成器: 设计一个好的软件随机生成器不是一件容易的事。一个简单的,但有效的实现应该基于多种数据源并用像 SHA-1 这样的单方向函数。

 

另外可以使用更安全的方法存储密钥,例如可使用防篡改的硬件加密存储器对共享密钥加密,并且仅在需要的时候才将其取出。当需要验证一个HOTP值时,共享密钥将被解密,之后将被立即加密以减少其在 RAM 中暴露的时间。存储共享密钥的数据存储器必须处于一个安全的环境中,以尽量避免对认证系统和保密数据库的攻击。

 

1.1.7 演示数据

这里以 K 为 12345678901234567890 为例

 

下面是各个计数器的值对应的 HMAC-SHA-1(K,C) 的值

   计数     十六进制 HMAC-SHA-1(K,C)

   0        cc93cf18508d94934c64b65d8ba7667fb7cde4b0

   1        75a48a19d4cbe100644e8ac1397eea747a2d33ab

   2        0bacb7fa082fef30782211938bc1c5e70416ff44

   3        66c28227d03a2d5529262ff016a1e6ef76557ece

   4        a904c900a64b35909874b33e61c5938a8e15ed1c

   5        a37e783d7b7233c083d4f62926c7a25f238d0316

   6        bc9cd28561042c83f219324d3c607256c03272ae

   7        a4fb960c0bc06e1eabb804e5b397cdc4b45596fa

   8        1b3c89f65e6c9e883012052823443f048b4332db

   9        1637409809a679dc698207310c8c7fc07290d9e5

 

下面是削减过的值(包含十六进制和十进制)和HOTP的值

                     Truncated

   计数     十六进制         十进制          HOTP

   0        4c93cf18       1284755224     755224

   1        41397eea       1094287082     287082

   2         82fef30        137359152     359152

   3        66ef7655       1726969429     969429

   4        61c5938a       1640338314     338314

   5        33c083d4        868254676     254676

   6        7256c032       1918287922     287922

   7         4e5b397         82162583     162583

   8        2823443f        673399871     399871

   9        2679dc69        645520489     520489

 

1.2 TOTP(基于时间)

1.2.1 算法

TOTP 的算法与 HOTP 的不同在于, HOT P是基于事件的, TOTP 是基于时间的,也就是说用一个由时间和更新频率得出的 T 来代替HOTP中的计数器 C 。

如下:

X:表示更新频率,单位为秒,默认为60秒

T0:表示Unix时间,默认为0

 

T = (当前 Unix 时间 - T0) / X

 

TOTP = HOTP(K, T) = Truncate(HMAC-SHA-1(K, T))

 

例如:

T0 = 0

X = 60

当前 Unix 时间为119,那么 T = 1

如果当前 Unix 时间为120,那么 T = 2

 

其他算法可遵循HOTP的算法,具体生成 TOTP 值的方法也与之前介绍的 HOTP 相同,可进行参考。

1.2.2 演示数据

   这里以 K 为 12345678901234567890 为例

   更新频率 X = 30

   T0 = 0

 

  +-------------+--------------+------------------+----------+--------+

  |  Time (sec) |   UTC Time   | Value of T (hex) |   TOTP   |  Mode  |

  +-------------+--------------+------------------+----------+--------+

  |      59     |  1970-01-01  | 0000000000000001 | 94287082 |  SHA1  |

  |             |   00:00:59   |                  |          |        |

  |      59     |  1970-01-01  | 0000000000000001 | 46119246 | SHA256 |

  |             |   00:00:59   |                  |          |        |

  |      59     |  1970-01-01  | 0000000000000001 | 90693936 | SHA512 |

  |             |   00:00:59   |                  |          |        |

  |  1111111109 |  2005-03-18  | 00000000023523EC | 07081804 |  SHA1  |

  |             |   01:58:29   |                  |          |        |

  |  1111111109 |  2005-03-18  | 00000000023523EC | 68084774 | SHA256 |

  |             |   01:58:29   |                  |          |        |

  |  1111111109 |  2005-03-18  | 00000000023523EC | 25091201 | SHA512 |

  |             |   01:58:29   |                  |          |        |

  |  1111111111 |  2005-03-18  | 00000000023523ED | 14050471 |  SHA1  |

  |             |   01:58:31   |                  |          |        |

  |  1111111111 |  2005-03-18  | 00000000023523ED | 67062674 | SHA256 |

  |             |   01:58:31   |                  |          |        |

  |  1111111111 |  2005-03-18  | 00000000023523ED | 99943326 | SHA512 |

  |             |   01:58:31   |                  |          |        |

  |  1234567890 |  2009-02-13  | 000000000273EF07 | 89005924 |  SHA1  |

  |             |   23:31:30   |                  |          |        |

  |  1234567890 |  2009-02-13  | 000000000273EF07 | 91819424 | SHA256 |

  |             |   23:31:30   |                  |          |        |

  |  1234567890 |  2009-02-13  | 000000000273EF07 | 93441116 | SHA512 |

  |             |   23:31:30   |                  |          |        |

  |  2000000000 |  2033-05-18  | 0000000003F940AA | 69279037 |  SHA1  |

  |             |   03:33:20   |                  |          |        |

  |  2000000000 |  2033-05-18  | 0000000003F940AA | 90698825 | SHA256 |

  |             |   03:33:20   |                  |          |        |

  |  2000000000 |  2033-05-18  | 0000000003F940AA | 38618901 | SHA512 |

  |             |   03:33:20   |                  |          |        |

  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 65353130 |  SHA1  |

  |             |   11:33:20   |                  |          |        |

  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 77737706 | SHA256 |

  |             |   11:33:20   |                  |          |        |

  | 20000000000 |  2603-10-11  | 0000000027BC86AA | 47863826 | SHA512 |

  |             |   11:33:20   |                  |          |        |

  +-------------+--------------+------------------+----------+--------+

这种基于时间的otp算法,也是我们本次微盾所用的otp算法。

这节我们主要介绍了新浪微盾实战教程核心算法——otp算法.

posted on 2014-03-02 10:12  laozhu1124  阅读(1587)  评论(0编辑  收藏  举报

淘宝免费计数器