Domanda

Come dice il titolo, sto cercando di implementare le parti programmatiche di RFC4226 "HOTP: un algoritmo di password One Time basato su HMAC in SQL. Penso di avere una versione che funziona (in quella per un piccolo campione di test, produce lo stesso risultato della versione Java nel codice), ma contiene una coppia nidificata di chiamate esadecimale (unlex ()), che i La sensazione può essere fatta meglio. Sono vincolato da a) che ho bisogno di fare questo algoritmo e b) che ho bisogno di farlo in Mysql, altrimenti sono felice di guardare altri modi di farlo.

Quello che ho finora:

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

Esiste un modo migliore (più efficiente) di farlo?

È stato utile?

Soluzione

Non ho letto le specifiche, ma penso che tu non abbia bisogno di convertire avanti e indietro tra esadecimale e binario, quindi questo potrebbe essere un po 'più efficiente:

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

Questo sembra dare lo stesso risultato della tua domanda per alcuni esempi che ho testato.

Altri suggerimenti

Questo è assolutamente orribile, ma funziona con i miei token OTP a 6 cifre. Chiama come:

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 ;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top