On 21 Dec 2012, at 5:37 PM, Pearu Peterson <pearu.peter...@gmail.com> wrote:
> Thanks for the hint!
> 
> The following expression works for me:
> 
>   db.auth_user.password.validate(plain_password) == 
> (db(db.auth_user.id==auth.user_id).select ().first ().password, None)

Good. There's probably a shortcut in Auth, too, that would make it less verbose.

A word to other readers: this is why the new format for stored passwords 
identifies the hash algorithm and includes the salt, which is (by default, 
anyway) randomly generated. When the user enters the plain password to log in, 
CRYPT can extract the algorithm and salt from the stored hash and hash the 
plaintext password with them, and then compare the result.

In Pearu's test above, the == operation is implemented by CRYPT.__eq__ 
(actually LazyCrypt.__eq__, but it amounts to the same thing), using the 
approach I described. It's in gluon/validators.py if you're interested in the 
details.

A nice side effect is that, if the comparison succeeds, you can migrate an old 
has to a newer, stronger one. That's pretty nice: you don't have to leave your 
MD5-hashed users hanging out to be hacked if someone manages to discover your 
hashes. (That's also a reason to use a global key for your hashes, which is not 
stored in the database, and not visible to someone who just manages to hack the 
database.)

> 
> 
> Thanks again,
> Pearu
> 
> On Saturday, December 22, 2012 3:25:00 AM UTC+2, Jonathan Lundell wrote:
> On 21 Dec 2012, at 5:12 PM, Pearu Peterson <pearu.p...@gmail.com> wrote: 
> > Hi, 
> > 
> > I have a password in plain text and I want to check if it matches with the 
> > crypted password in auth_user.password field. 
> > 
> > I have tried comparing auth_user.password with 
> > str(db.auth_user.password.validate(plain_password)[0]) with no success even 
> > when I know that the passwords match exactly. 
> > 
> > The problem seems to boil down to the fact that encryption of the same 
> > string results different encrypted strings. For example, 
> > >>> from gluon.validators import CRYPT, LazyCrypt 
> > >>> crypt = CRYPT() 
> > >>> str(LazyCrypt(crypt, 'mysecret')) 
> >     
> > 'pbkdf2(1000,20,sha512)$a2a2ca127df6bc19$77bb5a3d129e2ce710daaefeefef8356c4c827ff'
> >  
> > >>> str(LazyCrypt(crypt, 'mysecret')) 
> >     
> > 'pbkdf2(1000,20,sha512)$a555a267249876fb$bc18f82b72a3a5ebce617f32d6abaa5c48734ab9'
> >  
> > 
> > What would be the correct way to check if passwords match when they are 
> > given in encrypted form? 
> 
> You have to compare using the equality test in CRYPT, so compare 
> CRYPT()(plaintext) == store_password (or something like that). You can't 
> compare the resulting strings, because they have different (random) salt, at 
> least by default they do. 
> 
> > 
> > Any hints are appreciated, 
> > Pearu 


-- 



Reply via email to