January 2009 Archives

Authentication musings

| No Comments | No TrackBacks

So I sit and I think... authentication. Many times have I wondered, it must be possible, and somewhat simple, to do authentication without ever sending a great deal of the users information across the wire in plain text.

NOTE: I am ignoring the SSL'd HTTP approach here which somewhat makes this point not important, but more on that later. 

Then it hit me. Why not use some simple hashing/encryption to just try to deal with it? Here we go, this should be fun:

  1. Phase 1: Creation/Setup (Note this phase SHOULD happen over HTTPS, because this is one time when some critical information could be stolen that could later prove helpful to "hackers")
    • User creates account, the application sends the users name/other info, and the hashed password (I recommend hashing both with md5 and sha1, then concatenating them together, or just use sha1)
    • Server also generates a hash of the concatenation of the username with the hashed password.
    • All done, that is basically the same thing, except we throw an extra hash in there, we need it later don't worry. Notice we at least have prevented the users plain password from ever being sent over the lines, even though we should have been using HTTPS its nice to know the server could never, at any time, know the real password.
  2. Phase 2: Login (Note this could happen over HTTP, and still be basically secure. I will note the only drawback I have thought of in a moment.)
    • User enters username/password like normal
    • Client side, password is hashed
    • Username + hashed password is hashed
    • The super hash is sent to the server
    • Server finds the matching hash (this is why it generated it earlier, for easy lookup)
    • At this point the client knows who they are claiming to be, the server knows who the client is claiming to be, and we can challenge their knowledge of who they claim to be
    • Server picks a random number
    • Server creates a session and stores the user info and random number inside
    • Server encrypts the username, hashed password, and random number using the hashed password as the key and delivers it to the client
    • Server sends the session ID so the client knows what session they were assigned
    • Client takes hashed password and decrypts the delivered encrypted auth information
    • Client verifies username from decryption and hashed password matches, stores random number if so
  3. Phase 3: Communication (Note we can also do non-sensitive stuff over normal HTTP still, certainly would not be sending credit card numbers or something though!)
    • For each request the client is expected to encrypt the username, hashed password, and the NEXT random number. If it started as 2 by the server then the client should change it to 3 for the next message. Note that you can use a simple +1 or for further security include in the original message a series of number, such that make up the coefficients of some N-degree polynomial for the sequence, just take care of rolling over from MAX_INT in either case. 
    • The client updates the number, encrypts the data (it still knows the hashed password)
    • The client could optionally encrypt an arbitrary amount of data in the communication, it is more than likely not as secure as HTTPS, but if its somewhat sensitive but not life altering it may be appropriate since the key is already shared and no additional connections need to be worked out.
    • The server decrypts the information (client gave it the session ID so we know whats going on) and verifies the sequence number is intact. Should it be wrong the request is completely rejected and the client is informed the session is damaged or expired and they must login again.
    • The server updates its sequence number and responds to the client with the key, in this fashion the client knows the server is in on the loop and not some other server somehow.
    • The stars align and everything would continue working like normal with very minimal overhead. Some quick triple des on top of a few small values should save on the overhead of a full blown HTTPS style connection while not really giving up much of the security.
Don't need the session security stuff? Well at least you can use the steps up to that to generate a method for authenticating a user, have them respond once to the challenge (verify the number matches) and you know they are who they say they are.

What may be not good: (There has to be drawbacks always, doesn't there)
  • The same key is used to encrypt potentially millions of communications. A clever hacker could grab your super hash as its transmitted and keep asking for auth codes from the server, they may be able to eventually reverse the original hashed password back out since its the key used in so many messages.
  • You could potentially help this by always starting a session for a user when auth comes up, and for say 60 minutes, you just hold that session, so you always send the same key. Also you could use the current date or time as a piece of the key in the encryption to help vary it, use the current hour GMT or current day of year, some method of the server/client verifying each knows the hour/day properly is needed, but it would help.
  • Public/private keypairs like HTTPS use make great protected connection channels, but consume resources and have annoyances trying to use them with HTTP, but the layers higher up just magically take care of them. This process requires some involved work with the client/server itself, because its trying to add some protection on top of an unprotected protocol. TripleDES is fairly fast and not horribly resource intensive and its being used for small messages, hopefully this should render this a viable option. Something stronger could also potentially be used depending on the application type.
  • Not entirely RESTful, state needs to be maintained for the session between the client and the server, they rely on a moving target approach that means both have to know where the other is at for each request to work, but at least the user information is transmitted once as minimally as possible, and from then on your assumed known. You theoretically only need to remember the session id and session key to generate for each request though, so I submit that it can infact be RESTful in nature (I can attack REST in another post)
  • Any way to rig this puppy up to OpenID style systems? I haven't thought of anything yet really, still need to do some more research.

About this Archive

This page is an archive of entries from January 2009 listed from newest to oldest.

February 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.