[Twisted-Python] Authenticating with md5 hashed passwords

exarkun at twistedmatrix.com exarkun at twistedmatrix.com
Mon Feb 15 08:25:04 EST 2010


On 09:54 am, raq at cttc.upc.edu wrote:
>Jean-Paul,
>
>Thanks for your answers. Answers bellow. Also attachments of
>client/server application tests.
>
>On Fri, 2010-02-12 at 20:06 +0000, exarkun at twistedmatrix.com wrote:
>>On 06:03 pm, raq at cttc.upc.edu wrote:
>> >Hello everybody,
>> >
>> >I am trying to build a a client/server application using Perspective
>> >Broker and wanting to authenticate against a PostgreSQL database.
>> >Everything works fine if I user plain text passwords, but when trying
>> >to
>> >hash then using md5 using
>>
>>What do you mean when you say you're using plain text passwords?
>>Authentication involves multiple parties handling the password in
>>multiple ways, and the "plain text"-ness of the password changes from
>>step to step.
>
>I mean that the the server authenticates the client using a NOT HASHED
>password. In my case using a VARCHAR field in a PostgreSQL table
>> >from hashlib import md5
>> >md5Password = md5(password).hexdigest()
>> >

I'm confused here.  I don't see this code in your checker implementation 
in the attached code.  Is this code running someplace else?
>> >then it does not authenticate (I use
>> >credentials.checkMD5Password(password) at the checker class)
>> >
>> >Then after reading
>> >
>> >twisted/spread/pb.py
>> >
>> >I saw that everything is done in the functions:
>> >
>> >respond(challenge, password)
>> >challenge()
>> >
>> >and the methods
>> >
>> >checkMD5Password(self, md5Password)
>> >checkPassword(self, password)
>> >
>> >at the
>> >
>> >class _PortalAuthChallenger(Referenceable, _JellyableAvatarMixin)
>> >
>> >By changing digest() with hexdigest(), it works.

Indeed.  `checkMD5Password` needs to be passed the MD5 digest of the 
password, not the hex encoded MD5 digest (despite being documented as 
taking the plaintext password itself).
>> >
>> >The question is:
>> >
>> >I there some way to make it work without making changes at the 
>>'pb.py'
>> >module?
>> >
>> >Yes. I should use md5Password = md5(password).digest() to produce the
>> >password, but then I cant authenticate with a 'pure-ftpd' daemon I 
>>need
>> >to work with.

This seems to be the crux of the matter.  I'm not sure how the PB auth 
code and the FTP auth code interact, though.  Perhaps your FTP code can 
just do its own password hashing?
>> >Any alternatives?
>>
>>You should register an IUsernameHashedPassword checker with the portal
>>you pass to PBServerFactory and use PBClientFactory.login.  See
>>pbbenchserver.py and pbbenchclient.py for examples of this.  Despite 
>>the
>
>Yes I did so. You can see the attached examples I am testing with
>>fact that you're passing a UsernamePassword instance to
>>PBClientFactory.login, the plain text password is never sent over the
>>network.
>
>Yes I Know. You do that at the 'respond(challenge, password)' in
>'pb.py', do you?
>>
>>Also, IUsernameMD5Password is about to be deprecated, along with the
>>checkMD5Password method of _PortalAuthChallenger.
>
>So, how should I do it in order not to be using deprecated code? I 
>would
>like to know some details so that I can have a better understanding of
>how authentication is working.

If you have the plaintext password in the PB server, then you can just 
call `checkPassword` instead of `checkMD5Password` in 
DBCredentialsChecker._cbAuthenticate.

Jean-Paul



More information about the Twisted-Python mailing list