Реализация частей rfc4226 (HOTP) в MySQL - PullRequest
2 голосов
/ 30 января 2010

Как видно из названия, я пытаюсь реализовать программные части RFC4226 «HOTP: алгоритм одноразового пароля на основе HMAC» в SQL. Я думаю, что у меня есть версия, которая работает (в этом для небольшого тестового примера, она дает тот же результат, что и версия Java в коде), но она содержит вложенную пару шестнадцатеричных (unhex ()) вызовов, которые я чувствовать можно сделать лучше. Я ограничен: а) необходимостью выполнения этого алгоритма и б) необходимостью сделать это в 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;

Есть ли лучший (более эффективный) способ сделать это?

Ответы [ 2 ]

2 голосов
/ 30 января 2010

Я не читал спецификацию, но я думаю, что вам не нужно конвертировать туда и обратно между шестнадцатеричным и двоичным, так что это может быть немного более эффективным:

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

Похоже, это дает тот же результат, что и ваш запрос для нескольких примеров, которые я тестировал.

1 голос
/ 23 февраля 2011

Это абсолютно ужасно, но работает с моими 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 ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...