2013-06-21 35 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