If you had the opportunity to play that classic game you probably eventually succeeded in having tea and no tea at the same time. Of course, those events took place in a universe which had the benefit of the Infinite Improbability Drive.
Some time ago I wrote a humorous take on encrypting passwords. Hopefully it was clear that I was poking fun at a few nonsensical implementations. However, every so often I get requests to implement something along the lines of what I described in that article.
There are two types of passwords handled by the web server. First, there are passwords which (one way or the other) will be sent by a client to the server and the server needs to (by various mechanisms) to validate whether it matches the stored password. Second, there are passwords which the web server process will itself need to know during its lifetime because it will interact with some other entity using a protocol which requires the web server to posess the password in the clear.
The first kind is used, for example, when authenticating web clients using HTTP Basic or Digest auth or Servlet FORM authentication. The server doesn’t need to know the actual password of that user. It only needs to know a one-way hash of the password in a suitable form. The suitable form can vary depending on the protocol but we can ignore the details for the moment – the high level point being that the server only needs a hash of the password, therefore it doesn’t need to store the clear text password nor does it need to be able to compute the clear text password (say, by decrypting) at any time.
The second kind is different. Above I defined these to be those which the server will need to know in the clear at some point. So the question is raised, how should these be stored? Storing one-way hashes of the password is clearly out, since the one-way-ness handily breaks the stated requirement of recovering the original password.
We can encrypt these passwords with a suitably strong reversible algorithm! In the previous article I wrote “encryption is really hard to break, so that will certainly improve the security even further”. I chose that wording to highlight the common misconception that encryption is a magic bullet that makes problems go away.
Unfortunately we also need to handle the key management issues if encryption is introduced. It is certainly possible to encrypt those passwords with a strong cipher such as AES and have the web server store only the encrypted data on disk. But we have already asserted that the web server process needs to obtain the clear text of those password at some point during the life of the process. How will the process do that? As long as it has the encryption key it can decrypt the data to obtain the passwords.
So where is that key coming from?
The are two possibilities:
- The key is not stored anywhere on disk; a human must enter it into the console when the server process requests it.
- The key is kept on disk in a form which allows the server process to obtain it programmatically, without human interaction.
The first choice has some real benefits. The key is never stored anywhere and the passwords are only stored on disk securely encrypted. Of course, there is a major drawback to this option – the server cannot start without the help of the human who needs to enter the key. The scenarios where this is practical are limited.
The second choice is the one I covered in the previous article.