2011-05-17 5 views
5

Tengo una situación donde un script recibe algunos datos del usuario, luego devuelve un hash. Durante un cierto período de tiempo, por ejemplo, X segundos, el hash es válido y cuando se devuelve al script junto con los datos originales y dentro del marco de tiempo especificado, se permite el acceso a ciertas funciones.Causa de hash para caducar después de un cierto tiempo

Estoy haciendo esto incluyendo una marca de tiempo en el hash. Puedo obtener una marca de tiempo llamando a decir floor(time()/X); pero esto, en lugar de caducar después de X segundos, caduca en cualquier lugar entre 1 y X segundos. Tengo alrededor de esta ahorrando time()%X y añadiendo al hash, a continuación, cuando lo reciba de vuelta, analizarlo y restarlo de time(), por lo que mi función hash se ve un poco como esto:

function hash($oldhash='') { 
    static $hash; 
    if(!$hash) { 
     $time = time(); 
     $expoff = explode('!', $oldhash, 2); 
     $expoff = $expoff[0] ? $expoff[0] : $time%$this->_cfg['hashexpire']; 
     $hash = $expoff.'!'.sha1($this->_data.floor(($time-$expoff)/$this->_cfg['hashexpire'])); 
    } 
    return $hash; 
} 

Theres también una sal allí pero la retiré para mayor claridad.

Esto funciona, pero creo que hay una forma mejor de lograr lo que busco aquí y me pregunto si tiene alguna sugerencia.

Respuesta

3

Bueno, quiere que caduque después de un cierto número de segundos, ¿correcto? Bueno, ¿por qué no precalcular el tiempo de caducidad y pasarlo? Sólo se está hablando unos pocos bytes adicionales que se transfieren:

function makeHash() { 
    $expire = time() + $this->_cfg['hashexpire']; 
    $hash = $expire . ':' . hash_hmac('sha1', $this->_data, $expire); 
    return $hash; 
} 

Luego de verificar:

function verifyHash($hash) { 
    if(!strpos($hash, ':')) return false; 
    list ($expire, $rawhash) = explode(':', $hash, 2); 
    $testhash = hash_hmac('sha1', $this->_data, $expire); 
    if ($expire < time() && $testhash == $rawhash) { 
     return true; 
    } 
    return false; 
} 

Tenga en cuenta que se trata de utilizar un HMAC para "firmar" la carga de datos.

Y si realmente está paranoico con el tamaño de los datos, solo base_convert($expire, 10, 36) antes de enviarlo al cliente, y luego decodifíquelo al verificarlo.

Edit: Como estoy volviendo a leer su pregunta, no estoy seguro. ¿Está buscando generar un hash que no será válido después de $x segundos? ¿O está buscando generar el mismo hash para una ventana de tiempo absoluto de $x segundos (después de lo cual cambia el hash)? Si el anterior, la solución anterior funcionará. Si la tarde, entonces usted podría intentar algo como esto:

function makeHash() { 
    $time = time(); 
    $startTime = $time - ($time % $this->_cfg['hashexpire']); 
    return hash_hmac('sha1', $this->_data, $startTime); 
} 

La razón por la que esto funciona, es que los hashes con la fecha y hora de la primera, segunda válida de la ventana actual. Eso siempre permanecerá igual, por lo que no es necesario almacenarlo o ir más lejos ...

Tenga en cuenta que el hash generado solo cambiará cada $_cfg['hashexpire'] segundos. Pero podría invalidarse el segundo después de su creación. Así que solo use esto si eso es realmente lo que necesita. }

+0

¡Tu ejemplo actualizado parecía muy atractivo! Lamentablemente, no, no es lo que necesito. Pensaré en el primer ejemplo un poco más, quizás esto combinado con un vencimiento encriptado como Mel sugirió ... Gracias por el enlace sobre HMAC, tendré que leer un poco allí. – tjm

0

Creo que su solución es buena, dado el problema. Supongo que las cookies (y las sesiones de extensión) están descartadas; de lo contrario, no te molestarías con esto.

Un enfoque similar sería omitir agregar algo al hash y en su lugar probar el período actual y el último.

+0

Gracias, sí, las cookies no son una opción, me temo. – tjm

2

Dado que etiquetó esto con seguridad, agregar el tiempo al hash y extraerlo no es muy seguro. Un atacante puede revertir su código y proporcionar una marca de tiempo diferente.Necesita una forma (como una base de datos o construcción de archivo plano en su servidor) para asociar el hash con una marca de tiempo que el usuario no puede modificar.

Otra opción es encriptar la marca de tiempo con una contraseña en el código, de modo que incluso si el usuario extrae la parte de la marca de tiempo, no podrá encriptar la nueva marca de tiempo. Si se refería a esto con 'sal', no estaba claro en su pregunta si sació el hash o la marca de tiempo.

+0

Gracias. Tienes razón, mi preocupación era la falta de seguridad. Creo que primero veré la posibilidad de encriptar la marca de tiempo. – tjm

Cuestiones relacionadas