Storing Passwords in reversible form Storing Passwords in reversible form php php

Storing Passwords in reversible form


First, to state the (hopefully) obvious, if you can in any way at all avoid storing usernames and passwords do so; it's a big responsibility and if your credential store is breached it may provide access to many other places for the same users (due to password sharing).

Second, if you must store credentials prefer rather to stored passwords using a non-reversible, salted cryptographic hash, so if you data is compromised the passwords cannot easily be reverse-engineered and there's no need to store a decryption key at all.

If you must store decryptable credentials:

  1. Choose a good encryption algorithm - AES-256, 3DES (dated), or a public key cipher (though I think that's unnecessary for this use). Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
  2. Use a secure random generator to generate your keys. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
  3. Store the encryption/decryption key(s) separately from your database, in an O/S secured file, accessible only to your applications runtime profile. That way, if your DB is breached (e.g. through SQL injection) your key is not automatically vulnerable, since that would require access to to the HDD in general. If your O/S supports file encryption tied to a profile, use it - it can only help and it's generally transparent (e.g. NTFS encryption).
  4. If practical, store the keys themselves encrypted with a primary password. This usually means your app. will need that password keyed in at startup - it does no good to supply it in a parameter from a script since if your HDD is breached you must assume that both the key file and the script can be viewed.
  5. For each credential set, store a salt (unencrypted) along with the encrypted data; this is used to "prime" the encryption cipher such that two identical passwords do not produce the same cipher text - since that gives away that the passwords are the same.
  6. If the username is not necessary to locate the account record (which in your case it is not), encrypt both the username and password. If you encrypt both, encrypt them as one encryption run, e.g

    userAndPass=(user+":"+pass);
    encryptInit();
    encrypt(salt);
    encrypt(userAndPass);
    cipherText=encryptFinal();

    and store the singular blob, so that there is less occurrence of short cipher texts, which are easier to break, and the username further salts the password.

PS: I don't program in PHP so cannot comment on suitable crypto s/w in that environment.


You'll need to look into good 2 way cryptographic methods, and my general rule of thumb is:

If you implement your own cryptographic code you will fail.

So, find a good implementation that is well verified, and utilize that.

There is probably some good info here:

http://phpsec.org/library/


Check this library: PECL gnupg it provides you methods to interact with gnupg. You can easily encrypt and decrypt data, using safe public-key cryptographic algorithms.