导致哈希在一定时间后过期

时间:2011-05-17 20:17:12

标签: php security hash

我有一种情况,脚本从用户接收一些数据,然后返回一个哈希。在一段时间内,比如X秒,哈希是有效的,当与原始数据一起提供回脚本时,在指定的时间范围内,允许访问某些功能。

我这样做是通过在哈希中包含一个时间戳。我可以通过调用说floor(time()/X);来获取时间戳,但这不是在X秒后过期,而是在1到X秒之间到期。我通过保存time()%X并将其附加到哈希来解决这个问题,然后当我收到它,解析它并从time()中减去它时,所以我的哈希函数看起来有点像这样: / p>

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也是一块盐,但我为了清楚起见将其删除了。

这有效,但我认为可能有更好的方法来实现我在此之后的想法,并想知道你是否有任何建议。

3 个答案:

答案 0 :(得分:3)

嗯,你希望它在一定的秒数后过期,对吗?那么,为什么不预先计算过期时间,然后通过呢?你只是在谈论一些额外的字节传输:

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

然后验证:

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

请注意,它使用HMAC来“签署”数据有效负载。

如果您对数据大小非常偏执,只需将base_convert($expire, 10, 36)发送到客户端,然后在验证时对其进行解码。

编辑:因为我正在重读你的问题,我不确定。您是否正在寻找生成的哈希值,在$x秒后无效?或者您是否希望为$x秒的绝对时间窗口生成相同的哈希值(之后哈希值会发生变化)?如果先前,上述解决方案将起作用。如果是后者,那么你可以尝试这样的事情:

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

这个工作的原因是,它使用当前窗口的第一个有效秒的时间戳进行哈希处理。这将永远保持不变,所以没有必要存储它或更进一步......

请注意,生成的哈希值只会每$_cfg['hashexpire']秒更改一次。但它可能会在创建后的第二秒失效。因此,只有在您真正需要的时候才使用它。     }

答案 1 :(得分:2)

由于您使用安全性对此进行了标记,因此将时间附加到哈希并提取它并不是非常安全。攻击者可以撤消您的代码并提供不同的时间戳。您需要一种方法(如服务器上的数据库或平面文件构造)将哈希与用户无法修改的时间戳相关联。

另一种选择是在代码中使用密码加密时间戳,这样即使用户提取时间戳部分,她也无法加密新的时间戳。如果你的意思是'盐',那么你的问题就不清楚你是否腌制了哈希值或时间戳。

答案 2 :(得分:0)

考虑到问题,我认为你的解决方案很好。我认为cookie(以及扩展会话)是不可能的,否则你不会为此烦恼。

类似的方法是跳过向哈希附加任何内容,而是尝试当前时段和最后时段。