1

我正在从一个应用程序到另一个应用程序进行 API 调用。md5我通过传递一个ed 共享密钥 + 时间戳来处理授权...

$token = md5( $secret . time() );

然后在 API 端点,我像这样检查请求的真实性......

if ( md5($shared_secret . time() ) == $token )
    ...do stuff

这行得通。但它并不像我想要的那样可靠。我怀疑原因是由于网络(或我的慢速本地主机服务器)中的延迟导致时间戳不匹配一秒左右。

我通过删除时间戳的最后一位数字以一种懒惰的方式解决了这个问题,从而为我的 slowpoke 服务器创建了一个长达 10 秒的窗口来进行调用。但是,我对此并不满意,因为如果电话恰好在第 9 秒结束时落下,我将再次遇到同样的问题(在 #######49 发送!= 在 ## 收到######50)。

必须有更好的方法来做到这一点。它是什么?

4

3 回答 3

3

考虑使用token = time || MAC(time, shared_secret)where || 是连接,MAC 是一种消息认证算法,例如 HMAC,它采用密钥和一些数据并产生认证标签。在服务器端,检查 MAC 是否有效并且时间(以明文形式接收)在可接受的窗口内。

这比您当前的解决方案更安全(md5 使 MAC 很差),并且还解决了您的窗口问题。

请注意,此方案很容易在您允许的错误窗口内受到重放攻击(例如,同一令牌可以在一秒窗口内发送十次,而服务器无法判断)。

于 2013-05-15T18:52:09.343 回答
0

改用随机数?将随机数保存到数据库或一些持久性存储中,以确保不使用相同的随机数。

与您的“第 9 秒问题”相反,当您切断尾随 0 到 9 时,您会遇到类似的问题 ###...0 到 ###...9 散列到相同的值。这将允许重播那 10 秒的时间范围。

似乎这对于保证/检查真实性来说将是一个更大的问题。

您必须将明文和散列文本一起发送以供服务器检查,但这似乎比时间戳方法好一点。

无论哪种方式,单独使用这两个参数,您只是检查它不是重复请求,而不是验证任何内容。

于 2013-05-14T19:42:46.567 回答
0

使用时间戳不是正确的方法,因为时间跨系统不可靠。也许您可以使用消息的长度/哈希作为参数。不幸的是,它不会阻止攻击者的回放。

如果我错了,请纠正我,但似乎您正在处理身份验证(即,发件人就是他们所说的人)而不是授权。我建议您使用 SSL/TLS 来保护传输以了解传输是否被代理。

于 2013-05-15T08:45:44.677 回答