6

I'm working on creating basic password security on a medium size PHP CodeIgniter website. I need to start encrypting password that are being saved into a database. User passwords can be inserted using different methods including CSV import or an individual sign up approach.

Therefore I just want to know at what is the correct level in a MVC system where a password should be encrypted?

tereško
  • 58,060
  • 25
  • 98
  • 150
GrayB
  • 1,010
  • 8
  • 22

2 Answers2

3

The only time you need to perform this function is when adding a new user or updating the password for an existing user. Both of these functions should be performed by the User model. For example, something like:

$user = new User();
$user->setName('...');
$user->setPassword('...');
$user->save();

or:

$user = User::find('...');
$user->setPassword('...');
$user->save();

In this example, the setPassword() method would do the actual encryption.

Also, think of it this way -- it shouldn't be possible to get an unencrypted password into the system. So, you make the User model the only way to interact with users, and have it transparently encrypt all passwords given to it.

Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • Followup question: loading information from the database into this User class, would you be creating a new method for loading the already encrypted password field? – GrayB May 31 '12 at 15:53
  • No, its no different than loading any other field, like username or email address. The database stores the encrypted form of the password, and that's what you'll get back when you call $user->getPassword(). The unencrypted form is not stored anywhere, ever. – Alex Howansky May 31 '12 at 18:49
  • My comment was uncleared, my question was about using the setPassword method. If I'm fetching information from the database, I will be getting the encrypted password, therefore using the setPassword($row->password) will encrypt an already encrypted password. So I'm presuming I should just make an additional method setPasswordFromDB where I do not encrypt it. Does that sound like a proper solution? – GrayB May 31 '12 at 19:00
  • No. `setPassword()` is a public method. Your method to hydrate the object from the database should be private and only ever invoked indirectly (like via `find()`) -- and thus would probably just set a protected attribute directly. For example: `$this->password = ` – Alex Howansky May 31 '12 at 19:27
0

It all depends on how you store your passwords.

I usually do:

  1. Create a user with the password field set to nothing (not null).
  2. Insert the user into the database, thus generating the new UserID.
  3. Use the newly inserted UserID, plus some extra salt to generate the Password and store.

If you didn't used the UserID or a runtime generated (i.e. on insert) salt, then you can insert and encrypt the password at the same time.

Edit...

Sorry, I've inherited your use of Encrypt, however for a password, you "should" only ever HASH a password.

A simple example is:

md5(md5(UserID).md5('Password'))

Then, when the user types in their email/username and password, you simply need to so:

select * from User where Username = 'myusername' and Password = md5(concat(md5(UserID), md5('Password')))

instead of decrypting the password.

Gavin
  • 6,284
  • 5
  • 30
  • 38