Safe way to store decryptable passwords

2019-04-07 00:22发布

问题:

I'm making an application in PHP and there is a requirement that it must be possible to decrypt the passwords in order to avoid problems in the future with switching user database to different system. Consider that it's not possible to modify this future system's password method and I need plain text passwords in order to have the passwords generated.

The plan is to encrypt the user's password with a public key that is stored on the server. Authentication is done by encrypting the input and comparing the results. There is NO decryption done. The private key capable of the decryption is stored off-site for later usage.

What encryption/decryption algorithm would you suggest? Are the encrypted passwords still as safe as hashing (MD5/SHA1) when you consider the private key is not available to the attacker?

回答1:

I'll rephrase Jammer's approach -

  1. Generate a public/private key pair. Hard-code the public key on your webserver. Store the private key in a physical bank locker, outside the reach of webserver/database/any developer.
  2. When user registers, encrypt password + salt using public key. This step is identical to using a hash algorithm. Store the encrypted password + salt in the database.
  3. When you want to verify the password, encrypt it again, and compare it to the value stored in the database.

If an attacker gets the database, he can't decrypt the passwords because he doesn't have the private key. He cannot get the private key because it is in a bank vault outside his reach. Two identical passwords will still be stored differently in the database because of the salt.

I don't recommend using the above approach because at any point of time in the future someone could abuse the private key and get access to all passwords.

But if you guarantee that the private key will always remain private, then I don't see a technical flaw.

I could be wrong, of course.



回答2:

Don't decrypt the password. If you need to change the password system in the future, add a field called storage_type (or whatever).

Then, when you need to change the passwords, you will check if it's an old password. If it is, next time they login, you can change the password encoding. Otherwise, login with the new system.



回答3:

Being able to decrypt the passwords is a bad idea (and there's probably not any way of doing it that would be much better than storing them unencrypted). It sounds like your main problem is being able to use the passwords if you change your storage method. Just do what Linux does, store how you're hashing the password with the password. So for example $1$salt$hash is MD5. That way, if you decide to change how passwords are stored, you can still check against the old passwords (and if someone logs in correctly, you can update their password with the new hash).



回答4:

The only problem I see is that most public-private key encryption code out there will encrypt a symmetric key using the public key, and rely on the private key decrypting that, then use the symmetric key to encrypt the message.

You want to use the public key to directly encrypt the password+salt.

So attacks against your system boil down to:

  1. Attacks against general public/private key encryption
  2. Attacks against your private key store.


回答5:

For most applications it is more than sufficient to store SHA-1 hashes of passwords.

Yes, there are known collisions in most hashing algorithms, but that doesn't imply an actual attack vector. Especially when you're salting the hashes.

For your salt: Store it in a configuration file that is not accessible from the outside but can be read by your PHP installation.