[Checkins] SVN: zope.password/trunk/ Remove the 'cosmetic' salt from the SHA1 implementation as well, update docs.
Martijn Pieters
mj at zopatista.com
Sun Feb 20 10:14:41 EST 2011
Log message for revision 120468:
Remove the 'cosmetic' salt from the SHA1 implementation as well, update docs.
Changed:
U zope.password/trunk/CHANGES.txt
U zope.password/trunk/README.txt
U zope.password/trunk/src/zope/password/password.py
-=-
Modified: zope.password/trunk/CHANGES.txt
===================================================================
--- zope.password/trunk/CHANGES.txt 2011-02-20 15:07:25 UTC (rev 120467)
+++ zope.password/trunk/CHANGES.txt 2011-02-20 15:14:41 UTC (rev 120468)
@@ -19,10 +19,11 @@
- Add a MySQL PASSWORD() (versions before 4.1) password manager, as also found
in Zope2's AccessControl.AuthEncoding module.
-- Remove the useless, cosmetic salt from the MD5 password manager. This makes
- this manager compatible with other MD5 hash implementations such as RFC 2307
- but doesn't lower it's security in any way. Old, still 'salted' password
- hashes are still supported.
+- Remove the useless, cosmetic salt from the MD5 and SHA1 password managers.
+ This makes the output of these managers compatible with other MD5 and SHA1
+ hash implementations such as RFC 2307 but doesn't lower it's security in any
+ way. Checking passwards against old, still 'salted' password hashes is still
+ supported.
3.6.1 (2010-05-27)
------------------
Modified: zope.password/trunk/README.txt
===================================================================
--- zope.password/trunk/README.txt 2011-02-20 15:07:25 UTC (rev 120467)
+++ zope.password/trunk/README.txt 2011-02-20 15:14:41 UTC (rev 120468)
@@ -13,11 +13,11 @@
more secure implementations.
* MD5PasswordManager - a password manager that uses MD5 algorithm to
- encode passwords. It's generally weak against dictionary attacks.
+ encode passwords. It's generally weak against dictionary attacks due to a
+ lack of a salt.
* SHA1PasswordManager - a password manager that uses SHA1 algorithm to
- encode passwords. It has the same salt weakness as the
- MD5PasswordManager.
+ encode passwords. It has the same weakness as the MD5PasswordManager.
* SSHAPasswordManager - the most secure password manager that is
strong against dictionary attacks. It's basically SHA1-encoding
Modified: zope.password/trunk/src/zope/password/password.py
===================================================================
--- zope.password/trunk/src/zope/password/password.py 2011-02-20 15:07:25 UTC (rev 120467)
+++ zope.password/trunk/src/zope/password/password.py 2011-02-20 15:14:41 UTC (rev 120468)
@@ -18,7 +18,6 @@
from base64 import urlsafe_b64encode
from base64 import urlsafe_b64decode
from os import urandom
-from random import randint
from codecs import getencoder
try:
from hashlib import md5, sha1
@@ -227,9 +226,6 @@
class SHA1PasswordManager(PlainTextPasswordManager):
"""SHA1 password manager.
- Note: use of salt in this password manager is purely
- cosmetical. Use SSHA if you want increased security.
-
>>> from zope.interface.verify import verifyObject
>>> manager = SHA1PasswordManager()
@@ -237,7 +233,7 @@
True
>>> password = u"right \N{CYRILLIC CAPITAL LETTER A}"
- >>> encoded = manager.encodePassword(password, salt="")
+ >>> encoded = manager.encodePassword(password)
>>> encoded
'{SHA}04b4eec7154c5f3a2ec6d2956fb80b80dc737402'
>>> manager.match(encoded)
@@ -247,23 +243,10 @@
>>> manager.checkPassword(encoded, password + u"wrong")
False
- >>> encoded = manager.encodePassword(password)
- >>> encoded[-40:]
- '04b4eec7154c5f3a2ec6d2956fb80b80dc737402'
- >>> manager.match(encoded)
- True
- >>> manager.checkPassword(encoded, password)
- True
- >>> manager.checkPassword(encoded, password + u"wrong")
- False
-
- >>> manager.encodePassword(password) != manager.encodePassword(password)
- True
-
The old version of this password manager didn't add the {SHA} to
passwords. Let's check if it can work with old stored passwords.
- >>> encoded = manager.encodePassword(password, salt="")
+ >>> encoded = manager.encodePassword(password)
>>> encoded = encoded[5:]
>>> encoded
'04b4eec7154c5f3a2ec6d2956fb80b80dc737402'
@@ -277,6 +260,14 @@
>>> manager.match(encoded)
False
+ A previous version of this manager also created a cosmetic salt, added
+ to the start of the hash, but otherwise not used in creating the hash
+ itself. To still support these 'hashed' passwords, only the last 40 bytes
+ of the pre-existing hash are used:
+
+ >>> manager.checkPassword('salt' + encoded, password)
+ True
+
Previously, this password manager used {SHA1} as a prefix, but this was
changed to be compatible with LDAP (RFC 2307). The old prefix is still
supported:
@@ -293,17 +284,15 @@
"""
def encodePassword(self, password, salt=None):
- if salt is None:
- salt = "%08x" % randint(0, 0xffffffff)
- return '{SHA}%s%s' % (salt, sha1(_encoder(password)[0]).hexdigest())
+ # The salt argument only exists for backwards compatibility and is
+ # ignored on purpose.
+ return '{SHA}%s' % sha1(_encoder(password)[0]).hexdigest()
def checkPassword(self, encoded_password, password):
if self.match(encoded_password):
encoded = encoded_password[encoded_password.find('}') + 1:]
- salt = encoded[:-40]
- return encoded == self.encodePassword(password, salt)[5:]
- salt = encoded_password[:-40]
- return encoded_password == self.encodePassword(password, salt)[5:]
+ return encoded[-40:] == self.encodePassword(password)[5:]
+ return encoded_password[-40:] == self.encodePassword(password)[5:]
def match(self, encoded_password):
return (
More information about the checkins
mailing list