2010-01-30 13 views
2

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

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

-- 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 at-il une meilleure (plus efficace) de le faire?

Répondre

2

Je n'ai pas lu la spécification, mais je pense que vous n'avez pas besoin de convertir dans les deux sens entre hexadécimal et en binaire, 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.

+0

grâce, l'arrière-plan ne devrait pas être important tant que les résultats sont les mêmes –

+0

Eh oui, c'est exactement ce que je voulais, merci encore –

1

Ceci est absolument horrible, mais il fonctionne avec mes jetons OTP à 6 chiffres. Appel 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 ;