We have a business need to encrypt, decrypt, store and at times auto generate passwords. The passwords will be stored in a DB. We have played with JCE a little and the standard Base64. One of our concerns is the use of a .ser file on our App Server. Is there a better, secure and scalable way to implement this? I have attached some sample code below: Should we store the key in the DB? Your thought, opinions and sample code would be greatly appreciated.
Originally posted by Jeff Bradford: We have a business need to encrypt, decrypt, store and at times auto generate passwords. The passwords will be stored in a DB.
My first kneejerk reaction is: do you really need to be able to recover the passwords, or do you just need authentication? If you can live without recoverable passwords then the usual approach is to add some salt (= a large random number) to the password, calculate a secure hash of the whole caboodle (eg MD5), and store the hash together with the salt in your database. You can authenticate a password by hashing it with the salt and comparing the hash with the one in the database. The database is useless to an attacker. If the hash function you use is secure, it is virtually impossible to construct a password to match a given hash. No fancy encryption necessary.
One of our concerns is the use of a .ser file on our App Server. Is there a better, secure and scalable way to implement this?
Perhaps, perhaps not. Can you be more specific about your concerns? Having a serialized key on the app server doesn't seem much of a problem to me -- provided you have a copy in a safe somewhere in case the server breaks down And provided that you have some meaningful security in place, so that it is extremely unlikely for an attacker to get hold of both your database information and the private key on your appserver box.
Should we store the key in the DB?
Definitely not, unless perhaps it is a different database and you connect to that database using a secure link (eg SSL/TLS). The DB would otherwise contain all the ingredients necessary to decrypt the passwords! And if the link isn't secure a packet sniffer can deliver all said ingredients to an attacker. - Peter  I lied. Although passwords cannot be reverse-engineered, they can be guessed: an attacker can launch a dictionary attack against the password hashes stored in the database. Any weak passwords that may be present will be broken within a reasonable timeframe. Keeping database security tight and adding a password checker to filter out weak passwords should come a long way towards remedying this problem. [ January 24, 2003: Message edited by: Peter den Haan ]
Joined: Jan 24, 2003
Peter, thank you for your detailed response. Would the statement below be accurate? I am looking to publish a statement similar to this to our internal crypto developer(s). JCE with Symmetric Keys: The challenge with this approach is the Secret Key. A one to many relationship (one secret key used to encrypt many passwords) will exist since storing secret keys in a DB is not recommended. Changing the secret key regularly would be a recommended best practice, therefore an Admin function would be needed to loop through the DB of passwords, decrypt it using the old key, and encrypt them again using the new key. Secret key files need to stored in the secured area under the xxxxx directory and may or may not be serialized.
Peter den Haan
Joined: Apr 20, 2000
It would still be distinctly less than ideal Jeff, because it completely relies on secrecy for security. Your application would still need access to both the secret key and the database. An attacker who compromises your application will have all the ingredients to get the passwords. Regularly changing the password mitigates the risk only to a limited extent. As I see it, there are two better alternatives, either of which is probably secure enough. 1. You do not need to recover passwords. Take the password, add salt, hash it (MD5), and store the hash and the salt in the database. To verify a password, add the salt and compare the hash to the one in the database. This scheme relies on the fact that the MD5 hash is irreversible and that it's very hard to construct a password for a given hash. 2. You do need to recover passwords. Generate a public/private key pair. You can store the public key in the database, but the private key should remain secret. Take the password, add salt, encrypt it using the public key and store the encrypted password together with the salt in the database. To verify a password, add the salt and compare the encrypted password to the one in the database. Password recovery should ideally be done by a separate application, as it needs the private key. To recover a password, decrypt the stored password using the private key and remove the salt. This scheme relies on the fact that it's very hard to decrypt a message if you don't have the private key. Like your suggestion, it does rely on secrecy, but this is much less of a problem because you don't need the private key for authentication, just for recovery. In either case, make sure this is coded by developers who know more or less what they're doing. It is too easy to compromise security inadvertently. - Peter