1

我有一个标准的 API 设置,其中通过使用归因于提供的公钥的私钥对请求正文进行哈希处理,并将其与hash查询字符串中的值进行比较来验证客户端。

例如,请求正文是"THIS IS REQUEST BODY",他们会设置hashsha256('THIS IS REQUEST BODY'.PRIVATE_KEY),然后服务器会做同样的事情来验证它。

如果请求正文为空,如何保护此身份验证过程?哈希将是私钥的哈希值,然后可以被任何监听流量的人重新用于类似的“空”请求。


我假设唯一的答案是“要求请求正文中的内容”,但也许我遗漏了一些明显的东西。

4

2 回答 2

3

首先,不要这样做HASH(DATA + KEY)。它存在已知的漏洞。这正是HMAC设计的目的。所以你的哈希是:

hash = HMAC(sha256, data, privateKey)

现在,处理您的问题(如何防止重放攻击)的典型方法是为每个请求添加一个随机因子。有几种方法可以做到这一点,但效果很好的是nonce基于方法。所以:

nonce = random(16)
now = time()
data = api_data + '|' + nonce + '|' + now
hash = HMAC(sha256, data, privateKey)

apiCall = data '&nonce=' + nonce + '&time=' + now + '&sig=' + hash

然后,在接收方,您跟踪过去 30 秒内看到的随机数列表。如果你得到一个你见过的,然后拒绝 api 调用(因为那将是一个重放攻击)。如果你得到一个超过 30 秒的版本,请拒绝 api 调用。

if (now < time() - 30) {
    return false;
} else if (nonceExists(nonce)) {
    return false;
}
addNonce(nonce);

data = api_data + '|' + nonce + '|' + now
myhash = HMAC(sha256, data, privateKey)
if (myhash == hash) {
    return api_data;
}
return false;

然后您可以每 30 秒(在 cron 作业中)或每周清除 nonce 上的数据库,这并不重要。取决于您的 API 的活跃程度。

不过这里的关键是你想在它们有效时跟踪它们,否则你很容易受到重放攻击......

于 2013-06-22T00:57:04.240 回答
1

为什么不对请求使用时间戳。这将使消息独一无二。您可以进行时间同步,也可以以纯文本形式发送时间戳,并请求在服务器上进行验证。

于 2013-06-22T00:20:59.700 回答