2

正如标题所说,我正在尝试在 SQL 中实现 RFC4226“HOTP:基于 HMAC 的一次性密码算法”的编程部分。我想我有一个可以工作的版本(对于一个小测试样本,它产生与代码中的 Java 版本相同的结果),但它包含一对嵌套的 hex(unhex()) 调用,我感觉可以做得更好。我受制于 a) 需要执行此算法,以及 b) 需要在 mysql 中执行,否则我很乐意查看其他执行此操作的方法。

到目前为止我得到了什么:

  -- From the inside out...

  -- Concatinate the users secret, and the number of time its been used
  -- find the SHA1 hash of that string
  -- Turn a 40 byte hex encoding into a 20 byte binary string
  -- keep the first 4 bytes
  -- turn those back into a hex represnetation
  -- convert that into an integer
  -- Throw away the most-significant bit (solves signed/unsigned problems)
  -- Truncate to 6 digits
  -- store into otp
  -- from the otpsecrets table

  select (conv(hex(substr(unhex(sha1(concat(secret, uses))), 1, 4)), 16, 10) & 0x7fffffff) % 1000000
    into otp
    from otpsecrets;

有没有更好(更有效)的方法来做到这一点?

4

2 回答 2

2

我还没有阅读规范,但我认为你不需要在十六进制和二进制之间来回转换,所以这可能会更有效一点:

SELECT (conv(substr(sha1(concat(secret, uses)), 1, 8), 16, 10) & 0x7fffffff) % 1000000
INTO otp
FROM otpsecrets;

这似乎与您对我测试的几个示例的查询给出了相同的结果。

于 2010-01-30T19:08:50.623 回答
1

这绝对是可怕的,但它适用于我的 6 位 OTP 令牌。调用为:

select HOTP( floor( unix_timestamp()/60), secret ) 'OTP' from SecretKeyTable;

drop function HOTP;
delimiter //
CREATE FUNCTION HOTP(C integer, K BINARY(64)) RETURNS char(6)
BEGIN
    declare i INTEGER;
    declare ipad BINARY(64);
    declare opad BINARY(64);
    declare hmac BINARY(20);
    declare cbin BINARY(8);

    set i = 1;
    set ipad = repeat( 0x36, 64 );
    set opad = repeat( 0x5c, 64 );

    repeat
        set ipad = insert( ipad, i, 1, char( ascii( substr( K, i, 1 ) ) ^ 0x36 ) );
        set opad = insert( opad, i, 1, char( ascii( substr( K, i, 1 ) ) ^ 0x5C ) );
        set i = i + 1;
    until (i > 64) end repeat;

    set cbin = unhex( lpad( hex( C ), 16, '0' ) );
    set hmac = unhex( sha1( concat( opad, unhex( sha1( concat( ipad, cbin ) ) ) ) ) );

    return lpad( (conv(hex(substr( hmac, (ascii( right( hmac, 1 ) ) & 0x0f) + 1, 4 )),16,10) & 0x7fffffff) % 1000000, 6, '0' );
END
//
delimiter ;
于 2011-02-23T03:55:21.617 回答