-1

A client I am building a website for uses password / promo codes for their "Members Only" section, allowing members to gain access to special content. I am storing said passwords via MySQL, encrypted using sha1.

The client needs to see these passwords in the administrator control panel as plain-text. Obviously this is not an option using sha1.

What's the trade-off when it comes to encrypting passwords in the database, vs storing plain text? Should I simply store them in the database as plain-text, and just salt them in post?

What's the best method for having the ability to show plain-text passwords while maintaining a decent level of security?

mrtwidget
  • 83
  • 2
  • 9
  • 2
    http://stackoverflow.com/questions/2283937/how-should-i-ethically-approach-user-password-storage-for-later-plaintext-retrie – jraede Apr 30 '13 at 05:17
  • You could use an encryption algorithm (not an hashing function like sha1), they're reversable – Damien Pirsy Apr 30 '13 at 05:18
  • I like this idea @DamienPirsy, although I have little experience with (custom?) algorithms. The "passwords" I speak of will be used by multiple members at once, sent out via a mailing list, etc. – mrtwidget Apr 30 '13 at 05:26

6 Answers6

3

Don't display the password. Just provide the client with the ability to log in as the other users (I assume that's why they need the passwords?) perhaps on a page that itself is protected by a password known only the client.

Explosion Pills
  • 176,581
  • 46
  • 285
  • 363
  • +1 Find out why your client wants this for, and give them another way to do what they want to do. They shouldn't need to see their user's passwords - nor should they be allowed to, for it could lead to privacy breaches into their customers' accounts elsewhere. – doppelgreener Apr 30 '13 at 05:26
  • The client creates promo codes that are emailed to many members at once. This code (password) is used on the website to access special content. The password must be visible via the admin control panel for the client's reference. – mrtwidget Apr 30 '13 at 05:30
  • 1
    @mrtwidget I presume you're talking about something completely separate to a username/password login. Wow, that definitely needs to be clearer, because that is not a password at all. In fact, why are you bothering to encrypt it? – doppelgreener Apr 30 '13 at 05:48
2

You should explain to your client WHY it is imperative that they don't have access to the passwords. So many things can go wrong. Stolen DB, rogue user, missed SQL injection attack, that its just not worth the risk.

  • Member passwords only allow access to the member content. No sensitive information is passed to the regular members. – mrtwidget Apr 30 '13 at 05:33
1

This can do it.

<?php
    # --- ENCRYPTION ---

    # the key should be random binary, use scrypt, bcrypt or PBKDF2 to
    # convert a string into a key
    # key is specified using hexadecimal
    $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");

    # show key size use either 16, 24 or 32 byte keys for AES-128, 192
    # and 256 respectively
    $key_size =  strlen($key);
    echo "Key size: " . $key_size . "\n";

    $plaintext = "This string was AES-256 / CBC / ZeroBytePadding encrypted.";

    # create a random IV to use with CBC encoding
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

    # use an explicit encoding for the plain text
    $plaintext_utf8 = utf8_encode($plaintext);

    # creates a cipher text compatible with AES (Rijndael block size = 128)
    # to keep the text confidential 
    # only suitable for encoded input that never ends with value 00h
    # (because of default zero padding)
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
                                 $plaintext_utf8, MCRYPT_MODE_CBC, $iv);

    # prepend the IV for it to be available for decryption
    $ciphertext = $iv . $ciphertext;

    # encode the resulting cipher text so it can be represented by a string
    $ciphertext_base64 = base64_encode($ciphertext);

    echo  $ciphertext_base64 . "\n";

    # === WARNING ===

    # Resulting cipher text has no integrity or authenticity added
    # and is not protected against padding oracle attacks.

    # --- DECRYPTION ---

    $ciphertext_dec = base64_decode($ciphertext_base64);

    # retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
    $iv_dec = substr($ciphertext_dec, 0, $iv_size);

    # retrieves the cipher text (everything except the $iv_size in the front)
    $ciphertext_dec = substr($ciphertext_dec, $iv_size);

    # may remove 00h valued characters from end of plain text
    $plaintext_utf8_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,
                                         $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

    echo  $plaintext_utf8_dec . "\n";
?>

Source: http://www.php.net/manual/en/function.mcrypt-encrypt.php

Prashanth
  • 1,164
  • 2
  • 11
  • 27
1

You can use a two way encryption for storing and displaying the password. mcrypt_encrypt() and mcrypt_decrypt. Look at this question Simplest two-way encryption using PHP

Community
  • 1
  • 1
Preetam
  • 608
  • 6
  • 13
1

Don't do this. Find an alternate route.

If your client wants to see their user's passwords for whatever reason, ask them why they want to see those passwords, and what they'd do if they had those passwords - then provide them with an alternate, direct means of doing that, which never involves having to know what the user's password is.

No matter how innocent or minor your client's use might be, most people reuse their passwords everywhere. Your client might reason it that they only know the user's password for their own system, but this means they probably now know the user's password for everything - email, financial services like internet banking, and so on.

All it would take is one malicious employee and a user's account is breached elsewhere on the internet. That could be quite the legal quagmire, in addition to the fact someone's privacy got breached.

Find an alternative. Don't display user's passwords in plain text, ever.

doppelgreener
  • 5,752
  • 8
  • 42
  • 59
  • Absolutely agree with this answer. Additionally you should change to a slow key-derivation function like BCrypt, algorithms from the SHA-* family are ways too fast to hash passwords. – martinstoeckli Apr 30 '13 at 06:41
0

It was stored using SHA1 so it cannot be retrieved in cleartext because SHA1 is a one-way hash. You can't convert it to original form. http://php.net/manual/en/function.sha1.php

So either you can go for md5 format or simply store them in the database as plain-text, and just salt them in post

Roy
  • 42
  • 2