Pergunta

Como o título diz, estou tentando implementar as partes programáticas do RFC4226 "HOTP: um algoritmo de senha único baseado em HMAC" no SQL. Eu acho que tenho uma versão que funciona (para uma pequena amostra de teste, ela produz o mesmo resultado que a versão Java no código), mas contém um par de chamadas hexadecimais aninhadas (UNSEX ()), que eu A sensação pode ser feita melhor. Estou limitado por a) precisando fazer esse algoritmo e b) precisando fazê -lo no MySQL, caso contrário, fico feliz em procurar outras maneiras de fazer isso.

O que eu tenho até agora:

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

Existe uma maneira melhor (mais eficiente) de fazer isso?

Foi útil?

Solução

Não li as especificações, mas acho que você não precisa se converter entre hexadecimal e binário, então isso pode ser um pouco mais eficiente:

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

Isso parece dar o mesmo resultado que sua consulta para alguns exemplos que testei.

Outras dicas

Isso é absolutamente horrível, mas funciona com meus tokens OTP de 6 dígitos. Ligue como:

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 ;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top