2013-01-11 36 views
1

我使用Python的crypt程序包在Django網站的MySQL數據庫中保存加密的密碼。我不知道這是否是一個錯誤,但這裏是我使用的代碼:Python crypt package:可以在密碼中輸入多餘的字符

要加密/堅持密碼:

user.password = crypt(request.POST['password'], netid) 
user.save() 

要在登錄檢查是否有正確的密碼:

if crypt(password, email) == user.password: 
# Grant acccess to the user's profile, etc. 

問題是以下幾點。如果我使用變量netid = [email protected]request.POST['password'] = 'ABC123abc'加密密碼,它可以正常工作。但是,當我嘗試登錄時,如果我使用密碼'ABC123abc[trailing_chars]',其中trailing_chars可以是任何有效的字符串,我仍然可以登錄。爲什麼會這樣?它構成了一個巨大的安全漏洞。

+2

你不使用默認的[Django auth](https://docs.djangoproject.com/en/dev/topics/auth/)處理所有用戶/密碼的東西,包括散列密碼的原因是什麼? – jvc26

回答

6

首先,你應該而不是使用電子郵件地址作爲加密(第二個參數)的地穴。這不安全。你必須選擇一個好的隨機鹽。

對於傳統隱窩,鹽是從集合[a–zA–Z0–9./]中選擇的兩個字符的字符串。這個版本的crypt只接受8個輸入字符,並在第8個輸入字符後丟棄所有後續字符。這就是你在這裏看到的。

現代隱私實現還支持其他算法,這些算法在密碼上比傳統隱私更強大,但它們並不適用於所有平臺。新算法也不會將輸入限制爲8個字符。

要使用這些更好的算法之一(如果您使用支持它們的平臺),您需要提供一種特殊格式的鹽。這是函數如何識別您想要使用替代算法。

有關glibc支持的額外算法(因此可在GNU/Linux上獲得),請參閱crypt manpage的「Glibc註釋」部分。

順便說一句,當檢查密碼時,您不需要手動提取鹽。加密的密碼已經以鹽開始,因此只需將user.password(而不是email)作爲crypt的第二個參數。無論您使用的是舊算法還是新算法,這都是有效的。選擇正確格式的算法和生成salt只需在加密密碼時進行,而不是在驗證密碼時進行。

+0

非常感謝,非常豐富 –