2013-06-21 31 views
1

我有一个标准的API设置,其中客户端通过使用归因于提供的公钥的私钥对请求主体进行哈希验证并将其与查询字符串中的hash为基于公钥/私钥的API处理空请求主体

例如,请求正文是"THIS IS REQUEST BODY",他们会将hash设置为sha256('THIS IS REQUEST BODY'.PRIVATE_KEY),然后服务器将执行相同的操作来验证它。

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


我假设唯一的答案将是“要求内容在请求正文”,但也许我失去了明显的东西。

回答

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作业)或每周数据库,其实并不重要。取决于你的API的活跃程度。

这里的关键是,虽然要保持现时的轨道,而它们是有效的,否则你会很容易受到重放攻击...

+0

真棒。谢谢,这正是我正在寻找的。干杯。 – jraede

1

为什么不在请求中使用时间戳。这将使信息独一无二。要么有时间同步,要么可以用明文形式发送时间戳,请求在服务器上验证。

+0

所以才有所需要的时间戳作为请求主体的一部分每次?如果是时间戳,我不认为这很重要,我认为它可能是任何旧的变量。但时间戳确实增加了一个额外的维度,但很小。 – jraede