Question

Comme le titre le dit, j'essaie d'implémenter les parties programmatiques de RFC4226 "HOTP: un algorithme de mot de passe basé sur HMAC" dans SQL. Je pense que j'ai une version qui fonctionne (en ce que pour un petit échantillon de test, il produit le même résultat que la version Java dans le code), mais il contient une paire imbriquée d'appels Hex (Unex ()), que je La sensation peut être mieux fait. Je suis contraint par a) besoin de faire cet algorithme, et b) d'avoir besoin de le faire dans MySQL, sinon je suis heureux de regarder d'autres façons de le faire.

Ce que j'ai jusqu'à présent:

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

Y a-t-il une meilleure façon (plus efficace) de le faire?

Était-ce utile?

La solution

Je n'ai pas lu la spécification, mais je pense que vous n'avez pas besoin de vous convertir entre Hex et Binary, donc cela pourrait être un peu plus efficace:

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

Cela semble donner le même résultat que votre requête pour quelques exemples que j'ai testés.

Autres conseils

C'est absolument horrible, mais cela fonctionne avec mes jetons OTP à 6 chiffres. Appelez comme:

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 ;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top