2013-10-17 92 views
6

我有一個iPhone應用程序與Web服務器通信。啓動App時,用戶必須使用用戶名和密碼進行認證。 應用程序和Web服務器之間的通信是安全的(HTTPS),但我不想向Web服務器發送清除密碼,我只想發送密碼的「簽名」(簽名將被存儲在Web服務器上的數據庫中)。散列用於客戶端/服務器應用程序的用戶密碼

什麼是在IOS上創建這個「簽名」的最佳解決方案?我應該使用MD5還是其他?

我是否需要獲得外部庫來構建此簽名,還是可以使用IOS SDK中的SecKeyEncrypt完成此操作?

從長遠來看,我將在Android上運行一個應用程序,並且我必須能夠爲IOS和Android生成相同的簽名。

感謝您的幫助,

Sébastien。

回答

17

以明文形式傳輸密碼是不好的,所以做任何事都是很好的第一步。如果你要做出努力,值得知道如何正確做到這一點。

雖然MD5不再是強大的散列算法,但在MD5和SHA256(甚至SHA512)之間進行選擇並不像使用它的方式那麼重要。讓我們忽略哈希算法的細節,並看看它如何被首先使用。

使用散列的想法是,字符串的散列總是相同的並且是單向操作。通過捕獲字符串,確定密碼不可能(或實際)。近年來,隨着大量使用彩虹桌,這已經變得不真實。彩虹表包含每個可能的密碼(達到給定的長度)及其散列值,以便攻擊者可以使用反向查找來發現密碼。彩虹表適用於16個字符以下密碼的所有散列算法。

這個問題有幾個常見的解決方案。一個是執行哈希很多(大約1,000)次。確切的次數必須由客戶端和服務器都知道並預先確定,以便他們可以做到這一點。這具有使哈希生成代價高的優點和缺點。攻擊者在計算上變得越來越困難,但是如果彩虹表被擴展到足夠大,它仍然是有用的。

一個更好但不常見的解決方案是向密碼添加一個已知的隨機字符串(通常稱爲Salt),以使其長(可能爲64個字符)。客戶端和服務器必須事先知道這種鹽。這種解決方案既便宜又簡單,鹽即使泄漏也無關緊要。

密碼散列存在另一個常見問題。如果惡意用戶知道用戶密碼的哈希值,就像知道設計不良的系統的密碼本身一樣。假設我們有一個需要用戶名和密碼哈希的RPC函數。知道密碼散列的惡意用戶即使不知道密碼也可以提交該密碼,並訪問系統。這個已知的密碼哈希將繼續工作,直到用戶更改其密碼,可能是幾個月或幾年。需要的是一種限制密碼散列有用的持續時間的方法。這是通過使用動態鹽來實現的。

驗證然後成爲一個多步驟的過程。

  1. 客戶端連接到服務器,並且呈現某種客戶端(或設備)的標識符,例如UUID。
  2. 服務器然後爲該客戶端標識符生成動態鹽。動態鹽僅適用於短時間(通常是幾分鐘到幾小時)。
  3. 服務器將動態salt,其到期時間以及關聯的客戶端標識符存儲在數據庫表中以備將來使用。
  4. 服務器將動態salt返回給客戶端以及其到期。
  5. 客戶端使用以上兩種機制中的任何一種哈希密碼,連接動態salt,再次哈希,然後嘗試使用用戶名,客戶端標識符和動態哈希哈希進行身份驗證。
  6. 服務器通過檢查用戶已知的密碼散列值來驗證提交的憑證,該密碼散列值與嘗試連接並散列該客戶端標識符的每個已知動態鹽的提交值相對應。如果發現匹配,則接受認證。

這是(大體上)MySQL使用的機制。它足夠安全,可以在沒有SSL的情況下安全地使用它,但我總是建議使用SSL,以便其他有效負載得到保護。

如果您使用類似這樣的安全機制,則使用MD5或SHA變體無關緊要。也就是說,除非MD5有很好的理由,否則任何新的開發都不會使用SHA256。

+0

感謝您的詳細解答。 我將使用帶有salt的SHA256在將密碼發送到服務器之前對其進行散列(使用HTTPS)。 哈希密碼將存儲在服務器上的數據庫中。爲了避免任何有權訪問數據庫案例的人使用存儲的密碼,我想第二次散列(在服務器級和鹽)哈希密碼由客戶端應用程序發送。 它有道理嗎? – sebastien

1

md5不是最好的主意 - 現在有很多真正快速的彩虹表來解密它們。

我會建議使用AES256 - 在iOS上你有NSData+CommonCrypto它可以讓你輕鬆做到這一點。

NSString* encryptionPass = @"myEncryptionPass"; 
NSData* passData = [userPassword dataUsingEncoding:NSStringEncodingConversionAllowLossy]; 
NSError* error = nil; 
NSData* encryptedPassData = [passData AES256EncryptedDataUsingKey:encryptionPass error:&error]; 
if(!error) 
{ 
    NSString* encryptedString = [[NSString alloc] initWithData:encryptedPassData encoding:NSUTF8StringEncoding] 
} 
+1

好的長鹽會使彩虹桌無用,而且AES256有彩虹桌。只是說。 – user1133275

相關問題