2013-05-14 32 views
1

我正在從一個應用程序到另一個應用程序進行API調用。我處理授權通過傳遞md5版共享的祕密+時間戳...如何通過可靠的時間戳傳遞API令牌

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

然後在API端點,我檢查這樣的請求的真實性...

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

這工作。但它不如我想要的那麼可靠。我懷疑這是由於網絡延遲(或者我的速度慢的本地主機服務器)導致時間戳一秒鐘左右不匹配。

我通過刪除時間戳的最後一位數字,以一種懶惰的方式解決了這個問題,從而爲我的緩存服務器創建了長達10秒的窗口來進行呼叫。不過,我對此並不滿意,因爲如果這次電話會在第9秒的末尾落下,我會再次遇到相同的問題(發送####### 49!=在##處收到###### 50)。

必須有更好的方法來做到這一點。它是什麼?

回答

2

考慮使用token = time || MAC(time, shared_secret)其中||是串聯的,MAC是消息認證算法,如HMAC,它採用一個密鑰和一些數據併產生一個認證標籤。在服務器端,檢查MAC是否有效,並且時間(以純文本接收)在可接受的窗口內。

這比您當前的解決方案更安全(md5使可憐的MAC),並且還解決了您的窗口問題。

請注意,該方案容易在您允許的錯誤窗口內進行重播攻擊(例如,同一令牌可能在一秒內發送十次,而服務器無法識別)。

+0

你是完全正確的。我忘了發送純文本的時間戳!這正是我過去做過的事情,我只是簡單地忘記了。我很想知道更多關於你對MAC和md5的看法。爲什麼MD5是一個糟糕的選擇? (順便說一下,我使用PHP) – emersonthis

+0

[擴展長度攻擊](https://en.wikipedia.org/wiki/Length_extension_attack)是這個問題的構造問題。例如,根據時間格式和/或接收者解釋時間的靈活程度,攻擊者可能能夠使用令牌在未來創建新的令牌,並通過接收者的驗證。 PHP有一個[HMAC實現](http://php.net/manual/en/function.hash-hmac.php)。 HMAC在與md5一起使用時被認爲是安全的,但除非你有特別的理由使用md5,否則我建議sha256。 – Michael

+0

PHP HMAC非常值得了解。但是,我不是100%確定如何將其應用於我的情況,因爲我沒有發送任何加密數據。只是共享的祕密+時間戳。那麼這個'hmac('md5','foobar',$ secret)是一個比簡單的'md5($ secret)'更好的標誌嗎?或者也許它們是等價的,'hmac'的優點是可以使用sha256嗎? – emersonthis

0

改爲使用隨機數?將該隨機數保存到數據庫或某個永久性存儲器,以確保不使用同一個存儲器。

與你的'第九個第二個問題'相反,你有類似的問題幾秒鐘### ... 0到### ... 9當你截斷尾部0到9時散列到相同的值。將允許在10秒的時間內重放。

看起來像這將是更多的保證/檢查真實性的問題。

您必須將明文和散列文本一起發送給服務器進行檢查,但這似乎比時間戳方法好一點。

無論哪種方式,只用這兩個參數,你只是檢查它不是一個重複的請求,而不是驗證任何東西。

+0

我不確定你提出的解決方案。但是,您似乎可能誤解了某些內容:時間戳不適用於身份驗證。它被用來保護共享的祕密。沒有它,呼叫很容易被攔截,而令牌也會受到影響。通過時間戳,可以截獲API調用,但該令牌在1(0)秒後無用。合理? – emersonthis

+0

我想我着迷於此:「我檢查這樣的請求的真實性」 – asafreedman

+0

我的評論是否闡明瞭爲什麼我包含時間戳? – emersonthis

0

使用時間戳不是正確的方法,因爲時間在系統間不可靠。也許你可以使用消息的長度/散列作爲參數。不幸的是,它不會阻止攻擊者的回放。

糾正我,如果我錯了,但好像你正在處理身份驗證(即發件人是他們說他們是誰)而不是授權。我建議你使用SSL/TLS來確保傳輸的安全,以瞭解傳輸是否被代理。

+0

如果時間戳不是正確的方式,那麼*是正確的方式?我意識到SSL會加密整個呼叫,但這不是我問的問題的答案。由於這裏不重要的原因,我的系統不能依賴於SSL。 – emersonthis

+0

對不起,編輯我的文章 - 通常認爲時間戳是好的,因爲它是不可靠的。 – badunk