2011-07-20 23 views
0

我正在尋找爲IMAP和SMTP服務器實現CRAM-MD5身份驗證。問題在於CRAM似乎需要一個明文密碼隨時可用。服務器向客戶端發送一個獨特的挑戰和客戶端返回:CRAM-MD5實現

MD5(MD5(password, challenge), MD5(password)) 

我看不到的方式來檢查這個無需明文密碼,該規範並沒有說出來有一個可用但它似乎是合乎邏輯的。

我能想出的唯一解決方案是將密碼加密(正確加密,而不是散列)到數據庫中(可能使用基於RSA密鑰的AES,因爲我已經有一些東西需要處理),並且在解密時需要比較,似乎是一個非常緩慢的方法,因爲它需要對SMTP和IMAP上的每個單一登錄進行解密和哈希處理。

這是最好的解決方案/最有效的解決方案嗎?

或者更好,現在CRAM已經過時了,因爲現在使用SSL來保護線路上更安全的身份驗證?

回答

1

訣竅是,你真正需要的是密碼的未終結md5,它與最終確定之前md5上下文的中間狀態相同。

MD5_CTX ctx; 
MD5Init(&ctx); 
MD5Update(&ctx, password, length); 

,如果你做到這一點,那麼ctx值存儲爲hashed,那麼就可以再使用它的副本在CRAM MD5這樣

MD5(password, challenge)

MD5Update(&hashed, challenge, length); 
MD5Final(&digest, &hashed); 

MD5(password)

MD5Final(&digest, &hashed); 

MD5(MD5(password, challenge), MD5(password))其餘是相當簡單

我也喜歡使用Python在這個例子中,但在標準MD5有沒有辦法讓訪問的md5對象的,所以我用libmd5的API狀態

+0

希望您已經將它寫入python,這就是我正在寫的:p。 這似乎是最好的解決方案。保持密碼的安全性(只要MD5可以)。所以我可以使用我的加密方法,然後仍然能夠提供CRAM MD5功能。 – Paystey

+0

這可能比以純文本存儲密碼更好,因爲在多個地方使用相同密碼的用戶可能受到的影響較小,但數據庫仍包含登錄所需的所有內容。 CRAM難以避免。 –

1

目前有一個草案RFC建議將DIGEST-MD5移動到歷史狀態,CRAM MD5也沒有處於更好的狀態。

如果您想要適當的安全性,從TLS和SASL開始 - 在該模式下,PLAIN被認爲是可以接受的,但是,如果您擔心它不能令人滿意,那麼我會建議在頂層上實現GSSAPI或NTLM它。

+0

感謝,RFC狀態幫助我瞭解了很多。現在我很難看到CRAM MD5,因爲TLS和簡單的協議看起來好多了。我非常希望不要在數據庫和程序之間再添加一層,因爲它根本不是抽象的,所以GSSAPI或NTLM並不是真正的選擇。 – Paystey

+0

我希望你打算自己編寫自己的電子郵件客戶端;) – Olipro

+0

爲什麼這麼說? GSSAPI和NTLM是否提供客戶端身份驗證?從簡單的看,我收集他們是服務器端身份驗證機制。 – Paystey

1

Python的源代碼hashlib.py表示您可以使用二進制數據初始化哈希實例,但是從它似乎意味着「初始化此數據的哈希值」的用法來初始化哈希實例。

但是,您可以克隆其內部狀態完好的對象,以便您可以醃製對象並存儲該對象以代替密碼。要獲取密碼MD5,取消對象並獲取質詢哈希值,取出它並用質詢數據調用它的update()方法。

+0

但是這可以被任何人取消,並肯定使用?如果代碼可以訪問明文狀態以便能夠更新散列,那麼當然它仍然可以被發現。 我很欣賞這在混淆方面仍然相當不錯,因爲它需要一些操作來實現它是什麼以及如何撤消它。但我認爲我要將它完全加密到數據庫中。 – Paystey

+0

沒有檢查源代碼,我會假定對象只保留當前散列,因爲您不需要保留明文 - 這將是您在上面接受的答案中引用的初始化向量。 – Adrian