Hi there, while working on a password manager tool (commandline) for Grok I stumbled over the usage of salts in the password managers of `zope.app.authentication`.
In short, they seem to generate (and store) a salt number but do not make any use of it when it comes to creating the hashes (SHA1, MD5, whatever). As a result, same passwords lead always to same hashes, only the leading salt number is different. This could be exploited by dictionary attacks. The zope.app.authentication implementation for SHA1-encoding looks roughly like this (other hash-encodings have the same problem, if this is a valid problem):: def encodePassword(password, salt=None): if salt is None: salt = "%08x" % randint(0, 0xffffffff) return salt + sha.new(password).hexdigest() It looks to me that this way `salt` is only an arbitrary string that gets stored in front of the real hash value. The hash value itself will not change with the salt. When I run the following code (`checkPassword` like in `zope.app.authentication.password`):: def checkPassword(storedPassword, password): salt = storedPassword[:-40] return storedPassword == encodePassword(password, salt) for i in range(0,3): enc = encodePassword('asd') print 'Encode "asd"', enc print 'Check: ', checkPassword(enc, 'asd') I get:: Encode "asd" 81bde2dbf10e2821bbbea527ea02200352313bc059445190 Check: True Encode "asd" c96cfabdf10e2821bbbea527ea02200352313bc059445190 Check: True Encode "asd" bdba5b69f10e2821bbbea527ea02200352313bc059445190 Check: True As you can see, only the first eight letters change. And they are cleartext part of the encoded password. Not a problem for an dictionary-attacker: if one of the hashes in his/her dictionary are equal to ``f10e2821bbbea527ea02200352313bc059445190``, then the password is cracked. Salts do not improve the security level here, I think. What I assume to be correct, would be to build the hash from the salt plus password (instead of only the password):: def encodePassword(password, salt=None): if salt is None: salt = "%08x" % randint(0, 0xffffffff) return salt + sha.new(salt + password).hexdigest() Using this modified function, I get:: Encode "asd" 11ac348fe526cc38813fca0e5bd0a59ec3a16686bfa42502 Check: True Encode "asd" 08de8fa19212d743867f8867adee55a9efbe566a8ec56731 Check: True Encode "asd" d454b892224b0cf5b41767acfa80a3732b82c52fc2ee5e9f Check: True Now it is harder for an attacker. His dictionary has not only to provide the pure hashes for every entry in the dictionary, but also 16**8 variants for _each_ of the entries. That's it, I think, what salt is used for. As I am not a computer scientist nor a mathematician, I am not sure, whether these are valid concerns. But I would like to know, what others think about this. Maybe you can correct me here. Best regards, -- Uli
signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )